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.
DI: Kilka refleksji po wprowadzonych zmianach
Dziękujemy za dodanie artykułu – Trackback z dotnetomaniak.pl
Cześć Maciej!
Po pierwsze miło zobaczyć nowy, techniczny wpis na blogu po wakacyjnym odwyku :)! Gratuluje również nowego Layoutu (widziałem już pare dni temu, ale nie było gdzie zostawić komentarza) – krok w bardzo dobrą stronę, bo stary mimo, że dawał poczucie profesjonalizmu (coś a’la ‘nie mam czasu na fajerwerki, zajmuję się poważnymi rzeczami’ ;) ) to byl już trochę zbyt przestarzały.
Co prawda zajmuję się głównie desktopowym .NETem, ale bardzo zaciekawiło mnie Twoje spostrzeżenie odnośnie wirtualności kontrolerów, idealnie wpasowałeś się w moje ostatnie rozważania na temat zastosowania kontrolerów wraz ze wzorcem MVVM. Jakiś czas temu, w ramach prób przekonania się do aplikacji webowych testowałem zastosowanie VM w MVC (dla zainteresowanych: http://www.edandersen.com/2013/05/30/asp-net-mvc-basics-part-2-viewmodel-to-model-mapping-and-editing/) i pozytywne wrażenia z tego eksperymentu zachęciły mnie to do eksperymentownia z architekturą aplikacji. Zasiałeś ziarno niepewnosci i muszę się dobrze zastanowić, czy zmierzam w dobrym kierunku.
Pozdrawiam,
Maciek
@Maciej,
Dzięki za miłe słowo! Poprzedni layout faktycznie miał manifestować to co zauważyłeś, ale teraz planuję wypłynąć na szersze wody, więc i wygląd musi być bardziej profesjonalny.
Komentarze można zawsze zostawiać na fejsiku (https://www.facebook.com/Maciej.Aniserowicz.o.programowaniu), tam pojawia się wszystko co tutaj i jeszcze trochę więcej :).
Z aplikacjami dekstopowymi dawno nie miałem do czynienia (i nic nie wskazuje na to aby miało się to zmienić), ale swego czasu, dobre 5 lat temu, opisałem swoje podejście do wzorca MVP w tym kontekście, może Cię zainteresuje: http://www.maciejaniserowicz.com/2010/04/28/model-view-presenter-z-autofac-w-aplikacji-desktopowej/ .
Aż sie prosi o fasadę do prawdziwej aplikacji. Kontroler powinien zawierać cały shit związany z HTTP czyli odp rediredty, status codey itp, to ze ma wziąć/wziasc z tej czy innej klasy to już logika aplikacji.
Ja bym widział w tej fasadzie use caseowe metody w stylu generate link , send e-mail. Fasada powinna jednoznacznie mowić co róbi aplikacja. Kontroler zaś tylko tłumaczy generyczna aplikacje na świat HTTP
@rek,
No nie wiem czy w tym przypadku widziałbym w kontrolerze coś takiego jak “generate link”. Tutaj use-case to właśnie “register user”, a akurat częścią jest generowanie linku. Nie wiem czy śledziłeś/pamiętasz cały cykl, ale wrzucenie do kontrolera bardziej granularnych metod w tym przypadku moim zdaniem mija się z celem.
A że w większości aplikacji logika siedzi w kontrolerach, a nie powinna, to się zgadzam :).
Tak, śledziłem. Widziałem również prezentację. No właśnie o to mi chodzi, jeszcze mniej a nie bardziej. :)
https://gist.github.com/abenedykt/2f4dd0c64d8a13d4f6c5
Możemy o tym pogadać w realu (za tydzień będzie okazja :))
@rek,
A w ten deseń! No to jak najbardziej się zgadzam.
Ale pogadać na DevDay i tak można, a co tam :).
A kiedyw końcu obiecany tekst o CQRS? :)
JA,
W przyszłości, to jedyna sensowna rzecz którą jestem w stanie napisać :). Raczej nie wcześniej niż listopad/grudzień, może nawet styczeń.
Mocno się zdziwiłem jak wpadłem w nowy layout. Myślałem, że znajduje się na jakimś blogu kulinarnym :).
Wracając do root tematu, jak pozbyć się nadmiarowości w konstruktorze ? Jestem amatorem i często mój kontroler puchnie z uwagi na rozszerzająca się funkcjonalność, co skutkuje pojawianiem się coraz większej ilości serwisów w konstruktorze.
PATRYK,
Co do layout: jest tak jak miało być, blog NIE MA wyglądać jak typowy blog technologiczny – mission accomplished :).
A zbyt dużo zależności w konstruktorze (tzn więcej niż 3-4 max) oznacza, że źle zamodelowałeś problem. Brakuje jakiegoś klocka w tej obiektowej układance. Część zależności trzeba zagregować w nowej klasie.