Jakie są korzyści z używania Dependency Injection i IoC Containers?

62

Planuję porozmawiać na temat Dependency Injection i IoC Containers i szukam dobrych argumentów za jego użyciem.

Jakie są najważniejsze zalety korzystania z tej techniki i tych narzędzi?

Andy Lowry
źródło
1
Zobacz tutaj i tutaj odpowiedzi StackOverflow i tutaj dobrego pełnego artykułu na MKOl. A jeśli chcesz argumentów przeciwko temu, zajrzyj tutaj na SO.
Jesse C. Slicer
14
nie być tyłkiem ... ale jeśli nie wiesz, dlaczego należy stosować DI / MKOl, dlaczego o tym mówisz? przegrać zakład? ;-)
Steven A. Lowe
2
@ Steven, jego szef mógł go o to poprosić.
1
@ Steven, używam już DI cały czas (niektórzy mówią zbyt często :-D), szukam tylko dobrych argumentów, aby skłonić innych ludzi do korzystania z niego.
Andy Lowry,
2
Ludzie rzadko mówią o nadużywaniu DI. Jeśli opóźnisz każdą decyzję, utworzysz OO odpowiednik kodu spaghetti. Spójne projektowanie wymaga, aby w pewnym momencie podjęto prawdziwą decyzję.
Macneil,

Odpowiedzi:

47

Najważniejsze jest dla mnie ułatwienie przestrzegania zasady pojedynczej odpowiedzialności .

DI / IoC ułatwia mi zarządzanie zależnościami między obiektami. To z kolei ułatwia mi przełamanie spójnej funkcjonalności we własnej umowie (interfejsie). W rezultacie mój kod został znacznie bardziej zmodularyzowany, odkąd dowiedziałem się o DI / IoC.

Innym rezultatem tego jest to, że znacznie łatwiej mogę przejść do projektu, który obsługuje zasadę otwartego i zamkniętego . Jest to jedna z najbardziej inspirujących technik (po testach automatycznych). Wątpię, czy mógłbym wystarczająco docenić zalety zasady otwartej i zamkniętej.

DI / IoC to jedna z niewielu rzeczy w mojej karierze programistycznej, która zmieniła grę. Istnieje ogromna różnica w jakości między kodem, który napisałem przed i po nauce DI / IoC. Podkreślę to jeszcze trochę. OGROMNA poprawa jakości kodu.

Quentin-Starin
źródło
3
Dlaczego Zasada Otwartego Zamknięcia jest tak wielką sprawą? Jeśli uważasz, że musisz zmienić interfejs API / interfejs, dlaczego nie powinieneś?
Arne Evertsson
@ArneEvertsson Posłuchaj, jak Robert C. Martin opowiada o zasadzie otwartego zamkniętego. Będziecie oświeceni.
Alternatex
@AmeEvertsson Open-Closed jest bardzo ważny, gdy Twój kod jest dostarczany (np. Jako produkt komercyjny) jako moduł do użytku dla innych, ponieważ sprawia, że ​​twój kod jest bardziej elastyczny w użyciu, bez konieczności powrotu do ciebie, aby go zmienić
James Ellis-Jones
2
DI nie ułatwia zarządzania zależnościami, ponieważ jest znacznie bardziej złożony niż zwykłe tworzenie zależności od konkretnej klasy. Zapewnia to jednak elastyczność, ale jeśli nie wykonujesz „właściwych” testów jednostkowych, elastyczność ta często nie będzie potrzebna. Obie opisane kluczowe zalety dotyczą również Service Locator, co jest prostsze.
James Ellis-Jones,
1
Głosowałem tę odpowiedź wiele lat temu; oto kilka uwag: 1) W praktyce szerokie stosowanie DI zwykle działa przeciwko SRP, ponieważ programiści po prostu dodają metody do swoich wstrzykiwanych „kontrolerów”, „usług”, „DAO” itp. zamiast tworzyć nowe klasy dla nowa funkcjonalność. Tak zwykle dzieje się w projektach Java i C # .NET, które używają szkieletu lub kontenera DI. 2) Zasada otwartego zamknięcia była jedynie złudzeniem Bertranda Meyera odnośnie do przydatności dziedziczenia klas (implementacji); jeśli przeszukasz go w ponad 1400 stronicowej książce, zobaczysz, co mam na myśli - to naprawdę głupie.
Rogério,
9

Przykłady, które naprawdę otworzyły mi oczy, pokazały, w jaki sposób można łatwo testować w jednostce obiekty utworzone w taki sposób. Wcześniej miałem problemy z izolowaniem obiektów na potrzeby testu jednostkowego. Często pisałem testy, by współpracować ze znacznie większym systemem. Było to naprawdę trudne, ponieważ system jako całość był znacznie mniej przewidywalny i znacznie bardziej podatny na zmiany niż poszczególne elementy.

Winston Ewert
źródło
3

Zalety zastrzyków uzależnienia to:

  1. Twój kod jest czysty i bardziej czytelny.
  2. Kody są luźno powiązane.
  3. Bardziej wielokrotnego użytku, ponieważ implementacje są skonfigurowane w pliku XML, można go używać w innym kontekście.
  4. Kod można łatwo przetestować za pomocą różnych próbnych implementacji.
Solaimani SA
źródło
1

Myślę, że rzeczywiste korzyści są bardziej polityczne niż techniczne. DI to po prostu alternatywa dla wzorca Service Locator , nic więcej. Samo w sobie nie ułatwia przestrzegania zasad takich jak SRP lub OCP ani rozłączania warstw. Inni respondenci mylą różne koncepcje i techniki, IMO.

Możesz osiągnąć te same cele w odniesieniu do wysokiej kohezji i niskiego sprzężenia za pomocą lokalizatorów usług lub po prostu poprzez bezpośrednie tworzenie zależności, gdy ma to zastosowanie (co jest przez większość czasu).

Teraz wiem, że wielu nie zgodzi się z tą opinią. Z przyjemnością omówię konkretne przykłady.

Rogério
źródło
2
Ale bezpośrednie wywoływanie lokalizatora usług lub tworzenie konkretnej zależności zwykle utrwala zależności, a przynajmniej skąd pochodzą. Wydaje się, że to pokonuje cel DI. Nadal musisz również wstrzyknąć lokalizator usług.
Matt H
Korzystanie z Lokalizatora usług nie wiąże na stałe niczego poza użyciem samej klasy Lokalizatora usług, która zwykle nie jest „wstrzykiwana”. Tworzenie instancji konkretnej klasy implementacji jest w porządku, gdy nie potrzebujesz konfiguracji zewnętrznej (na przykład programiści zwykle tworzą bezpośrednio klasę ArrayList zamiast używać DI - co byłoby przesadą).
Rogério,
1
Wspominasz o „niskim sprzężeniu”, a później mówisz, że lokalizator usług nie ma wpływu na poziom sprzężenia aplikacji. To samo dotyczy tworzenia instancji współpracowników bezpośrednio w kodzie, nie mogę wymyślić bardziej idealnego sposobu połączenia obiektu z jego zależnościami. Jak przeprowadzasz test jednostkowy obu scenariuszy? Z całym szacunkiem nie zgadzam się ze wszystkim, co powiedziałeś.
Clint Eastwood
@ Jonathan Powinieneś przeczytać artykuł, który wprowadził wtedy DI ; autor kończy stwierdzeniem, że DI i ServiceLocator są „w przybliżeniu równoważne”, z „niewielką przewagą” w przypadku tego drugiego. Ważne jest sprzężenie między komponentem a innymi komponentami, które mogą mieć wiele implementacji; ServiceLocator to usługa infrastruktury z tylko jedną implementacją, więc jest w porządku. Uwaga: Napisałem „tworzenie instancji zależności, gdy ma to zastosowanie ”; oczywiście, jeśli musisz oddzielić konfigurację od użycia, nie zrobiłbyś tego.
Rogério,
1
@Jathanathan Jeśli chodzi o testy jednostkowe, to mit, że tworzenie instancji współpracowników uniemożliwia tworzenie takich testów; istnieją dobrze znane narzędzia próbne, które izolują klasę od implementacji zależności, niezależnie od tego, czy są one wstrzykiwane, czy nie.
Rogério,
-1

Gdy do odsłonięcia obiektów wewnętrznych do celów testowania stosuje się DI, wzór został nadużyty.

Thomas-Peter
źródło
1
co rozumiesz przez „obiekty wewnętrzne” ?. w prawdziwym OOP (zauważ, że prawdopodobnie tylko 1% programistów wie, co to tak naprawdę oznacza), istnieją obiekty komunikujące się ze sobą za pomocą wysyłania komunikatów (tj. wywoływania metod). W tym sensie każdy obiekt musi ponosić jedną odpowiedzialność, nie ma „ważniejszych” obiektów niż inne ... każdy z nich ma jeden obowiązek i współpracują w celu osiągnięcia funkcjonalności zapewnianej przez cały system. Ważne jest, aby przetestować każdy obiekt w sposób izolowany, abyśmy nie przeoczyli żadnego przypadku, w tym DI jest naprawdę dobry.
Clint Eastwood
Zapomniałem.
Thomas-Peter