Dependency Injection – Wprowadzenie

W tym artykule opowiem Ci o wstrzykiwaniu zależności (eng. dependency injection). Przybliżę Ci jego idee oraz podstawowe założenia.

Ten artykuł jest o Wstrzykiwaniu Zależności (ang. Dependency Injection). Przybliżę Ci jej główną koncepcję oraz omówię dlaczego warto ją stosować. Na konkretne biblioteki przyjdzie czas w kolejnym poście.

Głowna koncepcja Dependency Injection?

W dużym uproszczeniu, wstrzykiwanie zależności to tworzenie obiektów (zależności) i umieszczanie ich (wstrzykiwanie) w miejsca, gdzie są niezbędne.

Często możesz spotkać się z sytuacją, kiedy jakaś klasa potrzebuje referencji innej klasy. Przykładowo klasa Samochód, potrzebuje wykonać akcję na obiekcie klasy Silnik. Właśnie w takich momentach zastosujemy DI.

Bez „wstrzykiwania zależności” mogło by to wyglądać następująco:

class Car(
    private val engine: Engine = Engine(),
    private val wheel: Wheel = Wheel("number", "name")
){

 fun drive() {
    wheel.screw()
    engine.start()
 }
}

Jak możesz się domyślić takie podejście jest nie poprawne. Dlaczego? 

W programowaniu obiektowym istnieją zasady S.O.L.I.D. W skrócie… należy się ich trzymać, by kod jaki napiszemy nie przypominał spaghetti i nie wzbudzał dreszczy na myśl o jego dalszym utrzymaniu (zasadom S.O.L.I.D. poświęcę oddzielny artykuł).

Zgodnie z jedną z zasad, klasa powinna koncentrować się na wypełnianiu swoich obowiązków, a nie na tworzeniu podmiotów, niezbędnych do ich wykonania. 

I tu właśnie pojawia się wstrzykiwanie zależności, które dostarcza klasie wymagane obiekty. Zwróć też uwagę, że stosując powyższe (złe) rozwiązanie, musieli byśmy pamiętać o argumentach klas, które inicjalizujemy – jak w przypadku klasy „Wheel”. 

Wyobraź sobie, że klasa Car przyjmowała by pięć argumentów (a nie dwa) i każdy z nich miałby po pięć swoich argumentów do zainicjalizowania. Był by niezły bałagan.

Tak więc, poprawnie wyglądało by to tak:

class Car(
    private val engine: Engine,
    private val wheel: Wheel
){

  fun drive() {
    wheel.screw()
    engine.start()
  }
}

Zamiast ręcznego tworzenia instancji klas Engine i Wheel, instancje te zostały by wstrzyknięte za pośrednictwem DI. Jak dokonywać wstrzykiwania? O tym już w kolejnym poście.

Dlaczego DI jest tak istotne ?

  1. Po pierwsze, separuje miejsce tworzenia zależności, od miejsca jego użycia.
  2. Zależności przestają być ukryte wewnątrz implementacji klasy co niesamowicie wpływa na jakość i przejrzystość naszego kodu.
  3. DI ma ogromny wpływ na testowalność kodu naszej aplikacji. Przykładowo, możemy zamockować argumenty konstruktora i uruchomić testy jednostkowe w odizolowanym środowisku.

Ciąg dalszy …

Jak już wiesz, było to wprowadzenie do Dependency Injection. W tym artykule, chciałem nakreślić Ci o co w tym wszystkim chodzi… ale już wkrótce otrzymasz górę soczystego mięcha. Zobaczysz zastosowanie DI na realnym projekcie wraz ze szczegółowym opisem.

Pozdrawiam Cię gorąco,
Kamil Krzysztof.