fbpx
devstyle.pl - Blog dla każdego programisty
devstyle.pl - Blog dla każdego programisty
HOT / 9 minut

Czterej jeźdźcy gnijącego designu


13.01.2020

Gdy zaczynamy nowy projekt, spędzamy mniej lub więcej czasu na jego projektowaniu. Często mamy jasny obraz tego, jak powinno wszystko działać, jakie mamy założenia, na co pozwalamy, a na co nie. W rezultacie otrzymujemy design, który w danym momencie wydaje nam się najlepszym rozwiązaniem. Wszyscy rytualnie podpisujemy się pod nim krwią i postanawiamy nie łamać jego założeń.

Na razie wszystko jest dobrze, development idzie gładko, pierwsze wersje lądują na produkcji i zaczynają spływać pierwsze żądania zmian czy też nowych funkcjonalności. Jednak prędzej czy później w aplikacji pojawiają się małe odstępstwa od pierwotnych założeń. Tu jakieś obejście, tam jakieś obejście. A bo to tylko na chwilę, zobaczymy, czy to się w ogóle sprawdzi. A bo na szybko trzeba załatać buga itd. Nasz oryginalny design zaczyna gnić i nie przypomina tego, co żmudnie wypracowaliśmy na samym początku. W pewnym momencie osiągamy stadium, w którym padają magiczne słowa: „To wszystko trzeba przepisać”. I tu pojawia się problem, bo nie wszyscy muszą być tego samego zdania, a w szczególności ludzie, którzy nie mają styczności z kodem, ale za to są osobami decyzyjnymi. Wtedy może dojść do sytuacji typu: „Działa? Działa. No to jedziemy dalej!”. Ostatecznie może się okazać, że nie tak łatwo przeforsować owo przepisanie, i przyjdzie nam wypić piwo, które sami nawarzyliśmy. W tym momencie wprowadzanie jakichkolwiek zmian staje się zarówno bardzo trudne, jak i frustrujące, i to nie tylko dla programistów, ale też dla osób zlecających nowe funkcjonalności.

Możemy teraz zacząć szukać winnych i tłumaczyć sobie, że przecież to wszystko przez ciągle zmieniające się wymagania, że klient sam nie wie, czego chce, że skąd niby mieliśmy wiedzieć, że to ma być tak, a nie inaczej. Racjonalizacja to bardzo wygodna i skuteczna metoda. Zdarza się, że z przyczyn niezależnych rzeczywiście mamy związane ręce. Mimo to żąda się od nas, aby kod był odporny na takie zmiany. Dlaczego? Bo w większości wypadków pracujemy w metodykach zwinnych, a one zakładają, że wymagania będą się zmieniać, i naszym zadaniem oraz zadaniem naszego designu jest wychodzenie naprzeciw wymaganiom klientów.

Ale spokojnie, rozluźnijmy się trochę i zagrajmy w BINGO:

Rys. 1. Rotting design BINGO

I jak? Jest „BINGO!” czy nie? Jeśli „wygrałeś”, mam dla Ciebie dwie wiadomości: dobrą i złą. Zła jest taka, że chyba właśnie zmagasz się z psującym się designem, a dobra to taka, że postaram się rzucić trochę światła na chorobę, która go toczy. Zanim to jednak nastąpi, chciałbym, żebyśmy przyjrzeli się bliżej tym przykładom. Każdy z nich charakteryzuje się występowaniem jednego z czterech głównych symptomów psującego się designu.

Symptomy gnijącego designu

Symptom nr 1 – sztywność

Oznacza to, że z pozoru prosta, niewinna modyfikacja w kodzie powoduje lawinę nieprzewidzianych zmian, a każda kolejna pociąga za sobą następną. Rozlewa się po kodzie na coraz większe obszary, zajmując zależne klasy. Tym samym te – jak się wydaje – trywialne zmiany są bardzo trudne do wprowadzenia, bo wymagają korekty w wielu innych miejscach.

Przykładem z życia może być sytuacja, gdy Product Owner pyta, ile czasu zajmie dorzucenie checkboxa do formularza, a wy odpowiadacie, że dwie osoby będą nad tym pracować cały sprint. Niewiarygodne? Zaręczam, że prawdziwe.

W rezultacie problemy, które nie są krytyczne dla aplikacji, nie są naprawiane, ponieważ Product Owner czy inny manager zwyczajnie boją się zlecić ich naprawienie, nie wiedząc, na jak długo programista może przepaść.

Symptom nr 2 – kruchość

Jej występowanie możemy zauważyć, gdy przy zmianie w jednym miejscu zaczynają pojawiać się bugi w miejscach logicznie niezwiązanych z samą zmianą.

Naprawiliście politykę obliczania VAT-u, ale stało się to przyczyną trzech innych błędów obejmujących: dodawanie produktów do koszyka, filtrowanie użytkowników w panelu administratora i logowanie wyjątków.

Znowu pojawia się strach, bo nie wiadomo, czy naprawa błędu nie spowoduje tego, że biznesowo istotne funkcjonalności losowo przestaną działać. Wkrada się też podejrzenie, że programiści mogli stracić kontrolę nad kodem.

Symptom nr 3 – nieruchliwość

