Jakiś czas temu jak jeszcze się dopiero zaczynałem orientować w programowaniu zawodowym natknąłem się na kilka myśli, spostrzeżeń, które mocno zmieniły moje spojrzenie na pewne rzeczy i podniosły jakość mojej pracy niemal z marszu. Czerpałem głównie z książek, bo jestem książkowym świrem i częściej sięgnę po książkę niż Hindusa na YT, choć zdarza się i tak. A pracę zaczynałem zaraz po technikum w januszeksach więc często nie miałem żadnego mentora w firmie.

No i jedną z tych myśli była klasyfikacja kodu wg złożoności i liczby zależności. Zaprezentował ją Khorikov w książce Unit Testing (dostępna tez po Polsku, Helion).
Idea polega na tym, że kod można ocenić pod względem:
**złożoności lub wagi domenowej** - czyli jak istotny jest kod dla podstawowego celu aplikacji (np algorytm wyznaczania ścieżki do celu w nawigacji) bądź jak bardzo jest on skomplikowany, czyli ile ma rozgałęzień, przypadków skrajnych i tak dalej;
liczby współzależności - czyli ile zawiera odniesień do zależności spoza kontroli bieżącego procesu, które mogą być modyfikowane również przez inne procesy, np połączenie z bazą danych, redisem, jakimś innym serwisem. Khorikov stawia tutaj wyjątek, że jeżeli serwis jest read only to nie traktuje się go jako współzależność ale ja lubię nie stosować się do tego wyjątku.

Jeżeli dwie powyższe miary zaprezentujemy na układzie współrzędnych (rozpatrując dodatnie połowy obu osi, ofc) to możemy podzielić go na cztery ćwiartki, pic rel. Jedna z nich to algorytmy, czyli kod o niskiej czy lepiej zerowej liczbie współzależności, które należy otestować jednostkowo. Idealnie jeśli ich rola sprowadza się do przyjęcia danych i zwrócenia wyniku, bez "efektów ubocznych". Druga to kontrolery, które testuje się integracyjnie. Niska złożoność ale dużo współzależności. Idealnie nie ma tam żadnych ifów, obliczeń, nic. Jedynie koordynacja komunikacji pomiędzy współzależnościami. Kod trywialny to kod o niskiej złożoności i liczbie współzależności (np gettery, settery etc). Nie testuje się go w ogóle bo nie opłaca się. I wreszcie **kod przekomplikowany **(jest takie słowo w języku niepotocznym? xD) to kod który jest i złożony i ma dużo zależności i jest to ten który widzicie w Waszych spagetti w Wordpressie. Ten ostatni typ to kod, który należy zrefaktorować, podzielić na algorytmy i kontrolery i otestować je indywidualnie.

Po lekturze tej książki natychmiast zastosowałem się do tych wskazówek w projektach w pracy i to był game changer. Od tamtej pory kod który piszę jest otestowany, przemyślany i poukładany. W każdym języku w którym miałem okazję napisać coś więcej ta porada znalazła zastosowanie. Jak ktoś dopiero zaczyna karierę albo dalej ma problem z pisaniem testowalnego kodu to polecam całym sercem.

PS to nie reklama, po prostu jakbym miał zaczynać jeszcze raz to sam bym chciał żeby ktoś mi polecił takie inspirujące rzeczy wcześniej niż odkryłem je sam.
2428e4ee-a8a5-4a2e-990c-f2ecac28b4b2
Tank1991

@Kshaq no... tak. świetnie opisałeś złożony problem.


Wszedłbym jeszcze w jeden temat, to co siedzi pod kontrolerami. Ilość patternów ktora tam czasem wymagana by nie zrobić spagetti (w skrajnych przypadkach kontrolery złozene z rejestrów na rejestrze generowanych jeszcze czasami w locie ) to materiał na osobną książke.


I jak to mawia moj kolega "wzorce to ja znam na pamięć, problem jest kiedy użyć właściwego i który to jest".


Natomiast do domen sprawdza mi się zawsze najstarsze "weź zobacz co masz w świecie w swojego programu i zamodeluj". Oczywiście rafinacja domen zajmie czasem lata ale zrąb do pracy wychodzi dobry.

Kshaq

W żadnym razie nie miałem zamiaru upraszczać tematu ani nie twierdzę, że to wszystko co można na ten temat powiedzieć. Chciałem bardziej żeby wyszło jak "trailer" pewnej koncepcji, zwrócenie uwagi na problem czy zaprezentowanie punktu widzenia bo często okazuje się, że dużo ludzi potrafi rozpoznać słaby kod ale nie każdy potrafi powiedzieć co go takim czyni. Być może zainspiruje to kogoś do zgłębienia tematu.


Ilość patternów jest spora i można drążyć je długo, podobnie jak algorytmy i struktury danych, przyznaję Ci pełną rację. Ale nie to miałem zamiar zrobić w tym wpisie.

Tank1991

