Wstrzykiwanie zależności czyli Dependency Injection w 9 minut i 59 sekund. Część 3: jak źle używać DI
04.10.2009Kontynuujemy dalej naszą przeprawę z DI [część 1., część 2.]. W tym odcinku postaramy się w końcu coś popsuć – radosny marsz ścieżką usłaną różami jest przyjemny ale nie zawsze pouczający.
Zastanówmy się na ile użycie wstrzykiwania zależności czyni nasze oprogramowanie odpornym na błędy przy projektowaniu architektury aplikacji. W końcu nawet najwspanialszy wzorzec projektowy nie zabroni nam popełniania błędów.
Przyjrzyjmy się nieco zmodyfikowanej klasie NewsService
public class NewsService {
Storage storage;
Authenticator authenticator;
public NewsService(Driver driver) {
storage = new DBStorage(driver);
}
public Authenticator getAuthenticator() {
return authenticator;
}
public void setAuthenticator(Authenticator authenticator) {
this.authenticator = authenticator;
}
public void login(String uname, String pass){
((UsernamePassAuthenticator)authenticator).setUname(uname);
((UsernamePassAuthenticator)authenticator).setPass(pass);
}
public void addNews(String news){
if(authenticator != null){
authenticator.authenticate();
}
storage.save(news.getBytes());
System.out.println("News saved...");
}
}
Różni się ona od poprzedniej wersji w jednym drobnym, ale bardzo istotnym szczególe. Klasa NewsService w konstruktorze pobiera jako parametr sterownik (obiekt Driver), a nie, jak poprzednio Storage. W rezultacie NewsService sam sobie musi utworzyć obiekt Storage.
Kod NewsService jest wówczas związany na sztywno z konkretną implementacją kontenera na dane DBStorage, co jest oczywiście niepożądane. Co się zatem stało, co zrobiliśmy nie tak – w końcu używamy DI? A no popełniliśmy błąd polegający na tym, że wstrzykujemy do NewsService nie ten obiekt, co trzeba!
NewsService nie potrzebuje do niczego informacji o użytym sterowniku, NewsService potrzebuje tylko konkretnej implementacji Storage i to ona już ma się martwić o sterownik.
Ok. tutaj przypadek był prosty i ewidentny. W większych aplikacjach łatwo popełnić błąd polegający na wstrzyknięciu nie tego obiektu, który tak na prawdę jest wymagany. Także jeżeli widzimy, że gdzieś inicjalizacja klasy wymaga tworzenia obiektów, albo przekazujemy klasie jako parametr obiekty, które, logicznie rzecz biorąc, nie są jej potrzebne, to znaczy, że gdzieś położyliśmy architekturę aplikacji i błędnie użyliśmy DI.
Użycie DI wcale nie uwalnia nas od dobrego zaprojektowania aplikacji!
09.03.2009 at 1:17 po południu
[...] wstrzykując zależności do klas przy pomocy Springa [reszta cyklu: część 1., część 2., część 3.]. Dzisiaj czas na coś prostszego i przyjemniejszego: Google Guice! Przypomnijmy sobie jaki [...]
09.26.2009 at 10:40 przed południem
utitycefyna…
Where to Find Mortgage Financed Notes, Discounted … …