2010-03-26 20 views
23

Po prostu staram się wciąż zrozumieć zasady IOC.IOC - Czy klasy użytkowe ze statycznymi metodami pomocniczymi powinny być połączone z IOC?

Q1: Metody statyczne - Czy należy używać klas ze statycznymi metodami pomocniczymi z IOC?

Na przykład, jeśli mam klasę HttpUtils z szeregiem metod statycznych, czy powinienem próbować przekazać ją do innych klas logiki biznesowej za pośrednictwem IOC?

śledź na pytania do tego może być:

Q2: Singletons - Co o takich rzeczach logowania gdzie można zazwyczaj uzyskać do niego dostęp za pośrednictwem Logger.getInstance() typ połączenia. Czy normalnie pozostawiłbyś to tak, jak jest, a NIE używał IOC do wstrzykiwania loggera do klas biznesowych, które go potrzebują?

Q3: Klasy statyczne - Tak naprawdę nie używałem tej koncepcji, ale czy istnieją jakieś wskazówki, jak zwykle radzić sobie z tym, jeśli przechodzisz do podejścia opartego na IOC.

Z góry dziękuję.

Odpowiedz

30

Zabawną rzeczą w IoC jest to, że obiekty napisane w stylu są generalnie oddzielone od tych szczegółów.

Użyjmy klasę użytkową jako przykład:

public class HttpUtils 
{ 
    public static void DoStuff(int someValue) 
    { 
     // ... 
    } 
} 

W non-IoC-koncentruje aplikacji, można użyć tej metody bezpośrednio:

public class Foo 
{ 
    public int Value { get; set; } 

    public void DoStuff() 
    { 
     HttpUtils.DoStuff(Value); 
    } 
} 

jednak, że pary definicji DoStuff bezpośrednio do jego realizacji. IoC dąży do rozwodu te rodzaje informacji, więc zamiast tego zdefiniować działanie na własną rękę:

public interface IDoesStuff 
{ 
    void DoStuff(int someValue); 
} 

Następnie opuszczamy pokój w Foo na realizację zmienić:

public class Foo 
{ 
    private readonly IDoesStuff _doesStuff; 

    public Foo(IDoesStuff doesStuff) 
    { 
     _doesStuff = doesStuff; 
    } 

    public int Value { get; set; } 

    public void DoStuff() 
    { 
     _doesStuff.DoStuff(Value); 
    } 
} 

ten oddziela Foo od HttpUtils. Implementator koncepcji DoStuff jest teraz szczegółem konfiguracji, a nie nieodłączną zależnością (jak to jest w przypadku metody statycznej).

Należy zauważyć, że Foo nie ma pojęcia, czy jego IDoesStuff jest singleton, czy nie. To całe życie to , a także szczegół konfiguracji, a nie nieodłączny szczegół Foo.

Podsumowując, IoC i static są generalnie sprzeczne, ponieważ IoC promuje zmianę, a static, z definicji, zapobiega temu. Zadeklaruj swoje zależności w swoich konstruktorach, a zobaczysz, że prawie nigdy nie używasz funkcji static.

+0

dzięki Bryan - Czy to oznacza, że ​​może zaistnieć więcej problemów związanych z konstruowaniem przez IOC rzeczy (np. Rejestratora) za każdym razem? Również dla klas typu utils, zastanawiam się czy to spowoduje, że refaktoryzacja stanie się trudniejsza, gdy będziesz refaktoryzować swoje funkcje pomocnicze wśród swoich klas pomocniczych? (Używam sam ReSharper) - dziękuję – Greg

+0

Większość kontenerów IoC pozwala na pewien zakres. Rozumiem przez to, czy wskazujesz, czy obiekt jest tworzony za każdym razem (fabryka), tworzony raz na kontekst (jednostka pracy), lub raz na aplikację (singleton). Oznacza to, że można zarejestrować rejestrator tak, aby był tworzony tylko jeden raz. –

+2

Ostatecznie chcesz wyeliminować klasy narzędziowe. Każda metoda na każdej z tych klas ma takie same problemy z sprzężeniem, jak powyższa metoda 'HttpUtils.DoStuff'. Z tego powodu nie chcesz wymagać, aby * dowolny * kod zależał bezpośrednio od "statycznych" członków. Zamiast tego, weź treść 'HttpUtils.DoStuff', umieść ją za' IDoesStuff' i usuń metodę całkowicie z 'HttpUtils'. Teraz każda klasa, która mogła nazwać metodę statyczną, może zamiast tego zaakceptować 'IDoesStuff' w swoim konstruktorze. Viola: nie ma potrzeby używania klasy narzędziowej! –

6

