Dependency injection albo kim jest key grip?

Wstrzykiwanie zależności to podstawa dzisiejszego programowania. Dzięki tej koncepcji mamy kod łatwiejszy do zarządzania, bardziej modułowy i testowalny. Ale jak wyjaśnić tą koncepcję w prostych słowach? Jak zwykle posłużymy się przykładem z życia.

Jak się kręci filmy?

Powiedzmy, że jest sobie plan filmowy. Na tym planie pracują aktorzy, reżyser, operatorzy, charakteryzacja i wiele wiele innych osób dbających o kręcenie filmu.

W trakcie kręcenia fimu potrzebujemy dużo różnych przedmiotów. Potrzebne są rekwizyty, pojazdy, miejsca, zezwolenia itp.

W filmach amatorskich każdy jest sobie aktorem, rekwizytorem itp. Przynosimy co mamy i filmujemy. Odpowiedzialność jest wymieszana.

W tradycyjnym modelu programowania, gdybyśmy chcieli zacząć filmowanie musielibyśmy zawczasu przygotować wszystkie potrzebne przedmioty. Musimy zgromadzić wszystkie rekwizyty, zakupić lub wypożyczyć pojazdy, zarezerwować lokalizacje a także zadbać o tysiące małych szczegółów. Każdy aktor (lub jego asystent) przed kręceniem scen dostałby komplet potrzebnych akcesoriów.

Czy da się to zorganizować w praktyce? Pewnie tak, ale jest to trudne i pracochłonne. Planowanie wszystkiego naprzód wymaga wielu godzin spotkań i ustaleń. W tym czasie aktorzy siedzą i się nudzą a producent denerwuje się, że jeszcze im za to płaci.

A co jeśli nagle zmieni się koncepcja? Cały misterny plan idzie w łeb.

Dlatego od dawna już plany fimowe urządza się inaczej. Zamiast przygotowywać wszystko zatrudnia się człowieka (lub ekipę), którego zadaniem jest dogranie szczegółów. Potrzebujemy więcej lamp? Ten człowiek to załatwi, może nie sam ale wie z kim rozmawiać. Chcemy egzotyczny rekwizyt? Znów nasz człowiek od wszystkiego zajmie się przekazaniem zapotrzebowania i dopiluje, żeby rekwizyt do nas trafił.

Tym właśnie zajmuje się tajemniczy key grip, którego często widzieliśmy w napisach na koniec filmu i zawsze zastanawialiśmy się kto to taki.

Key grip w programowaniu to właśnie DI?

W programowaniu obiektowym działamy podobnie. Zamiast tworzyć obiekty i dawać im od razu wszystkie potrzebne parametry dajemy im tylko jeden – obiekt rozdający obiekty. Mówimy na niego fabryka, kontener, dostawca lub po prostu obiekt DI.

Niech teraz nasza klasa potrzebuje dostępu do bazy, albo mailera, albo zapisu do plików, albo kont użytkowników… zamiast tworzyć sobie nowy obiekt, np. database, mailer itp mówi naszemu DI: „Daj mi jakiegoś mailera”. Obiekt DI oddaje najlepszego mailera, jakiego ma.

Zalety są oczywiste:

  • Możemy łatwiej testować kod podkładając np. tymczasowego mailera.
  • Możemy równolegle pracować nad projektem gdy jedni programiści robią mailera, inni dostęp do bazy a jeszcze inni logikę biznesową.
  • Zmiany w działaniu aplikacji są łatwiejsze gdy wiemy kto (który moduł) za co odpowiada.
  • Unikamy też tworzenia wielu takich samych obiektów – nasz DI sam dba o to, by nie tworzyć obiektów gdy nie są potrzebne tylko przekazuje ten sam obiekt wielu modułom, które o niego proszą.
  • Możemy oszczędnie gospodarować zasobami czyli tworzyć obiekty dopiero, gdy ktoś o nie poprosi (leniwe ładowanie).

Są też wady. Musimy stworzyć trochę więcej kodu. Trudniej jest też na pierwszy rzut oka zorientować się w przepływie programu gdyż obiekty sięgają innych obiektów dopiero, gdy ich potrzebują.

Dependency injection wymaga zmiany sposobu myślenia o programie. Wcześniej myśleliśmy w kategoriach zrób, zrób, podaj, zrób. Teraz nie mamy wprost podanego przepływu programu a jedynie siatkę zależności. Przypomina to trochę pisanie makefile, gdzie kolejne reguły mogą zależeć od poprzednich. Musimy teraz myśleć w kategoriach daj, daj, powiedz a na koniec oddam co zrobiłem. Nasza struktura kodu zaczyna przypominać programowanie deklaratywne.

 

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *