devstyle.pl - Blog dla każdego programisty
devstyle.pl - Blog dla każdego programisty
4 minut

Dependency Injection: z kontenerem czy bez?


22.11.2016

Dependency Injection to bardzo potężny i przydatny wzorzec projektowy. Pozwala zaprowadzić w kodzie porządek, jawnie zadeklarować powiązania między klasami i uprościć proces utrzymania kodu. Powstała cała masa narzędzi wspomagających nas w tym światłym dziele. I po co?

Akcja: BLOGvember! Post nr 17.
W listopadzie w każdy roboczy poranek na devstyle.pl znajdziesz nowy, świeżutki tekst. W sam raz do porannej kawy na dobry początek dnia.
Miłej lektury i do przeczytania jutro! :)

Kontenery

Kontenery Dependency Injection powstały, aby uprościć proces tworzenia obiektów w systemie. Mówimy im, jakie klasy wchodzą w skład systemu, a one sobie wszystkie klocki układają. Zależności między strukturami wykrywają. Drzewa zasadzają, grafy modelują. By na koniec: tworzyć instancje.

Co bardziej zaawansowane kontenery potrafią o wiele więcej. A to Aspect-Oriented Programming nam udostępnią, a to dekoratory w prosty sposób pozwolą dorzucić, a to Dispose() wywołają kiedy trzeba, a to to, a to tamto. Więcej można poczytać w poście Profesjonalne kontenery i DI: kontener.

Lata temu ludzie rzucili się na tę rodzinę narzędzi. Powstawały coraz to nowe, bardziej skomplikowane. Później, jak to często bywa, nastąpił odwrót i tendencja upraszczania całego procesu zarządzania zależnościami. Aż dotarliśmy do stanu równowagi: equilibrium. Wszyscy byli szczęśliwi.

A potem: z dev-Olimpu poleciały gromy.

Alternatywa

Po co nam dodatkowe narzędzia? Możemy to naklepać ręcznie! W każdym projekcie z osobna! Bo kontenery są trudne! I powinniśmy minimalizować liczbę zależności w projekcie!

Takie oto głosy zaczęły dobiegać z programistycznych niebiesiech. Okazało się, że na przykład Mark Seemann (autor książki “Dependency Injection in .NET”) i Greg Young (kto nie zna, ten niech pozna we własnym zakresie) wiele mają kontenerom do zarzucenia. Że to UNIKALNE (IUnikable) zło. Że niepotrzebne. Że skomplikowane.

Polecam chociażby te linki:

Argumenty przedstawiane w tych treściach na pewno nie są bezpodstawne. Ci kolesie, jak już otwierają paszczę lub siadają do klawiatury, to wiedzą co czynią. Mam tylko jeden problem: zaprezentowane remedium… zupełnie do mnie nie przemawia.

Eksperymentalnie zrealizowałem kiedyś projekt bez wykorzystania kontenera. Wszystkie zależności rzeźbiłem ręcznie. Projekt ten miał raptem kilkadziesiąt klas na krzyż (“las krzyży” vs “las klas”?), a i tak kod budujący obiekty wyglądał bardzo… kupiaszczo. Nie chciałbym teraz do niego wrócić.

Werdykt

Kontenery nie są narzędziami banalnymi w “obsłudze”. Ich niepoprawne skonfigurowanie może nieść za sobą katastrofalne konsekwencje. Co powiedz na aplikację, która wysypuje się co 2 tygodnie, bo z powodu nieprzemyślanych rejestracji obiekty mnożą się jak wirusy i zżerają całą pamięć? Wiesz, ile czasu może zająć diagnostyka i profilowanie? Ja wiem :), więc podpowiem: DNI całe!

Ale z drugiej strony: popatrz na kod w podlinkowanych postach i prezentacjach.

Lambda na lambdzie i lambdą pogania. Poukrywane, pozagnieżdżane. Ja osobiście wolę mieć 50 linii czytelnego kodu niż 8 linii kodu, który bez problemu “załapie” maksymalnie 10% populacji.

Albo IFy, SWITCHe. Kurde… ControllerFactory o nazwie PoorMansCompositionRoot? Z mega-switchem? Ciut nie pattern-matching, tylko dla BARDZO ubogich.

Bardzo szanuję obu Panów, są półbogami programowania. Gdyby ich scalić, to powstałby dev-bóg. Ale tego… po prostu nie kupuję.

Oczywiście, każda zależność, referencja, to dodatkowy koszt. Każde narzędzie to proces nauki, obowiązki związane z utrzymaniem i aktualizacjami. Każda biblioteka to ryzyko “cudzych” błędów. Ale czy to powód, żeby wszystko pisać samemu?

