W jaki sposób wtrysk zależny zwiększa sprzęganie?

32

Na stronie Wikipedii dotyczącej wstrzykiwania zależności, sekcja wad mówi:

Wstrzykiwanie zależności zwiększa sprzężenie, wymagając od użytkownika podsystemu zaspokojenia potrzeb tego podsystemu.

z linkiem do artykułu przeciw wstrzykiwaniu zależności .

Wstrzykiwanie zależności powoduje, że klasa korzysta z interfejsu zamiast konkretnej implementacji. To powinno skutkować zmniejszeniem sprzężenia , prawda?

czego mi brakuje? W jaki sposób wstrzykiwanie zależności zwiększa sprzężenie między klasami?

BЈовић
źródło
2
Nie jestem pewien, kto napisał tę listę wad, ale wziąłbym ją z odrobiną soli. Na przykład widziałem, że DI zmniejsza rozmiar podstawy kodu o 2/3, eliminując tonę zbędnego kodu konfiguracji.
Rob
@RobY Najczęściej używałem fabryki do wstrzykiwania zależności, a moim doświadczeniem jest to, że zwiększa rozmiar kodu, ale upraszcza testowanie.
BЈовић
Spróbuj użyć alternatywy, takiej jak rejestr lub przekazywanie kontekstu;) Albo kod, który tworzy instancję obiektów, a następnie pobiera ich właściwości z config. Głównie mówię o różnicy między teraz a 15 lat temu.
Rob
Powiązane: stackoverflow.com/a/9503612/264697 . Odpowiedź Marka Seemanna wyjaśnia, w jaki sposób ogólne sprzężenie jest zmniejszane przy użyciu wstrzykiwania zależności.
Steven

Odpowiedzi:

42

Więc czego mi brakuje?

Wstrzykiwanie zależności zmniejsza sprzężenie między klasą i jej zależnością. Ale zwiększa to sprzężenie między klasą a jej konsumentem (ponieważ konsument potrzebuje więcej informacji, aby ją utworzyć) oraz zależnością i jej konsumentem (ponieważ konsument musi znać zależność, której należy użyć).

Bardzo często jest to dobry kompromis. Klasa nie powinna znać szczegółów na temat swoich zależności poza interfejsem, a na aplikacji powinna spoczywać powiązanie określonych fragmentów kodu.

Telastyn
źródło
Racja, sprzężenie zmniejsza się w jedną stronę, a zwiększa w drugą.
Paul Draper
Ale konsument go nie tworzy; o to właśnie chodzi.
Casey
@emodendroket - Eh? Odwrócenie kontroli pozwala konsumentowi go nie tworzyć. Wstrzykiwanie zależności jest prostopadłe do tego.
Telastyn
Robisz rozróżnienie, którego nie znam, ponieważ zwykle terminy są używane zamiennie.
Casey
22

Załóżmy, że masz podsystem Szależny od połączenia z bazą danych D. Bez wstrzykiwania zależności istnieje względnie ścisłe sprzężenie między Si D, ponieważ Smusi wiedzieć zarówno, jak używać, Djak i jak go tworzyć. Reszta systemu może jednak być błogo nieświadoma tej zależności między Si D.

W przypadku wstrzykiwania zależności sprzężenie Si Dstaje się luźniejsze, ponieważ usuwasz z Swiedzy, jak utworzyć D. Spo prostu musi wiedzieć, jak go używać. Zwiększone ogólne sprzężenie wynika z faktu, że inne części systemu muszą teraz wiedzieć Di być może jak je utworzyć. Zakres tego wzrostu sprzężenia zależy od tego, w jaki sposób Dwstrzykiwana jest zależność od S:

  • Dzięki iniekcji konstruktora twórca Spotrzebuje zależności Di być może wiedzy, jak ją stworzyć.
  • W przypadku wstrzykiwania na poziomie metody każdy wywołujący metodę, za Spomocą której Dwstrzykiwany jest zastrzyk, potrzebuje zależności Di być może wiedzy, jak go stworzyć.

W obu przypadkach liczba klas, które zależą od Dwzrostu, i wiedza na temat tworzenia Dwciąż musi znajdować się gdzieś w systemie. To powoduje ogólny wzrost sprzężenia.

Bart van Ingen Schenau
źródło
Ok, ma sens zastrzyk konstruktora i setera. Ale jeśli używa się wzorca fabrycznego lub strategicznego, kreacja jest tam przenoszona, a klasa używa tylko wstrzykiwanego obiektu. Czy też nie jest to wstrzyknięcie zależności (tylko odwrócenie kontroli)?
BЈовић
Nawet w przypadku wstrzyknięcia fabrycznego twórca Smusi dostarczyć fabrykę D, co oznacza, że ​​musi wiedzieć, które Szastosowania D(lub przynajmniej pewien jej interfejs).
Idan Arye
7

Zdecydowanie nie zgadzam się, że zwiększa to sprzężenie.

Bez wstrzykiwania zależności masz ścisłe połączenie między podsystemem a konkretną implementacją zależności.

Po wstrzyknięciu zależności odłączyłeś podsystem od implementacji zależności.

Argumentowanie, że zwiększa sprzężenie między konsumentem a tym podsystemem, jest BARDZO wątpliwe, ponieważ sugeruje, że konsument jest teraz ściśle powiązany z zależnością wymaganą przez podsystem. Oznacza to tylko, że piszesz ściśle powiązany kod, który łączy klienta z zależnością. Idealnie WSZYSTKO twój kod jest oddzielony.

Wtrysk Konstruktora:

Rozdzielczość zależności jest obsługiwana przez pojemnik wstrzykiwania zależności lub fabrykę. Konsument może uzyskać konkretną implementację podsystemu z pojemnika wstrzykiwania zależności lub z fabryki.

Konsument nie musi wiedzieć, jak wygląda konstruktor podsystemu. Nie ma sprzężenia z zależnością od podsystemu.

Metoda wtrysku:

To samo co wstrzykiwanie konstruktora, tyle że teraz konsument musi uzyskać konkretny przykład zależności od kontenera lub fabryki (lub nawet wstrzyknąć metodę / konstruktor) i wstrzyknąć go do metody. Znowu konsument nie jest powiązany z konkretnym wdrożeniem zależności.

TL; DR Najgorszym przypadkiem wstrzykiwania zależności w podsystemie jest przeniesienie sprzężenia na kod konsumenta. NIE MA OGÓLNEGO ZWIĘKSZENIA SPRZĘGŁA.

Najlepszym przypadkiem jest to, że wszystkie systemy są teraz luźno połączone, a wstrzykiwanie zależności jest kontrolowane przez pojemniki lub fabryki wstrzykiwania zależności.

Jastrząb
źródło