Kontener IoC jest zwykle przydatny do wstrzykiwania obiektu ze stanem; lub klas lub interfejsów, które mają więcej niż jedną implementację, nawet jeśli druga implementacja jest próbna do celów testowych. Jeśli żadna z nich nie jest prawdziwa, nic nie zyskujesz poprzez wstrzyknięcie.Najczęstszym idiomem w dzisiejszych czasach jest poprowadzenie twojej klasy przez interfejs, który zarówno realna, jak i fałszywa implementacja może zaimplementować.

1) Metody statyczne dla klas pomocniczych - Nie, te często nie są wstrzykiwane przez IoC. Zazwyczaj są to bezpaństwowe narzędzia.

Aby użyć bardzo prostego przykładu, nie potrzebujesz dwóch wersji narzędzia o nazwie StringUtils.Reverse(). Potrzebujesz tylko jednego i możesz łatwo pisać testy wokół niego, ponieważ nie ma on stanu lub zależności, więc nie ma absolutnie żadnej korzyści z kpiny z niego. Przykład testu:

string reversedString = StringUtils.Reverse("input"); 
Assert.AreEqual("tupni", reversedString) 

Jeśli narzędzie nie jest tak naprawdę bezpaństwowcem (np zależy HttpContext.Current), wówczas należy dokonać zależność wyraźny przez wstrzykiwanie go, a nie czyni narzędzie statyczne.

2) Singletons: Często tak, wstrzykiwane są pojedynczo. Ale dobrą rzeczą w IoC jest to, że mniej martwisz się o to, czy jest tylko jedno z czegoś, czy nie. Zyskasz elastyczność w instancji za pomocą IoC. Decyzja o tym, że dany typ jest pojedyncza lub nowa, za każdym razem staje się częścią konfiguracji kontenera IoC i nic więcej w kodzie nie musi się zmieniać.

Tak więc singleton-stop przestaje być osobnym problemem, który musi zostać zakodowany w klasie (a klasy mające wiele obaw, gdy nie muszą, są złe) i stają się przedmiotem kontentu IoC. Nie kodujesz klasy "jako singleton" z niczym specjalnym jak prywatny konstruktor i metodą public static GetInstance(), po prostu kodujesz ją dla głównego problemu, podczas gdy konfiguracja kontenera IoC określa, czy jest to singleton czy nie, czy gdzieś pomiędzy, jak jedna instancja na wątek.

3) Klasy statyczne - są naturalnym domem dla metod statycznych. Rozważ zastosowanie metod rozszerzania metod statycznych w stosownych przypadkach. Nie możesz wstrzykiwać tych klas, ponieważ nie możesz ich utworzyć. Używanie klas statycznych powoduje, że kod proceduralny nie jest obiektowy. Nie jest to zła rzecz dla małych metod pomocniczych, ale jeśli większość kodu jest taka, to nie korzystasz z potężnych funkcji OO platformy .Net.

2

Metody statyczne z definicji nie potrzebują instancji. DI/IOC ma na celu zaspokojenie interfejsów z konkretnymi klasami i biorąc pod uwagę, że twoja klasa statyczna wraz z jej statycznymi metodami z definicji nie może implementować interfejsu lub rozszerzać klasy, pytanie to nie ma sensu. Nie ma sensu przekazywać klasy pomocnika, ponieważ nie trzeba instancji, aby używać metod statycznych. Twój kod zawsze będzie wykonywał te same statyczne metody helperów, nawet bez instancji.

W aplikacji zasilanej z IOC/DI zdefiniowano by interfejsy i przynajmniej jedną implementację. Wszystko zależy od zarządzania instancjami i ich zależnościami.

0

Dylemat pojawia się, gdy klasy narzędziowe, na przykład, potrzebują bazy danych dostępu. Podczas gdy db accessor wymaga Ioc, więc klasa narzędziowa musi używać Ioc jako, więc nie może być statyczna.

Ale naprawdę chcę, aby klasa użyteczności była statyczna, tak łatwa do konsumpcji. Nie chcę zapełniać konstruktorów dla każdej klasy konsumpcji, która potrzebuje klas użytkowych.

Samo spożywanie klas może nawet nie wymagać dostępu do db. Więc nie chcę wstrzykiwać akcesora db i przekazywać go do klas narzędziowych.

Zgadnij, nie ma na razie idealnego rozwiązania.Pewnego dnia mam nadzieję, że pójdziemy o krok dalej, oprócz zastrzyku konstruktora/własności, istnieje "globalny kontekst wtrysku/konfiguracji" lub "iniekcja statyczna", zastosowanie Ioc poza tworzeniem obiektu.

Zastanów się, dlaczego nie?

+0

Czy to jest odpowiedź, czy tylko komentarz do pytania? –