Teraz wyobraź sobie sytuację, że pisząc nową funkcjonalność, wiesz, że gdzieś w kodzie jest kawałek, który idealnie by pasował do tego, co masz zamiar zrobić, zarówno pod kątem funkcjonalności, którą realizuje, jak i kontekstu użycia. Odnajdujesz go, analizujesz z każdej strony, a następnie zostawiasz i piszesz to samo, tylko w nowym miejscu. Dlaczego? Bo oceniasz, że narzut związany z jego ponownym użyciem – wyodrębnieniem i spełnieniem jego zależności – jest tak duży, że zwyczajnie się to nie opłaca. W tym przypadku kończymy z klasami, które po prostu nie nadają się do ponownego użycia.

Symptom nr 4 – lepkość

Istnieją w zasadzie dwa sposoby wprowadzania zmian: zgodnie lub niezgodnie z aktualnym designem. W przypadku kiedy łatwiej jest nam działać według drugiego z tych sposobów, oznacza to, że mamy do czynienia właśnie z lepkością. Możliwe, że spotkaliście się z sytuacją, kiedy wiedzieliście, jak „powinno” się coś napisać, ale ostatecznie po analizie, ile by to zajęło, zapadała decyzja, że na razie zrobi się mały wyjątek, żeby szybko coś dowieźć. Podsumowując – wygodniej i sprawniej jest nam dorzucić tzw. „hack”, niż trzymać się założeń designu.

Rys. 2. Cztery główne symptomy psującego się designu

Złe zarządzanie zależnościami

Dotarliśmy do momentu, kiedy trzeba odpowiedzieć na pytanie: właściwie jaka choroba trawi nasz design? Skoro powiedzieliśmy wcześniej, że niekoniecznie są to zmieniające się wymagania, to co to może być innego? Najczęściej okazuje się, że jest to złe zarządzanie zależnościami w naszym kodzie. Z pomocą przychodzą nam tu dwa stare pojęcia: „coupling” (myślę, że angielska forma jest tak popularna, że wybaczycie mi posługiwanie się właśnie nią) i „kohezja”.

Coupling można zdefiniować jako stopień zależności między klasami czy modułami, siłę ich relacji. Zwykle mówi się o dwóch typach couplingu, czyli o słabym i mocnym. Jednak jak to w życiu bywa, jeśli są jakieś skrajne wartości, to musi być coś między nimi, i tak też jest w tym przypadku. Dowiesz się więcej na ten temat w kolejnym wpisie.

Jeśli chodzi natomiast o kohezję, to jest to określenie tego, jak bardzo elementy już pojedynczej klasy „pasują do siebie”. Wszystkie one powinny efektywnie ze sobą współpracować w konkretnym wspólnym celu. Powinny wręcz naturalnie się zazębiać, bez potrzeby stosowania jakiegoś „kleju” do ich połączenia. W przypadku spójności najczęściej mówi się o niej jako o niskiej lub wysokiej, i tutaj niespodzianka – również jest coś pomiędzy.

W ogólnym rozrachunku dobry design, czyli taki, który jest łatwy w utrzymaniu i odporny na zmiany, charakteryzuje się tym, że klasy są niezależne i słabo powiązane ze sobą oraz wykonują dokładnie określone czynności. Innymi słowy: w takim designie występują słaby coupling pomiędzy klasami i wysoka kohezja ich samych.

Rys. 3. Silny coupling i niska kohezja (po lewej) oraz słaby coupling i wysoka kohezja (po prawej)

Na teraz to tyle. Zagraj w Bingo w swoim projekcie, poszukaj symptomów gnijącego designu. Już niedługo wrócę z dwoma wpisami, w których szczegółowo opiszę pojęcia couplingu i kohezji.

Chcesz więcej JUŻ TERAZ? >>TUTAJ znajdziesz podcast DevTalk O Programowaniu Obiektowym<< z Tomkiem, autorem tego tekstu!

Trzymaj się ciepło i do przeczytania!

Nie przegap kolejnych postów!

Dołącz do ponad 9000 programistów w devstyle newsletter!

Tym samym wyrażasz zgodę na otrzymanie informacji marketingowych z devstyle.pl (doh...). Powered by ConvertKit

5
Dodaj komentarz

avatar
5 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
5 Comment authors
OliaMaciekMarekDamianMateusz Recent comment authors

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  Subscribe  
Notify of
Mateusz

Merytoryczna wiedza!

Niby człowiek wie ale zawsze dobrze sobie odświeżyć :)

Pozdrawiam, Mateusz.

Damian

Niestety, ale kilkukrotnie spotkałem się z tzw. ‘over-engineering’ w wielu projektach, jeżeli chodzi o architekturę.

Prosta aplikacja mająca kilka encji na krzyż, miała architekturę tak skomplikowaną, że zanim człowiek ogarnął co gdzie się znajduje – miał dość.

Uważam, że warto promować powiedzenie – “dobieraj narzędzia(architekturę) do problemu, a nie odwrotnie”.

Dobry wpis!

Marek

Pomocny materiał. Robię sporo grafiki dla firmowych mediów społecznościowych i już widzę, że sporo rzeczy muszę poprawić.

Maciek

Artykuł pełen przydatnej wiedzy. Dzięki!

Olia

Naprawdę świetny artykuł!

Moja książka

Facebook

Zobacz również