2015-08-05 18 views
7

Ogólnie rzecz biorąc, moje zależności są pobierane z interfejsów, ale będę używał tylko jednej konkretnej implementacji podczas użycia bez testowania. Na przykład, gdybym napisać FooService:Wstrzykiwanie zależności: co utraciłeś podczas tworzenia instancji klas w konstruktorze bez parametrów?

public class FooService : IFooService 
{ 
    private readonly IBarDependency _barDependency; 

    public FooService(IBarDependency barDependency) 
    { 
     this._barDependency = barDependency; 
    } 

    public FooService() : this (new BarDependency()) 
    { 
     // nothing to do here 
    } 

    . . . // code goes here 
} 

Teraz puryści mają tendencję do gasp w horror, bo instancja konkretnej klasy w konstruktora bez parametrów. W przeszłości wzruszyłem ramionami, ponieważ wiem, że jedyną sytuacją, w której nie będę korzystał z konkretnej klasy, jest to, że jestem jednostkowym testerem i kpiną z zależności.

Mimo że łączy w sobie klasę FooService z klasą BarDependency, nie jest to połączenie ciasne; te klasy i interfejsy również istnieją w tym samym zespole, więc nie wydaje mi się, że tracę tu dużo lub maluję się w kącie. Nadal mogę łatwo przetestować klasę FooService, nie uzyskując kodu, którym nie można zarządzać, tylko za pomocą konstruktora, który pozwala mi przekazywać fałszywe interfejsy.

Pytanie brzmi: co jest tutaj zagrożone? Co tracę przy tego typu wzorach, które warto dodać do kontenera IoC?

+0

Używam tego samego podejścia w małych projektach. DI i inne reguły "robienia tego dobrze" zazwyczaj sprawiają, że małe projekty są nazbyt skomplikowane. Oczywiście, przynosi wiele korzyści, ale nie zawsze jest to warte kłopotów. –

Odpowiedz

6

Zarządzanie na całe życie, na przykład. Być może używasz BarDependency w całym kodzie i chcesz, aby tylko jedna instancja przeżyła. Nie można tego zrobić, jeśli każdy użytkownik tworzy własne instancje.

Musisz również znaleźć wszystkie zastosowania new BarDependency(), jeśli kiedykolwiek chcesz zastąpić je new NewBarDependency().

Kontener rozwiązuje oba problemy, ponieważ wówczas konfigurujesz instancję i cykl życia obiektów w jednej metodzie, a mianowicie przy konfiguracji kontenera.

+0

Więc sugerujesz, że pojemnik IoC jest lepiej dopasowany do wstrzykiwania Singleton? To ma sens. –

+1

Tak, można użyć okresu istnienia "raz na AppDomain", więc nie potrzebujesz pojedynczych lub statycznych klas. – CodeCaster

1

To, co można stracić bez wstrzykiwania zależności, to możliwość centralizacji wszystkich aspektów zarządzania zależnościami. Wizualizacja wykresu zależności i zarządzanie cyklami życia twoich obiektów jest łatwiejsze, gdy masz wszystkie informacje w jednym miejscu, zamiast rozproszone po całym kodzie.

Konkretnym przykładem byłoby zastąpienie domyślnej implementacji IBarDependency używanej w niektórych, ale nie we wszystkich klasach. Rozumowanie, które z nich należy zastąpić, jest znacznie łatwiejsze, jeśli wszystkie zależności są połączone w tym samym pliku lub grupie plików.

2

To zależy, ale jeśli FooService musi być dostępny dla jakiegoś innego programisty, zależność od BarDependency będzie w zasadzie ukryta. Moim zdaniem nie tylko szyderstwo i testowanie jest powodem stosowania zastrzyku zależności, ale także wyraźne wskazanie, czego używa się w klasach i jakie są one niezbędne do prawidłowego działania. A może jestem za dużo purystów, ale gdy taki wzór jest w porządku, łatwo można pójść dalej i zakończyć się całkowicie ściśle powiązanym i trudnym do utrzymania kodem.