Jestem nowy w zastrzykach zależności i mam kilka pytań na temat tego, jaki styl powinienem zastosować w swoich aplikacjach. Właśnie przeczytałem Inversion of Control Containers i wzorzec Dependency Injection autorstwa Martina Fowlera, ale nie mogę dostrzec praktycznej różnicy między konstruktorem, seterą i iniekcją interfejsu.
Wydaje mi się, że powody używania jednego nad drugim to tylko kwestia czyszczenia kodu i / lub przejrzystości. Jaka jest różnica? Czy są jakieś zalety lub wady korzystania z jednego nad drugim, czy jest to właśnie to, co powiedziałem wcześniej?
Moim zdaniem wstrzyknięcie konstruktora jest najbardziej intuicyjne ze wszystkich, podobnie jak wstrzyknięcie interfejsu . Z drugiej strony wstrzykiwanie setera jest terminem średnim, ale czy powinieneś być w stanie zmienić instancję obiektu zależności, który początkowo wstrzyknąłeś? Czy ten styl wstrzykiwania gwarantuje, że obiekt, który potrzebuje zależności, zawsze będzie ją wstrzykiwał? Nie wierzę, ale proszę, popraw mnie, jeśli się mylę.
Odpowiedzi:
Constructor Injection ma tę zaletę, że wyraźnie określa zależność i zmusza klienta do zapewnienia wystąpienia. Może także zagwarantować, że klient nie będzie mógł później zmienić instancji. Jednym (możliwym) minusem jest to, że musisz dodać parametr do swojego konstruktora.
Zaletą Setter Injection jest to, że nie wymaga dodawania parametru do konstruktora. Nie wymaga również od klienta ustawienia instancji. Jest to przydatne w przypadku zależności opcjonalnych. Może to być również przydatne, jeśli chcesz, aby klasa utworzyła domyślnie np. Prawdziwe repozytorium danych, a następnie w teście możesz użyć setera do zastąpienia go instancją testową.
Interfejs Iniekcji , o ile wiem, nie różni się niczym od wtrysku setera. W obu przypadkach (opcjonalnie) ustawia się zależność, którą można zmienić później.
Ostatecznie jest to kwestia preferencji i tego, czy wymagana jest zależność, czy nie . Osobiście używam zastrzyku konstruktora prawie wyłącznie. Podoba mi się, że wyraźnie określa zależności klasy, zmuszając klienta do zapewnienia wystąpienia w konstruktorze. Podoba mi się również to, że klient nie może zmienić instancji po fakcie.
Często moim jedynym powodem przekazania dwóch osobnych implementacji jest testowanie. W produkcji mogę zdać
DataRepository
, ale w testach zdałbymFakeDataRepository
. W takim przypadku zwykle dostarczam dwa konstruktory: jeden bez parametrów, a drugi akceptującyIDataRepository
. Następnie w konstruktorze bez parametrów wywołam połączenie z drugim konstruktorem i przekażę komendęnew DataRepository()
.Oto przykład w języku C #:
Jest to znane jako zastrzyk uzależnienia od ubogich. Podoba mi się, ponieważ w kodzie klienta produkcyjnego nie muszę się powtarzać, mając kilka powtarzających się instrukcji, które wyglądają
Nadal jednak mogę przekazać alternatywną implementację do testowania. Zdaję sobie sprawę, że w DI Poor Man zapisuję na stałe swoją zależność, ale jest to dla mnie do zaakceptowania, ponieważ do testów używam głównie DI.źródło
Różnice między wtryskiem konstruktora i setera są już odpowiednio opisane powyżej, więc nie będę ich dalej omawiać.
Wstrzykiwanie interfejsu jest bardziej zaawansowaną formą wstrzykiwania, która jest przydatna, ponieważ pozwala określić zależność w momencie jej użycia, a nie podczas inicjalizacji obiektu, który będzie go używał. Umożliwia to szereg przydatnych opcji:
Zależność można określić inaczej niż obiekt, do którego jest wstrzykiwany; na przykład można użyć wstrzykiwania interfejsu w celu zapewnienia obiektu, dla którego istnieje jeden na sesję użytkownika lub na wątek do globalnego singletonu. Za każdym razem, gdy obiekt potrzebuje zależności, wywoła metodę gettera udostępnianą przez środowisko, co może zwrócić różne wyniki w zależności od sytuacji, w której jest wywołane.
Pozwala na leniwą inicjalizację - nie ma potrzeby inicjowania zależności, dopóki nie zostanie ona użyta
Umożliwia ładowanie zależności z kopii w pamięci podręcznej, gdy istnieją, lub ponowne inicjowanie, gdy nie istnieją (np. Za pomocą
SoftReference
Java).Oczywiście takie zaawansowane techniki mają swoje wady; w tym przypadku głównym problemem jest to, że kod staje się mniej przejrzysty (klasy używane w kodzie stają się abstrakcyjne i nie ma oczywistej konkretnej implementacji, co może być mylące, jeśli się do niego nie przyzwyczaisz) i stajesz się bardziej zależny na platformie wstrzykiwania zależności ( oczywiście nadal możliwe jest tworzenie instancji obiektów ręcznie, ale jest to trudniejsze niż w przypadku innych stylów wstrzykiwania).
źródło