NIE! A nawet: NIH! NIH Syndrome się kłania. Tak, jak bez sensu jest pisać własny kontener (co na jutubie czynię :) ), tak bez sensu jest ręcznie, samodzielnie, dbać o wszystkie rejestracje i tworzenie obiektów.

Z głową i umiarem. Świadomie, panie i panowie. Ze zrozumieniem, bez tępego copy/paste ze StackOverflow. Oto uniwersalna porada i maść na ból wszelaki.

Nie przegap kolejnych postów!

Dołącz do ponad 9000 programistów w devstyle newsletter!

Tym samym wyrażasz zgodę na otrzymanie informacji marketingowych z devstyle.pl (doh...). Powered by ConvertKit
Notify of
pawelek

Albo wziąć język funkcyjny, gdzie nie ma obiektów i już :) Ale fakt tu już pewnie tylko 3% populacji zrozumie “o co kaman” :)

Bartek
Bartek

Zajmowałem się problemem wycieków pamięci w aplikacji webowej – spring+scala+akka. Scenariusz podobny do opisanego przez Ciebie – apka się wykładała średnio co 3-4 tygodnie. Diagnoza? – OutOfMemoryError. Przyczyna? heh… Debugowanie języka funkcyjnego tudzież scali z akką to była istna mordęga… Skoki między tonami klas, masa apply’jów i problemy z zatrzymywaniem się w breakpointach… Nie wspominając już o tych wszystkich skrócikach i “uproszczeniach” konstrukcji, które do mnie nie trafiają. Jak słyszę teraz o tym, że ktoś się zachwyca scalą, jej skalowalnością, lambdami i że jest taka wow – mam ochotę strzelać. Scala może sama w sobie nie jest aż taka zła,… Read more »

Darek
Darek

Również tego nie kupuję, zarówno bez sensu jest bezmyślne ładowanie do projektu miliona frameworków i bibliotek jak i pisane siłę swoich rozwiązań, które ktoś już zrobił dobrze i dopracował, bo siedzi w temacie od lat. Wyobraźmy sobie stolarza który zamiast robić zlecenie, zajmuje się produkcją narzędzi bo “zrobi to lepiej i uniezależni się od producentów”.

Bartosz Sypytkowski

– Sądzę jednak, że łatwiej jest ludziom wyjaśnić jak działają funkcje anonimowe / lambdy, niż tłumaczyć API do biblioteki mającej prawie tyle kodu, co projekt do którego jej używam. – Używanie kontenera zasadniczo przenosi cię w strefę programowania dynamicznego: skąd wiesz, że poprawnie podpiąłeś wszystkie zależności i twój program działa? Cóż, nie dowiesz się tego po prostu kompilując swój projekt. Musisz go odpalić i wywołać kod w każdym miejscu gdzie używasz DI. Oczywiście możesz napisać do tego testy, tylko że to mija się z początkowym założeniem. – Zauważyłem, że nagminnym problemem w projektach korzystających z DI jest tendencja ludzi do… Read more »

Krzysztof Skrzynecki
Krzysztof Skrzynecki

Istnieją również kontenery, które sprawdzają zależności podczas kompilacji – Dagger (https://google.github.io/dagger/) jest dobrym przykładem. Jestem ciekaw czy istnieją podobnę rozwiązania dla świata poza javowego

Wojciech
Wojciech

Zysk z weryfikacji w trakcie kompilacji bije wszystko pozostałe na głowe. Jeśli mamy framework, który umie zrobić DI w czasie kompilacji (np. macwire w scali) to spoko. W pozostałych wypadkach, sorry memory.

trackback

[…] Dependency Injection: z kontenerem czy bez? […]

Dawid
Dawid

IMHO, kontenery (nikt nie mówi o IoC jako takim) powinny być dodawane do projektów w kolejnej fazie. To zrobiło się tak bardzo popularne, że nawet nikt nie zauważa wrzucania kontenerów (z mojego podwórka nawet tak prostych jak Guice) do 3 klasowej applikacji jako zwykły błąd i overengineering. Czy nie przypomina to mikroserwisów? W przypadku kontenerów bardzo ciężko wyznaczyć granicę, kiedy “narzut” się opłaca, a kiedy nie – bo właściwie to kwestia developera jaki styl pracy mu się bardziej podoba. Pomijam fakt, że po prostu można nie potrafić programować bez użycia kontenerów – co też się zdarza.

Moja książka

Facebook

Zobacz również