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 ?
- Po pierwsze, separuje miejsce tworzenia zależności, od miejsca jego użycia.
- Zależności przestają być ukryte wewnątrz implementacji klasy co niesamowicie wpływa na jakość i przejrzystość naszego kodu.
- 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.