Po dość znacznej przerwie powracamy jeszcze na chwilę do tematu Dependency Injection. Pamiętacie cykl i moment, do którego dotarliśmy? Zastosowaliśmy SRP by uprościć kod. Wprowadziliśmy jawne zależności między komponentami i ubraliśmy je w interfejsy. Spróbowaliśmy napisać własny kontener Dependency Injection, a potem zobaczyliśmy dlaczego lepiej użyć jednak czegoś gotowego. I stanęło na Autofac, kiedy to obiecałem “kilka finalnych refleksji”. Oto one.
Czy jest lepiej?
Tak, zdecydowanie można stwierdzić, że JEST lepiej. Po porównaniu kodu początkowego z kodem finalnym (tag demo5-start) aż dziw bierze, że tak proste zabiegi mogą mieć tak pozytywny efekt.
Zwiększyliśmy czytelność: zamiast jednej wielkiej klasy mamy teraz kilka mniejszych, mieszczących się na jednym ekranie. Takie komponenty łatwo jest przeczytać i zrozumieć. Szczerze mówiąc zwykle staram się pisać klasy w ten właśnie sposób: by całość mieściła się na jednym ekranie. Czy mam wtedy dużo klas? Tak! Czy to coś złego? Tu można dywagować, ale: u mnie się sprawdza.
Dzięki poprzedniemu zabiegowi: wprowadziliśmy testy. Znaleźliśmy nawet buga bez uruchamiania systemu i… poprawiliśmy go! O tym jak bardzo istotne są testy automatyczne dzisiaj rozpisywać się nie będę, ale: wiadomo jak jest :). Pokrycie testami pierwotnego kodu było średnio możliwe.
Wszystkie zastosowane zabiegi miały wpłynęły pozytywnie na najważniejszą cechę oprogramowania: stało się ono bardziej utrzymywalne! Do tego dążymy, o to dbamy, tym się jaramy i to nas kręci ;).
Ale…
Czy jest idealnie?
Nigdy nie jest idealnie :). Niestety, w aktualnej postaci nie jest nawet “wystarczająco dobrze“.
Spójrzmy na kawałek naszego UsersController:
public UsersController ( IEmailValidator emailValidator, IActivationLinkGenerator activationLinkGenerator, IEmailService emailService ) { _emailValidator = emailValidator; _activationLinkGenerator = activationLinkGenerator; _emailService = emailService; }
https://github.com/maniserowicz/di-talk/blob/demo5-start/src/app/UsersController.cs
Co oczom naszym się ukazuje? Ano konstruktor. Z iloma zależnościami? Z trzema. Czy to dużo? Jak zwykle: “to zależy”. Trzy zależności zwykle “ujdą”, ale tutaj mamy do czynienia z zabawną sytuacją: kontroler potrzebuje do działania prawie wszystkich innych komponentów w systemie! Code-smell jak nic.
Wiecie dlaczego zostawiłem kod w takiej postaci i nie ciągnąłem refactoringu? Bo na dłuższą metę to nie ma sensu. Jeśli będziemy podążać tą drogą to i tak na końcu wylądujemy z brzydkim kontrolerem. “Kontrolerem-orchestratorem”. Jego jedyną odpowiedzialnością będzie przyjęcie X zależności i wywoływanie metod w odpowiedniej kolejności. “Przecież dokładnie do tego służy kontroler!” – mógłby ktoś zakrzyknąć. I z jednej strony: będzie miał rację. A z drugiej: kontrolery w MVC są bytem sztucznym i zbędnym (ale o tym innym razem).
W celu podniesienia jakości tego kodu jeszcze bardziej trzeba zmienić trochę podejście. “Wyewoluować” od standardowego MVC… trochę dalej. Wprowadzić do systemu pojęcie “komend”. I “zdarzeń”. Już wiadomo o czym mówię, o co chodzi, prawda? Naturalną konsekwencją mojej prezentacji o Dependency Injection było przygotowanie kolejnej, tym razem o CQRS. I tego tematu możecie wkrótce spodziewać się na blogu.