@Kshaq 

>wyszło jak "trailer" pewnej koncepcji,

nie no wyszlo jak koncepcja, tylko chciałem dopowiedzieć i podyskutować że domeny - ok wyglądaja na zamknietą domenę (o ironio) algo ok - to samo zamknięta domena problemu o tyle te kontrolery nie wydaja mi sie na tyle oczywiste ze bedzie tu napewno jeden kwadracik.


>do zgłębienia tematu

domeny sa poznane, algo to wiadomo - bo sporo osob je lubi ale własnie do bebechów kontrolerów to nic madrego oprocz refactoring guru nie widzialem a zagadnienia skladania wzorcow to wogole nigdzie nie widzialem tego mnie moj "mistrz" uczył i poznałem to w praktyce

Kshaq

@Tank1991 znaczy nie wiem czy dobrze zrozumiałem problem, ale bebechy kontrolerów są o tyle ciężkie że w sumie to co powtarza się w nich najczęściej masz już zdefiniowane jako wzorce projektowe, a to co powtarza się rzadko lub wcale musisz rozkminić indywidualnie. Ta koncepcja w każdym razie tego nie pokrywa w takim detalu. Idk może najlepszym sposobem na naukę niektórych rzeczy jest po prostu praktyka

YebacWykop

@Kshaq panie kto ma czas na testowanie? Xd Mi nie udalo się jeszcze nauczyć pisania testów bo nie mam na to czasu to jest największa bolączką.

666

@YebacWykop robilem w korpo januszeksie gdzie pisalismy calkiem duza aplikacje, ktora byla krytyczna dla bardzo duzego klienta (lider w danej branzy na polskim rynku + zasieg miedzynarodowy). Do czego daze: robiona byla januszerka a nie bylo nawet testow.... Poszedlem do innej firmy gdzie byly testy - panie, to jest inna jakosc. Zmieniaj firme, serio

osobliwy

@YebacWykop panie, bez testów to jest niestety kupa. Jedna nieistotna zmiana potrafi zepsuć jakąś ważną funkcję w innym module. Tak nie można pracować.

qdco

@YebacWykop To się tylko tak wydaje, że to jest dodatkowy nakład czasu, a jest wręcz odwrotnie. Dobrze napisane testy sprawiają, ze potem możesz rozwijać tę aplikację bez zastanawiania się za każdym razem, czy nie wywali ci to kodu w innym miejscu. Poza tym w jakiś sposób i tak to pewnie testujesz, tylko ręcznie za każdym razem, zamiast napisać testy raz a dobrze. No, chyba że w ogóle nie testujesz tego, co piszesz i lecisz na #yolo - może zadziała


Druga sprawa, że pisanie testów też poprawia zwykle jakość kodu i ogólnie sprawia, że więcej rzeczy ma w nim sens. Polecam w ogóle spróbować z podejściem, gdzie najpierw piszesz testy do kodu, a potem dopiero kod.

YebacWykop

@666 właśnie szukam, tylko problem jest teraz z pracą dla juniorów/początkujących midów

YebacWykop

@osobliwy wyjebane, jak im sie spierdoli to moge zrzucić na to ze nie miałem czasu na pisanie testów, zresztą z takie pieniądze kto by się przejmował (budżetówka)

Kshaq

@YebacWykop Poświęć tempo na rzecz jakości zamiast odwrotnie. Skoro i tak wyjebane to lepiej coś z tego wynieść dla siebie, a jak zapytają co tak wolno to powiedz, że to tyle czasu zajmuje i siema. Testy to jest to czego się musisz nauczyć żeby wbić następny level

YebacWykop

@Kshaq masz rację, tylko jestem na etapie gdzie muszę sie wykazać, że potrafię pisać większe apki i kolejna juz na pewno będzie na spokojnie i z testami , zresztą testy zacznę pisać również w moich pobocznych projektach jak tylko znajdę na nie czas

GazelkaFarelka

@Kshaq Największą zaletą pisania testów jednostkowych jest nakazanie ich pisania programistom do ich własnego chujowego kodu. Jeżeli pisanie testow do tego co wysrałeś to droga przez mękę i zajmie ci pół dnia, to powinno ci dać do myślenia.

kobiaszu

@Kshaq Szczerze to totalnie nie zawracam sobie tym głowy od kiedy pisze w podejściu "Design by Contract" I używam weryfikacji formalnej

Voltage

@Kshaq to co opisałeś brzmi jak osobna, "własna" interpretacja architektury warstwowej czy heksagonalnej przy DDD. Dodatkowo, jeśli musiałeś odkryć podobne podziały sam to najwidoczniej zawiedli koledzy albo po prostu firmy w których było Ci dane na początku pracować, ale to nic nowego, sam też niestety przechodziłem podobną ścieżkę.


