Wstrzykiwanie zależności – cz. 1

Dzisiaj artykuł o wstrzykiwaniu zależności. W tworzonej przeze mnie aplikacji CyberHome stosuję wstrzykiwanie zależności za pomocą AutoFac’a. Na wstępie zastanowimy się po co to na w ogóle… Zapraszam do lektury.

Każda poważniejsza aplikacja w obiektowym języku programowania powinna implementować zasadę odwróconego sterowania (IoC), a jej poszczególne modułu powinny być luźno powiązane (loose coupling).

Często z IoC utożsamiamy DI (wstrzykiwanie zależności), podczas gdy DI to najpopularniejsza realizacji IoC; nie będę się produkował ponieważ Wikipedia bardzo trafnie to opisuje:

DI silnie preferuje zewnętrzne tworzenie połączeń (zależności) pomiędzy komponentami oprogramowania (np. asocjacje w klasach), nad zlecaniem tworzenia zależności im samym.
Jest to wzorzec, w którym odpowiedzialność za tworzenie obiektów i łączenie jest przeniesiona z obiektów do fabryki (np. kontenera IoC).
Na żądanie kodu fabryka tworzy obiekt, lub udostępnia obiekt z puli obiektów, ustawiając mu powiązania z innymi obiektami (np. wstrzykiwanie konstruktorem –- Constructor Injection, wstrzykiwanie mutatorami – Setter Injection, użycie interfejsu Interface Injection lub w mieszany sposób).
DI jest więc realizacją „odwrócenia sterowania” w sensie tworzenia i wiązania obiektów.

 Jakie zalety wynikają ze stosowania odwróconego sterowania:

  • Wymusza tworzenie dobrze zorganizowanego, modułowego kodu, o ściśle przypisanych zadaniach.
  • Kod podlega dużo łatwiejszemu testowaniu (tylko krok dzieli nas od TDD).
  • Kod jest luźno powiązany.

A są jakieś wady..?

Wad jest niewiele, przede wszystkim jeśli nie mamy doświadczenia łatwo jest popłynąć i zbyt mocno „zgranulować” kod .
Jeśli skorzystamy z kontenera IoC (a skorzystamy na pewno! :)) tracimy część kontroli nad tym co dzieje się w aplikacji – kontener niektóre czynności (np. tworzenie obiektów, instancjonowanie ich) wykonuje za nas. Oczywiście – jest to zgodne z naszym oczekiwaniem.

Najprostszy przykład DI

Wyróżniamy kilka sposobów wstrzykiwania instancji jednej klasy w drugą.
Najprostszym z nich jest Constructor Injection (dokładny opis tutaj):

class AppPoolWatcher
{
    INofificationAction action = null;

    public AppPoolWatcher(INofificationAction concreteImplementation)
    {
        this.action = concreteImplementation;
    }
 
    public void Notify(string message)
    {   
        action.ActOnNotification(message);
    }
}

Jak widać konstruktor klasy AppPoolWatcher oczekuje jako argumentu instancji klasy implementującej interfejs INotificationAction. Interfejs ten wymusza implementację metody ActOnNotification(string).
Obie klasy będą więc z sobą luźno powiązane, autor AppPoolWatcher wie, że otrzyma działającą instancję klasy, na z której będzie mógł wywołać metodę ActionOnNotNotification. Nie uzależniamy ściśle jednej klasy od drugiej.

EventLogWriter writer = new EventLogWriter();
AppPoolWatcher watcher = new AppPoolWatcher(writer);
watcher.Notify("Sample message to log");

Powyżej użycie w kodzie: tworzymy klasę EventLogWriter implementująca interfejs INotificationAction.
Tworzymy klasę AppPoolWatcher , jako argument konstruktora przekazujemy instancje utworzonej w poprzednim kroku klasy.
Następnie możemy wywołać metodę Notify narzuconą przez  INotificationAction. Działa! 🙂

AutoFac zrobi całą robotę za nas! Opowiem o tym w kolejnym artykule. Pokażę również jak go używam w moim programie.


Artykuł w ukazuje się w ramach projektu CyberHome tworzonego w ramach akcji DajSięPoznać.


5 przemyśleń nt. „Wstrzykiwanie zależności – cz. 1

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *