Co Jaś Fasola otwierający auto ma wspólnego z programowaniem?
Cześć!
Poniedziałek, poniedziałeczek. Ja wyjątkowo spędziłem go nie w pracy, ale w podróży znad morza. Sam nie wiem co lepsze czy kilkugodzinna podróż samochodem z nudzącym się jak nie śpi brzdącem czy też bycie w pracy. Ciężki wybór nie? Żartuję, zawsze lepiej niż w pracy.
Dlatego dzisiaj też jeszcze mniej mięsnie (postaram się to nadrobić w kolejnym mailu), ale bardziej refleksyjnie. Zanim przeczytasz dalszą część obejrzyj proszę sobie poniższy filmik:
Jaś Fasola otwiera samochód dodaje nowy zestaw klas do obsługi encji. Najpierw samą klasę encji, potem repozytorium (tudzież rejestruje jego generyczną wersję), potem serwis aplikacji, walidator requestu, mapowanie kontraktu na encje. Już ma ruszać, gdy przypomina sobie o tym, że nie pojedzie, bo zapomniał dodać kontroler. No dobra, kontroler już jest, odpalamy no i bum, nie działa, bo jeszcze przecież zapomnieliśmy czegoś zarejestrować w kontenerze IoC. Potem tylko unit testy do każdej z dodanej klasy, jakiś test integracyjny i wreszcie nasz endpoint dodający słownik z dwoma polami działa…
Robota zrobiona, można sobie otrzepać ręce i dumnie pomyśleć “ależ się narobiłem!“. Szczególnie jeśli dorzucimy jakąś generyczną faktorkę, fikuśny provider i doprawimy refleksją to możemy się czuć spełnieni. Kawał dobrego kodu!
Kiedyś dokładnie tak myślałem. Kiedyś na integracji podszedł do mnie i powiedział “Oskar, wiesz co, zanim zrozumiałem jak robić funkcjonalności w naszej architekturze to zajęło mi to ze 3 miesiące, ale teraz jak już wreszcie rozumiem to jest spoko”. Poczułem się najpierw dumny, że stworzyłem “porządną” architekturę. W końcu jest skomplikowana, więc trzeba dużo poświęcić czasu, żeby ją zrozumieć. Zrobiłem też w tym projekcie klasę generyczną, która potrafiła wszystko, nawet kawę zaparzyć. Potrzebowała do tego co prawda do uzupełnienia 14 parametrów generycznych, ale co tam! Robimy poważną aplikację biznesową przecież!
Gdy to przemyślałem, to stwierdziłem, że to jest jednak coś nie halo. Czy naprawdę to co skomplikowane to jest takie fajne? Czy naprawdę potrzebna jest ta cała ceremonia? Kiedyś tak myślałem - teraz uważam, że najlepszy kod to jest taki, który jak zobaczymy, to powiemy “kurde, jakie to proste, czemu ja na to nie wpadłem”. Wbrew pozorom taki kod wymaga sporo pracy - nie tylko nad nim, ale i nad sobą. Czasem są to małe rzeczy, jak odpowiednio stawiane IFy (pisałem o tym szerzej na swoim blogu już kilka lat temu: https://oskar-dudycz.pl/2015/10/31/what-really-grind-my-gears-1/). Czasem są to nieco większe rzeczy jak poznawanie nowych wzorców, paradygmatów - np. programowanie funkcyjne, wzorce architektoniczne jak Event Sourcing, CQRS. Czasem skoki w bok na trawnik sąsiada w inny język czy też technologię.
Ja nie jestem dogmatykiem, wywodzę się ze światka .NET - to jest mój matecznik, do którego wracam i dookoła, którego orbituję, ale lubię poznawać inne technologie. Często w swoich projektach więcej piszę w innych językach niż C# - np. aktualnie więcej TypeScript i Node.JS. Praca z różnymi językami, środowiskami programistycznymi daje możliwość spojrzenia z boku - z innej perspektywy. Kiedyś np. nienawidziłem JS - pisałem o nim per “gówniany język”. Teraz po czasie uważam, że ja go po prostu nie rozumiałem i nie umiałem w nim pisać. Jak przestawiłem myślenie to okazało się, że ma duży sens, a jego dynamiczność, prostota i zacięcie funkcyjne dużo mnie nauczyło.
Dlatego np. jak wracam do Visual Studio i do .NET to myślę sobie “czemu to jest takie ciężkie?!“. Dlatego cieszą mnie usprawnienia w C# 9 (https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/), cieszy mnie niewymaganie metody main, czy też umożliwienie robienie endpointów bez kontrolera (https://github.com/dotnet/aspnetcore/issues/17160). Im mniej ceremonii tym lepiej.
Często też spotykam się ze stwierdzeniem “programista powinien to wiedzieć i o tym pamiętać”. Tylko im więcej programista musi wiedzieć i pamiętać tym większa szansa, że o tym kiedyś zapomni i popełni głupi błąd. Wg mnie takie konieczne rutynowe powtarzalne czynności powodują, że programista przestaje myśleć, a zaczyna kopiować i wklejać, a to najlepsza droga do głupich błędów, które trudno wykryć.
Dlatego zadanie domowe dla Ciebie:
- zastanów się przez ile klas i warstw przechodzi request do momentu zapisu w bazie,
- jak dużo masz klas generycznych, szczególnie z kilkoma parametrami i jakie masz z tym problemy,
- czy wiesz czemu kompozycja jest lepsza od dziedziczenia?
Zastanów się czy to na pewno musi tak być i czy te konstrukcje nie przypominają przypadkiem, otwierania samochodu Jasia Fasoli. Chętnie przeczytam Twoje wnioski.
Jeśli dalej Cię nie przekonałem do zmniejszenia ceremonii to wytłumacz mi proszę - po co do w WebApi kontroler?
Pozdrawiam serdecznie!
p.s. w razie pytań śmiało pisz, przez urlop mam lekkiego laga z odpisywaniem, ale postaram się to w najbliższych dniach nadrobić. Czekam na pytania, uwagi oraz propozycje o czym chcesz przeczytać.