Z perspektywy doświadczonego deva powiem tylko tyle, że takowe interpretacje własne i książki niesamowicie burzą spójność w świecie IT i po prostu ciężko się przez nie dogadać. Stosowanie różnych praktyk, pojęć, później czasem wychodzi nadmierne tłumaczenie przy CRkach albo po prostu przez różnice w nazywaniu tych samych rzeczy (bo każdy przeczytał inną książkę) wychodzą jakieś dziwne koncepcje.

Kshaq

@Voltage 

Wiadomo, boli jak zmieniasz pracę, projekt, klienta i musisz przerzucać się na inny "framework" ale nie uważam żeby to był rozwiązywalny problem. Różne koncepcje są przyjmowane w różny sposób w zależności od potrzeb. Takie DDD na przykład, czasami jest przyjmowane w całości, czasami częściowo, czasami wcale. Podobnie hexagonal, onion, CA. Każdy projekt to okazja do poszerzenia horyzontów, a każda nowa koncepcja którą ktoś przynosi to okazja do dyskusji, z której albo nie wyniknie nic albo wyłoni się potencjalnie lepsze rozwiązanie, a zbiór doświadczeń co działa i co nie to korzyść dla ciebie, bo będziesz znał wady i zalety podejść w przyszłości. Nie trzeba od razu implementować każdego nowego pomysłu a w mnogości języków, technologii, paradygmatów i zwykłych trendów zawsze ktoś będzie miał coś ciekawego do powiedzenia. To tyle jeżeli chodzi o świat IT, ale brak spójności w firmie, dziale czy nawet zespole to już inny temat.


A co do tego o czym pisałem: to nie jest "własna interpretacja" czy alternatywa dla żadnego gotowego "frameworka" tak jak nie jest nią np. dependency inversion, ocp albo coupling i kohezja. To jest obserwacja, uogólnienie jakiejś koncepcji, problemu i propozycja jego rozwiązania. Warto umieć nazwać i opisać elementarne problemy jakie rozwiązują różne "gotowe" architektury jak ten hexagonal czy onion, bo nie zawsze masz możliwość ich wprowadzenia, choćby kiedy masz za zadanie robić refactor jakiegoś śmietnika. A kiedy junior pyta dlaczego robisz to tak a nie inaczej, to dobrze jest umieć zaargumentować inaczej niż "bo tak jest w ddd".

Voltage

@Kshaq Nie mówię że nie masz racji, chodzi mi po prostu o wspólny język w branży który przez takie redefiniowanie oczywistości stanowi często problem. Weźmy taki DDD (skoro już przy nim jesteśmy), którego podstawą jest ustalenie wspólnego języka, nie tylko wśród devów ale też na połączeniu dev-biznes. Im lepiej się rozumiemy tym szybciej, i bardziej bezproblemowo zaimplementujemy odpowiednie rozwiązania na akceptowalnym poziomie, i tym mniej długu narobimy. W Twoim przykładzie (a może po prostu źle go opisałeś?) wyodrębniasz "kod trywialny" którym opisujesz property oraz warstwę algorytmów jako szeroko pojętą domenę, a przecież np. w DDD modele i property mają swoje miejsce właśnie w warstwie domenowej. Tak, znajdują się w niej również serwisy domenowe, jednak tutaj już jest jakaś nieścisłość. Stąd moja opinia - im więcej ludzi pisze książki/blogi i miesza w nich pojęcia tym gorzej dla innych którzy to czytają i czasem łapią mindfucka konfrontując z innymi.


Oczywiście z większością tez mogę się zgodzić, piję jedynie do tego jednego problemu.

Kshaq

Ach, jasne, o to chodzi, nie zrozumiałem na początku.

Cała książka jest o testowaniu i to w tym kontekście jest przedstawiona koncepcja. Według Khorikova kod trywialny i algorytmy to nie są osobne warstwy, a jedynie klasyfikacja kodu. I tak na przykład możesz mieć model i property, ale nie testujesz go jeżeli nie zawiera żadnej logiki - stąd kod trywialny. Nie testujesz też na przykład DTO. Nic jednak nie przeszkadza w tym żeby ten sam model udostępniał metodę, która klasyfikuje się jako algorytm. Jakiś przykład który mi przychodzi do głowy to model Money. Uwaga, będzie Java moment. Możesz tam mieć konstruktor, getDecimals, getWholes i podobne i to jest kod trywialny, czyli nie testujesz go. Możesz mieć jednak w tej samej klasie funkcje dodawania dwóch moneyów, obliczania procentów albo podobnych i to już jest algorytm który testujesz jednostkowo. Ta klasyfikacja nie zawsze oznacza separację w osobnych warstwach, po prostu kawałek kodu albo jest testowany jednostkowo, albo integracyjnie, albo wcale, albo wymaga podzielenia jeżeli nie da się go jakoś bez fikołków otestować.


Jak czytam co napisałem to faktycznie mogło to nie wybrzmieć. Przyznaję Ci pełną rację w kontekście wspólnego języka.

Zaloguj się aby komentować