POIT #130: Dług technologiczny

Witam w sto trzydziestym odcinku podcastu „Porozmawiajmy o IT”. Tematem dzisiejszej rozmowy jest dług technologiczny.

Dziś moim gościem jest Dawid Yerginyan – Senior Software Developer w Boldare. Od kilku lat zajmuje się budową produktów cyfrowych dla klientów zagranicznych, głównie w branży energii odnawialnej. Jego obszarem specjalności są technologie backendowe i rozwiązania devopsowe. Miał też okazję współtworzyć popularne, open source’owe narzędzie marble.js. Aktywnie dzieli się swoją wiedzą, biorąc udział w webinarach, warsztatach i meetupach branżowych (jak np. Dev.js lub No Exceptions).

W tym odcinku o długu technologicznym rozmawiamy w następujących kontekstach:

  • czym jest dług technologiczny (technical debt)?
  • jak i dlaczego powstaje dług technologiczny?
  • czy dług technologiczny jest problemem? Komu zagraża?
  • kiedy dług technologiczny jest czymś naturalnym, a kiedy staje się problemem?
  • czy każdy rodzaj długu technicznego musi być jawnie komunikowany tzw. biznesowi czy użytkownikom?
  • jak można osobom nietechnicznym wytłumaczyć rolę i sposoby zarządzania długiem technicznym?
  • czy są jakieś obiektywne sposoby mierzenia długu technicznego?
  • jak dokumentować dług technologiczny?
  • jak zarządzać długiem technologicznym?
  • jakie możemy mieć strategie spłacania długu?
  • czy są jakieś różnice między długiem technologicznym w kodzie, architekturze i infrastrukturze?
  • po czym poznać, że dług technologiczny staje się krytyczny?

Subskrypcja podcastu:

Linki:

Wsparcie na Patronite:

Wierzę, że dobro wraca i że zawsze znajdą się osoby w bliższym lub dalszym gronie, którym przydaje się to co robię i które zechcą mnie wesprzeć w misji poszerzania horyzontów ludzi z branży IT.

Patronite to tak platforma, na której możesz wspierać twórców internetowych w ich działalności. Mnie możesz wesprzeć kwotą już od 5 zł miesięcznie. Chciałbym oddelegować kilka rzeczy, które wykonuję przy każdym podcaście a zaoszczędzony czas wykorzystać na przygotowanie jeszcze lepszych treści dla Ciebie. Sam jestem patronem kilku twórców internetowych i widzę, że taka pomoc daje dużą satysfakcję obu stronom.

👉Mój profil znajdziesz pod adresem: patronite.pl/porozmawiajmyoit

Pozostańmy w kontakcie:

 

Muzyka użyta w podcaście: „Endless Inspiration” Alex Stoner (posłuchaj)

Transkrypcja podcastu

To jest 130. odcinek podcastu Porozmawiajmy o IT, w którym z moim gościem rozmawiam o długu technologicznym.

Przypominam, że w poprzednim odcinku rozmawiałem i trendach w IT.

Wszystkie linki oraz transkrypcję dzisiejszej rozmowy znajdziesz pod adresem porozmawiajmyoit.pl/130

Ocena lub recenzja podcastu w Twojej aplikacji jest bardzo cenna, więc nie zapomnij poświęcić na to kilku minut. 

Nazywam się Krzysztof Kempiński, a moją misją jest poszerzanie horyzontów ludzi z branży IT. Środkiem do tego jest między innymi ten podcast. Zostając patronem na platformie Patronite możesz mi w tym pomóc już dziś. Wejdź na porozmawiajmyoit.pl/wspieram i sprawdź szczegóły. Jednocześnie bardzo dziękuję moim obecnym patronom. 

A teraz życzę Ci już miłego słuchania. 

Odpalamy! 

 

Cześć! Mój dzisiejszy gość to Senior Software Developer w Boldare. Od kilku lat zajmuje się budową produktów cyfrowych dla klientów zagranicznych, głównie w branży energii odnawialnej. Jego obszarem specjalności są technologie backendowe i rozwiązania devopsowe. Miał też okazję współtworzyć popularne opensourcowe narzędzie Marble.js. Aktywnie dzieli się swoją wiedzą, biorąc udział w webinarach, warsztatach i meetupach branżowych, m.in. dev.js czy No Exceptions. Moim i Waszym gościem jest Dawid Yerginyan. 

Cześć, Dawid! Bardzo miło mi gościć Cię w podcaście.

 

Cześć Krzysiek! Witam wszystkich, którzy będą słuchaczami. 

 

Dzisiaj z Dawidem będę rozmawiał o rzeczy, która występuje w każdym projekcie, nawet typu greenfield. Nawet w drugim dniu jego istnienia, jak się okazuje, czyli o długu technologicznym. 

Ale zanim do tego przejdziemy, to standardowy punkt programu zakłada, że pytam mojego gościa o to, czy słucha podcastów i jeśli tak, to może jest w stanie podzielić się listą ulubionych. Jak to jest u ciebie, Dawidzie?

 

Odpowiem tak, że znam ten standardowy element Twojego programu, co już w jakiś sposób sygnalizuje, że słucham podcastów. Aczkolwiek muszę powiedzieć, że nie jestem aktywnym słuchaczem, a na pewno nie wszystkiego, czego słucham. 

Jedyny podcast, który mnie wciągnął tak, że słucham od deski do deski, to jest Better Software Design, zdecydowanie. W czasach kiedy ten podcast był jeszcze aktywny, słuchałem Developer On Fire, taki bardzo pamiętny odcinek był z Alberto Brandolinim na temat EventStormingu. Niestety autor podcastu przestał być aktywny, wyłączył chyba nawet swojego Twittera i stwierdził, że już nie będzie w ogóle brał w tym udziału. Z branżowych jeszcze Porozmawiajmy o IT też słucham.

 

Dzięki!

 

Ostatnio to, co przykuło moją uwagę, to był odcinek na temat site reliability engineering, bardzo fajny, polecam! 

A tak pozabranżowo ostatnio zainteresowałem się podcastem, który nazywa się The Strong Towns, i jest to podcast, który próbuje wytłumaczyć, jak urbanistyka państw Ameryki Północnej źle wpływa na ich gospodarkę. Tak że jak ktoś jest zainteresowany, to polecam.

 

Szeroki przekrój. Dzięki wielkie! 

Dobrze. Na początku zaczniemy może od pewnych definicji, czyli właściwie od określenia czym jest ten dług technologiczny, czym jest technical debt, u o kogo zaciągamy ten dług, jak to po prostu działa? 

 

Dług technologiczny, czy techniczny, myślę, że można spokojnie używać tych słów zamiennie – nie wiem, które jest poprawne, zakładam, że technologiczny. 

W skrócie można powiedzieć, najprostszymi słowami, że jest to coś, co trzeba będzie zapłacić w przyszłości. Ktoś będzie musiał to zapłacić. Nie dotyczy to tylko kodu, to mogą być różne składowe oprogramowania, jakaś architektura, infrastruktura, takie rzeczy. 

Można porównać ten dług technologiczny do takiego długu finansowego, stąd chyba wzięło się to pojęcie. Po prostu jakiś dług, wygenerowany w naszych, można powiedzieć, artefaktach oprogramowania trzeba spłacić, bo jeżeli się go nie spłaci, to będzie generował jakieś odsetki, które będą na nas wpływać w jakiś sposób. Kogo może dotknąć? Przepraszam, pytanie było, u kogo dług zaciągamy. 

 

Tak.

 

Tak naprawdę wydaje mi się, że dług zaciągamy, choć nie wiem, czy ty się ze mną zgodzisz, u zespołu developerskiego, dlatego że to on jest tym, który będzie go spłacał. Niezależnie od tego, czy to jest zespół outsource’owy, czy to jest zespół inhouse’owy, to raczej oni będą, że tak powiem, dealować z tym długiem technologicznym. 

 

Tak, zgadzam się absolutnie. To jest zaciąganie długu u tych, którzy będą w przyszłości pracować nad tym projektem. W jakimś tam szczególnym przypadku to możemy też być my po prostu, autorzy, też się tak zdarza. 

Zresztą ja mam takie prywatne zdanie, że nie ma niczego złego w dłuższej pracy nad jednym projektem, bo to pozwala właśnie nam się zderzyć z tymi decyzjami, które kiedyś podjęliśmy i musimy teraz żyć z ich konsekwencjami. To jest więc fajna możliwość, nie tylko odpalanie co chwilę nowych projektów, ale też właśnie przez jakiś czas popróbowanie swoich sił w tych projektach, które trwają nieco dłużej. 

Chciałem teraz trochę odbić piłeczkę, bo nie wiem, czy się ze mną zgodzisz, ale w takim powszechnym mniemaniu dług technologiczny, technical debt jest kojarzony z tymi właśnie projektami, trwającymi już jakiś czas, tzw. brownfield. Czyli że tutaj już wiele lat się to wszystko rozwija, wielu developerów maczało tam swoje palce w tym kodzie, no i ten dług technologiczny narasta. 

Właśnie, chciałbym cię zapytać, czy ty się z tym zgodzisz, że to faktycznie jest domeną tych już takich leciwych projektów. I dopytać może też, jak i właściwie, dlaczego dług technologiczny powstaje?  

 

Czy jest to domeną wyłącznie takich długoletnich typu brownfield? Ja uważam, że nie. Mogę powiedzieć tylko, że na pewno one są bardziej podatne na takie znaczne obciążenie tym długiem, stąd biorą się te wszystkie nasze historie o legacy strasznym itd. Bo faktycznie im dłużej projekt trwa, im więcej osób się w nim zmienia, tym łatwiej jest o takie właśnie smaczki, gdzie ktoś coś pozostawi, nie zostanie to udokumentowane, później ktoś inny musi się z tym bawić, ale moim zdaniem nie. 

Dla mnie dług technologiczny to jest w ogóle taki naturalny efekt związany z rozwojem oprogramowania, chociażby dlatego, że on często kojarzy się z tym, że podejmujemy jakąś złą decyzję, nie wiedząc o niej albo podejmujemy ją nawet świadomie, z premedytacją na zasadzie: „teraz zrobimy to prościej, pójdziemy na skróty, skleimy dwa komponenty taśmą, a później w przyszłości będziemy chcieli to odkręcić”. Ale na dług technologiczny wpływa też taki efekt, że tak naprawdę wiedza, którą zdobędziemy w przyszłości, może podważyć nasze dzisiejsze decyzje. Czyli to, że ja dzisiaj się zdecyduję na stworzenie aplikacji w architekturze np. modularnego monolitu, w przyszłości może się na mnie odbić i stwierdzić, że to nie powinno być w ogóle tak. 

Tak że i w projektach greenfieldowych też może narastać dług technologiczny. Jest to związane z ciągłym rozwojem oprogramowania. On np. może powstać już na samym starcie, w pierwszych miesiącach życia produktu, bo wtedy najczęściej robimy jakieś prototypy, MVP, jest najwięcej zmian, jakichś pivotów. Wtedy też często jest duża presja czasu, bo np. chcemy wypuścić jakiś produkt już, od razu, najszybciej jak się da, żeby on zaczął zarabiać albo żeby w ogóle go przetestować. Tak jak już mówiłem, możemy też zaciągać ten dług z premedytacją, na zasadzie: „teraz pójdziemy sobie na skróty, szybciej wypuścimy nasz produkt, a poprawimy to później”. 

Wpływa na to też, nie wiem, czy słyszałeś takie pojęcie jak bit rot albo code rot. Chodzi o to, że z czasem, jak oprogramowanie nie jest utrzymywane w żaden sposób, to można powiedzieć, że ono gnije, rozkłada się, to jest takie pseudo stwierdzenie. Jak będziesz chciał posłuchać, to mogę potem opowiedzieć o tym jeszcze, ale chodzi o to, że oprogramowanie, które zostaje pozostawione samopas i nikt go nie wspiera, wiadomo, dezaktualizują nam się jakieś komponenty, dependency itd. Może się okazać, że jak ktoś będzie chciał za dwa lata coś zrobić w tym projekcie, to on się np. w ogóle nie zbuduje. 

 

No właśnie, to jest bardzo mądre, co powiedziałeś. Po pierwsze uczymy się projektu, pracując w nim. Pomiędzy bajki można włożyć coś takiego, że architekturę jesteśmy w stanie zaplanować sobie w tym pierwszym, zerowym sprincie, czy na początku i cały czas już według tych wytycznych podążać. My się po prostu uczymy, to otoczenie technologiczne, biznesowe się zmienia, więc tak jak mówisz, to jest związane z tym długiem technologicznym. 

Druga rzecz, o której powiedziałeś, to jest to, że ten dług technologiczny nam z czasem narasta, zwłaszcza jeśli go nie spłacamy, jeśli na bieżąco tego nie kontrolujemy, to w pewnym momencie możemy przejść już tę magiczną linię, za którą albo nie będzie miało zupełnie sensu tego długu spłacać, albo to będzie wręcz niemożliwe. 

To wszystko, co ty powiedziałeś, co ja trochę dopowiedziałem, może stawiać ten dług technologiczny w takim obrazie bardzo pejoratywnym, że to jednak jest coś bardzo, bardzo złego. Mówiliśmy tutaj nawet o zgniliźnie, więc to jest powiązanie bardzo jasne. Ale właśnie – czy zawsze dług technologiczny jest problemem? I komu on zagraża w projekcie?  

 

Można powiedzieć, że on zawsze jest problemem, tylko jego skutki nie zawsze są widoczne. Chodzi o to, że pewien poziom długu technologicznego nie jest groźny i nawet można powiedzieć, że sam jest wskazany, bo dzięki niemu jakoś tam rozwijamy tę naszą aplikację szybciej, ale czasami po prostu jak on się zbiera, nie ma takich natychmiastowych, oczywistych skutków, które informują nas o tym, że coś jest nie tak i warto by było z tym powalczyć. 

Można by było powiedzieć, że zagraża developerom, ponieważ oni później muszą walczyć w tym środowisku o to, żeby jakoś tę aplikację rozwijać, ale ja bym powiedział, że on zagraża całemu otoczeniu i wszystkim, którzy mają jakąkolwiek styczność z tym oprogramowaniem, które jest zadłużone. Czyli developerom, którzy się męczą przy jego rozwoju, można powiedzieć, że biznesowi, ludziom albo w ogóle całej organizacji, jej finansom. W taki sposób, że nie dowozimy ficzerów na czas, nasza konkurencja rozwija się szybciej. 

Może nawet wpływać na użytkowników, jeżeli mamy jakieś niestabilne oprogramowanie. Tutaj fajnym przykładem mogą być gry komputerowe. Często gry są np. rozwijane przez 10 czy 12 lat i jeśli ten dług się nawarstwi, to może się okazać, że nawet użytkownicy końcowi mają niezbyt przyjemne styczności z tym oprogramowaniem, bo np. ciężko jest rozwijać tę grę i jakieś aktualizacje wychodzą bardzo późno, gracze odchodzą. 

 

Jasne. Mówiłeś tutaj o tym, że możemy ten dług technologiczny, powiedziałbym świadomie zaciągać. Dobrym przykładem może być startup, kiedy powstaje gdzieś jakieś MVP, takie trochę na kolanie robione. 

W związku z tym chciałbym cię zapytać, kiedy ten dług technologiczny jest czymś naturalnym, a kiedy już staje się problemem?  

 

Myślę, że tutaj nie ma takiej jednoznacznej granicy, trzeba samemu sobie ocenić, zadeklarować jakieś drivery, które o tym świadczą, ale myślę, że w skrócie można powiedzieć, że wtedy, kiedy zaczyna nam przeszkadzać. Spowalnia na przykład naszą pracę, spowalnia development, jest jakimś źródłem dużej ilości błędów albo np. oprogramowanie zaczyna nam się zachowywać w jakiś nieprzewidywalny sposób. Na przykład chcemy wpłynąć na jakąś określoną część aplikacji, rozwijamy ją, a zmienia się pięć innych i mamy takie side effecty, że modyfikacja jakiejś części kodu wpływa nam na inną i nie mamy nad tym kontroli. To są już takie znaki, które mogą świadczyć o tym, że coś jednak jest nie tak. 

Może też wpływać na zadowolenie użytkowników bezpośrednio, czyli wiemy o tym, bo dostajemy feedback od użytkowników, którzy mówią nam, że aplikacja działa wolno albo mierzymy to w jakiś sposób, albo zgłaszają nam błędy.

 

Właśnie, to jest ciekawy wątek, bo zawsze kojarzymy ten dług technologiczny z czymś bardzo technologicznym, z taką powiedziałbym architekturą, która gdzieś tam na backendzie sobie leży i tam się ewentualnie coś złego może dziać. Ale czy każdy rodzaj długu technologicznego, według ciebie, musi być komunikowany gdzieś wyżej – do biznesu, do produktu, do użytkowników, jednym słowem mówiąc, czy jest taki jasny podział długu na coś bardzo backendowo-technicznego, który to obszar jest odpowiedzialnością developerów i inny rodzaj długu, który właśnie może dotykać użytkowników i o którym biznes powinien przynajmniej wiedzieć.  

 

Ja jestem zwolennikiem takiej wyraźnej transparencji, więc uważam, że wszystko powinno być komunikowane przynajmniej biznesowi. 

Natomiast jeśli chodzi o użytkowników, to tutaj bym się zastanowił, dlatego że komunikowanie niektórych rzeczy może wpływać negatywnie np. na naszą markę. Bo jeżeli wyślemy komunikat do użytkowników: „słuchajcie, oprogramowanie nam się wali, mamy niesamowitą ilość długu technicznego”, to to może źle na nas wpłynąć. Ale jeżeli są jakieś elementy, które mogą podbudować tych naszych użytkowników, utrzymać ich trochę przy naszej aplikacji, np. jeżeli powiemy im: „słuchajcie, mamy drobne problemy, ale jeżeli wy czekacie, to jesteśmy w stanie to naprawić”, to myślę, że warto to zakomunikować. 

Jedynie gdzie bym się zastanawiał, to sytuacja, gdy mamy jakiś dług, który jest taki marginalny, nieznaczny. Myślę tu o czymś takim, że jeżeli jest to dług w kodzie, to możemy go rozwiązać, zostawiając to do’s-a i ktoś, wchodząc do tego pliku następnym razem, po prostu to zrobi. Myślę, że takie rzeczy ewentualnie można by było pominąć. Ale tak poza tym, to ja jestem zdania, że dobrze jest komunikować, ponieważ jeżeli biznes jest świadomy tego długu, to później można to zaplanować w jakimkolwiek frameworku pracujemy.

 

Chciałbym jeszcze pociągnąć trochę ten wątek świadomości, bo my jako osoby techniczne, związane z IT, wiemy mniej więcej jaki jest impact, jaki jest wpływ tego długu technicznego taki krótkoterminowy, ale też długoterminowy. Wiemy, jaka jest waga, wiemy, jak ten dług zaciągamy i co będziemy musieli spłacać. 

Ale dla biznesu, zwłaszcza tego nieświadomego, to może być coś bardzo oderwanego od tej biznesowej domeny, coś, co jest ciężkie w zrozumieniu. Coś, co bardzo trudno jest przeliczyć na pieniądze, czy też inwestycja w ten obszar byłaby trudna do przeliczenia na pieniądze, w związku z tym może to być taki obszar trochę ignorowany. Dlatego chciałbym zapytać, czy znasz jakieś sposoby tłumaczenia osobom nietechnicznym, jaka jest rola długu technicznego, jak można nim zarządzać, jak można go spłacać?   

 

Jeszcze nawiążę do tego, że my rozumiemy impact tego, a niekoniecznie możemy być w stanie przełożyć to na pieniądze, straty, zyski, czy coś takiego – tak, jak najbardziej. I myślę, że skoro my jesteśmy inżynierami, specjalistami, architektami, to wydaje mi się, że to naszym zadaniem jest przyłożenie do tego odpowiedniej wagi. Można nawet powiedzieć, że my, jako zespół developerski albo programiści, architekci, inżynierowie jesteśmy takim stakeholderem jakości artefaktów naszego oprogramowania, więc wydaje mi się, że w naszym obowiązku jest wytłumaczenie tego biznesowi. Tak, jak tłumaczymy różne inne rzeczy związane z oprogramowaniem, np. że jest jakiś problem z danymi, incydenty, GDPR itd. Takie rzeczy się tłumaczy, wydaje mi się, że na porządku dziennym. 

I też postawmy się na miejscu drugiej strony – w momencie, kiedy pracujemy nad skomplikowaną domeną, niech będzie to źródło energii odnawialnej, to ten biznes, który tak bardzo nie rozumie tego naszego długu technologicznego, on też ma problem, żeby wytłumaczyć nam swoją domenę, w której operuje. Na przykład pojawiają się jakieś terminologie związane z urzędami rejestrującymi różnego rodzaju jakieś inwertery energetyczne. Oni też muszą nam to wytłumaczyć, nie mogą nas zignorować, więc my też nie ignorujmy ich. Starajmy się to im wytłumaczyć, używajmy różnego rodzaju metafor, jak np. finansowych. 

Kiedyś usłyszałem taką bardzo fajną metaforę od koleżanki z Boldare, która mówi, że dług technologiczny jest trochę jak gotowanie – jeśli chcesz sobie ugotować obiad, przygotowując go, kroisz marchewki itd., zostaje ci potem brudny blat, jakieś obierki itp. I to jest ten twój dług, który musisz posprzątać, zanim zaczniesz ponownie gotować, bo jak go nie posprzątasz, to wiadomo, co się stanie. 

 

 I też postawmy się na miejscu drugiej strony – w momencie, kiedy pracujemy nad skomplikowaną domeną, niech będzie to źródło energii odnawialnej, to ten biznes, który tak bardzo nie rozumie tego naszego długu technologicznego, on też ma problem, żeby wytłumaczyć nam swoją domenę, w której operuje. Na przykład pojawiają się jakieś terminologie związane z urzędami rejestrującymi różnego rodzaju jakieś inwertery energetyczne. Oni też muszą nam to wytłumaczyć, nie mogą nas zignorować, więc my też nie ignorujmy ich. Starajmy się to im wytłumaczyć, używajmy różnego rodzaju metafor, jak np. finansowych. 

 

Bardzo obrazowe, ale faktycznie może docierać. 

Muszę przyznać, że bardzo podoba mi się twoja odpowiedź, czyli po prostu nastawienie na komunikację i na obustronne zrozumienie. Nie stawianie siebie w takim obozie, który mówi: „ja to rozumiem, a to wy nie rozumiecie”, tylko raczej próba dogadania się, próba wzajemnego zrozumienia, która jest pewnie jedynym i najbardziej skutecznym sposobem, żeby jakoś wychodzić z tego długu technicznego, który powstaje na co dzień, nieraz niezależnie od tego, co byśmy zrobili. Bo trzeba też sobie jasno powiedzieć, że bardzo trudno jest znaleźć takie rozwiązania w IT   też w software developmencie, które są wolne od długu technicznego. To jest najczęściej jakiś rodzaj zrezygnowania z czegoś na korzyść czegoś innego, ale wiadomo – musimy iść na jakieś kompromisy.  

 

Dokładnie. 

 

Jeśli chodzi o to, czy jesteśmy świadomi tego długu technicznego albo czy w ogóle wiemy, że go mamy, to możemy się o tym przekonać, dostając bardzo niemiłą informację, że faktycznie mamy jakiś dług techniczny, bo coś np. przestaje działać. Może się okazać, że biznes czy produkt zwraca się do nas, że np. szybkość developmentu nam ostatnio mocno spada albo estymując jakieś kolejne rzeczy, wychodzimy na coraz większe czasy, bo zarządzanie tym długiem niestety stanowi dodatkową pracę. 

W związku z tym dążę do tego, że dobrze by było ten dług techniczny jakoś mierzyć, żeby być świadomym, ile go mamy i później jakoś nim zarządzić. Czy jest coś, co według Ciebie daje nam taką możliwość mierzenia długu technicznego? Jakieś metody, jakieś narzędzia, może jakieś podejścia?  

 

Taką żartobliwą miarą może być coś, co widziałem kiedyś w memie – „dług techniczny można zmierzyć, dając developerowi kod do przeczytania i słuchając ile razy poleci WTF z perminent. To może być jedna z miar. Oczywiście to jest żart, ale…

 

 Tak jak KPI. 

 

Tak, dokładnie – tak, jak KPI. 

Myślę, że narzędzi jest sporo. Możemy mierzyć jakąś złożoność cyklomatyczną naszego kodu, jakąś złożoność poznawczą, łącząc to z jakimiś prostszymi metrykami, jak chociażby pokrycie kodu, to, jakie mamy przedawnione biblioteki, ile mamy jakichś security vulnerabilities, podatności, ile mamy bugów – to są takie rzeczy, które można mierzyć. 

Z takich bardziej nieoczywistych może, to możemy mierzyć, może niekoniecznie czas w minutach, ale ile nam zajmuje onboarding nowego developera. Bo to, że nowy developer nie jest w stanie w miarę szybko wejść w nowy projekt, świadczy o tym, że czegoś w nim brakuje – dokumentacji czy po prostu ciężko zrozumieć domenę, przeczytać co siedzi w tym kodzie. 

Możemy też korzystać z jakichś bardziej zaawansowanych technik, które stawiają już na liczby, jak np. Technical Debt Ratio czy SQALE, czyli Software Quality Assessment based on Lifecycle Expectations. I to są metryki, które może mierzyć nam np. narzędzie SonarQube. SQALE właściwie można powiedzieć, że opiera się na tym samym, co wymieniłem przed chwilą, czyli testowalności kodu, readability, jak bardzo jest podatny na zmiany, jaki ma performance, czy jest bezpieczny, czy jest utrzymywalny, czy łatwo go portować na inne środowiska, czy np. kod jest reużywalny, mierzy, ile razy pojawia się duplikacja kodu, znajduje jakieś codes smellsy i na podstawie tego może, że tak powiem, wypluć nam jakiś wynik, jaki jest poziom naszego długu technicznego.

Myślę, że warto to mierzyć, ale to są już takie rzeczy, że myślę, że ustawienie tego w swoim procesie zajmuje dużo czasu i to faktycznie będzie przydatne w projektach, które są duże, mają wiele zespołów, myślę, że setki ludzi na spokojnie. 

Ja mam też takie podejście troszeczkę prostsze. Nie wiem, czy się ze mną zgodzisz, ale ja uważam je za obiektywne. Jeżeli zgodzisz się ze mną, że story pointy są miarą obiektywną, to zgodzisz się, że taka metoda też jest. Przeczytałem kiedyś o niej na blogu technicznym Riot Games, to jest game developer, który stworzył sławną grę League of Legends. Ich Engineering Manager napisał o tym, jak oni kategoryzują w ogóle dług technologiczny i jak sobie z nim radzą, jak go mierzą. 

Wymienił coś takiego, że można skategoryzować, a właściwie nadać cechy długowi w postaci tego, jaki on ma impact, jaki on ma wpływ na organizację czy cokolwiek, jaki jest koszt jego naprawienia, czy spłacenia tego długu i jak bardzo jest on podatny na rozprzestrzenianie, tam jest użyty taki termin jak contagion – zaraźliwość. I wtedy jakiś określony fragment długu technologicznego, który znajdziemy w naszej aplikacji, jakiś po prostu code smell czy coś takiego, można ocenić w tych kategoriach na skali 1 do 5 albo na przykład w skali story pointów. 

I w ten sposób mamy porównanie, które elementy naszego długu technologicznego są gorsze, które są lżejsze, a które może warto szybciej zaadresować. I to też pomaga nam priorytetyzować i mieć ogląd. Nie są to takie twarde, suche dane czy liczby mówiące, że u nas jest np. 5% długu technicznego, ale wydaje mi się, że to i tak jest spoko metoda, która jest znacznie prostsza i szybsza w implementacji niż postawienie np. SonarQube’a na całą organizację i zdefiniowanie wszystkich tych metryk. 

 

Wymienił coś takiego, że można skategoryzować, a właściwie nadać cechy długowi w postaci tego, jaki on ma impact, jaki on ma wpływ na organizację czy cokolwiek, jaki jest koszt jego naprawienia, czy spłacenia tego długu i jak bardzo jest on podatny na rozprzestrzenianie, tam jest użyty taki termin jak contagion – zaraźliwość. I wtedy jakiś określony fragment długu technologicznego, który znajdziemy w naszej aplikacji, jakiś po prostu code smell czy coś takiego, można ocenić w tych kategoriach na skali 1 do 5 albo na przykład w skali story pointów. 

 

Pewnie. Ja myślę, że obojętnie jakiej metody byśmy tutaj nie wzięli, to i tak będzie lepiej, niż gdybyśmy w ogóle nie brali żadnej. W sensie jakakolwiek forma mierzenia jaki ten dług techniczny jest, jest lepsza niż żadna. 

Podoba mi się to, co powiedziałeś, że niektóre z tych narzędzi, jak np. te związane z coveragem czy z analizą statyczną, da się jakoś nawet włączyć w proces CI/CD i mieć ten feedback tak w miarę na bieżąco. 

Zgodzę się też absolutnie z tym, że patrzenie, jak nam spada ta szybkość developmentu to też jest jakiś objaw faktycznie długu technicznego. Jeśli się okaże, że mamy coraz więcej bugów, coraz więcej jakichś ticksów związanych z security, z podbijaniem paczek itd., no to faktycznie jest to jakiś obraz tego, że ten dług techniczny rośnie. 

To, co ja teraz nieraz też robię w projektach, to jest taka próba spisywania sobie mniej więcej ile developer, szacunkowo oczywiście, poświęca w ciągu dnia czasu np. na nowe ficzery, na bugi, fixy, związane z bezpieczeństwem, podbijanie paczek itd. Jak się na to spojrzy, nawet jeśli jest bardzo ogólnie zrobione, to od razu widać w czasie, jak to się zmienia i widać też, że jeśli w miarę na bieżąco się tego długu technicznego, przynajmniej tego związanego z takim mocnym impactem na biznes, nie próbuje łatać, to to się akumuluje w czasie i później faktycznie ta szybkość developmentu nam spada.   

 

Dokładnie. Można też zawsze, choć może to nie jest już takie obiektywne, ale zwyczajnie popatrzeć – jeżeli pracujecie w jakichś zwinnych oczywiście frameworkach, jak nie wiem, Scrum na przykład – historycznie, np. jaka była średnia wysokość takiego przeciętnego ficzera, storiesa w story pointach i porównać ją np. dzisiaj. Co było pół roku temu, a co było dzisiaj. 

Oczywiście to może odbiegać od realiów, bo np. teraz możemy po prostu robić grubsze rzeczy, niż wtedy, ale można mniej więcej, tak poznawczo spróbować porównać, takie powiedzmy, średnie rzeczy pół roku temu, a średnie rzeczy teraz i zobaczysz, że np. estymata jest znacznie wyższa – to znaczy, że roboty jest tyle samo, ale złożoność tego jest większa, trudniej jest to po prostu wprowadzić, wdrożyć. 

 

Dokładnie. Na podobny powiedzmy ficzer, musimy poświęcić więcej czasu, żeby go finalnie dowieźć, dokładnie tak. 

Ok, powiedzieliśmy trochę o mierzeniu długu technicznego. Dług techniczny można też dokumentować. Z racji tego, że często jest on związany z jakimiś decyzjami, które podejmujemy, idziemy w tym kierunku, a nie w tamtym, w związku z tym świadomie albo nieświadomie zaciągamy jakiś dług. Jeśli jesteśmy w miarę tego świadomi, to możemy to jakoś udokumentować. Decydujemy się np. na taki framework, taką bibliotekę, cokolwiek i w związku z tym wygeneruje to taki, a nie inny efekt. 

Wydaje mi się, że dokumentowanie długu technicznego jest też istotne w momencie, kiedy trafiamy na jakiś projekt, już taki np. wieloletni i tam niczego takiego nie ma i tak naprawdę nie ma też testów, co też oczywiście się zdarza, nie wiemy, gdzie jesteśmy, w związku z tym musimy przynajmniej go dokumentować, ten punkt startowy.

Chciałbym cię zapytać o twoje doświadczenia, twoje opinie, twoje zdanie na temat właśnie dokumentowania długu technicznego – czy to w ogóle warto  ? Jeśli tak, to może, w jaki sposób? 

 

Nie jestem wielkim fanem dokumentowania. Powiedziałbym, że jestem raczej przeciwnikiem, ale tutaj muszę się zgodzić z tym, że warto to robić, bo to wspomaga tę wcześniej wspomnianą transparencję. Ja na przykład robię to w postaci, chociażby wpisywania tego do backlogu tak naprawdę. Wrzucanie elementów spłaty długu technicznego do backlogu – w ten sposób biznes o tym wie, product owner, chociażby o tym wie. Można to jakoś trackować, priorytetyzować, dzięki temu nie zapomina się o tym przede wszystkim. 

Druga opcja to jest wiadomo, to do’s-y w kodzie – bardzo w porządku. Albo jakieś informacje o tym, że coś zostało deprecated – to wszystko jest w porządku, na zasadzie wrzucamy to do’s-a i mówimy: „to powinno zostać usunięte po tym releasie, bo już ta część kodu nie będzie nigdy używana albo coś tam”. 

I kolejna rzecz, związana z decyzjami, o których mówiłeś. Tutaj wydaje mi się, że świetnie sprawdzają się ADRy – Architecture Decision Record, gdzie jeżeli podejmujemy jakąś decyzję pójścia na skróty, możemy to udokumentować, napisać od razu, jaka byłaby opcja alternatywna, która kosztuje nas więcej, zajmuje więcej czasu. Możemy podać, co nami kierowało w wyborze tej decyzji, wtedy ktoś, kto np. wpadnie do projektu, będzie wiedział, jaka była jego historia, dlaczego taka decyzja została podjęta, co było rozważane innego i tak naprawdę na podstawie tego może sobie wnioskować albo po prostu wymyślać co dalej z tym zrobić.

 

I kolejna rzecz, związana z decyzjami, o których mówiłeś. Tutaj wydaje mi się, że świetnie sprawdzają się ADRy – Architecture Decision Record, gdzie jeżeli podejmujemy jakąś decyzję pójścia na skróty, możemy to udokumentować, napisać od razu, jaka byłaby opcja alternatywna, która kosztuje nas więcej, zajmuje więcej czasu. Możemy podać, co nami kierowało w wyborze tej decyzji, wtedy ktoś, kto np. wpadnie do projektu, będzie wiedział, jaka była jego historia, dlaczego taka decyzja została podjęta, co było rozważane innego i tak naprawdę na podstawie tego może sobie wnioskować albo po prostu wymyślać co dalej z tym zrobić.

 

Tak, dokładnie. Myślę, że przynajmniej jakieś takie zdawkowe dokumentowanie tego, takich grubszych rzeczy, bo oczywiście nie ma się co czepiać drobnych. Myślę, że w pewnym momencie ta inwestycja może nam się po prostu zwrócić. 

Mówiliśmy tutaj sporo o tym, że dług, o którym rozmawiamy, jest problemem, czy też może być problemem dla zespołu developerskiego. To jest najbardziej oczywiste, ponieważ to są osoby, które na co dzień są odpowiedzialne, przynajmniej miejmy nadzieję, że są odpowiedzialne za swój kod, więc będą musiały się mierzyć z podjętymi wcześniej decyzjami. 

Może być to też problematyczne w jakiś sposób dla biznesu, bo spada nam, chociażby np. ta możliwość szybszego wytwarzania kodu, trzeba inwestować w tzw. maintenance itd. 

Jak to jest natomiast z klientem? Przychodzi klient, dostał od software house’u, obojętnie, to w sumie może być dowolna firma programistyczna. Zamawia jakiś produkt, dostaje kod – czy dla niego w ogóle temat długu technicznego powinien istnieć? Czy on może w jakiś sposób to ugryźć?  

 

To zależy, co ten klient będzie chciał zrobić z tym oprogramowaniem. Jeżeli to jest klient, który wpada np. po prototyp, żeby coś przetestować, to myślę, że średnio może go interesować ten dług technologiczny. Zwaliduje sobie jakąś swoją hipotezę, no i potem będzie chciał rozwinąć ten produkt albo z tym samym software housem, albo z innym, albo inhousoe’wo będzie chciał to sam stworzyć. 

Natomiast jeżeli ma jakieś plany na przyszłość związane z tym, że to już nie jest prototyp, to fajnie byłoby, żeby się tym zainteresował, choć tak naprawdę jeżeli jest się software housem, to fajnie byłoby tego klienta o tym uświadomić, powiedzieć mu jak to wygląda. Jeżeli on np. powiedzmy, miał jakiś dosyć ciasny budżet i niewiele czasu, to powiedzieć mu, jakie decyzje zostały podjęte, co zrobiliśmy i co wypadałoby zrobić w przyszłości, żeby ten produkt mógł się jakoś bardziej zeskalować czy wpasować w swój rynek.

 

Czyli wracamy znowu do transparencji, ale myślę, że to jest owszem, czasem trudne, ale bardzo potrzebne, ponieważ buduje taką długofalową po prostu relację, a to jest w biznesie bardzo ważne. 

No to teraz przechodzimy do takiego nieuchronnego pytania. Długi trzeba spłacać, a przynajmniej się powinno. Chcę cię zapytać jak zarządzać takim długiem technologicznym? Jak sobie z nim radzić w projekcie, który się ciągle zmienia, w którym te przyrosty są co sprint, codziennie, co tydzień? Jak sobie radzić w takim projekcie z długiem technologicznym? 

 

Czyli zakładamy, że to jest taki projekt, który raczej jest utrzymywany. 

Może zacznę jeszcze trochę z drugiej strony – jeżeli to jest projekt, który np. odziedziczyliśmy, jakieś legacy czy brownfield, to tutaj trzeba będzie zastosować jakieś rzeczy pokroju audytu kodu, zbadania tego, co tam jest najpóźniej, jakiejś takiej ścieżki do tego, żeby z tego wybrnąć. 

Z doświadczenia raczej zauważyłem, że przepisywanie nie kończy się dobrze, bo często jest tak, że: „ooo, z tym się nie da nic zrobić, trzeba to przepisać”. Myślę, że to raczej w 90% przypadków jest zły wybór. Można zastosować tam jakieś wzorce, które spróbują wygasić ten system powoli, na rzecz jakiegoś nowego, który jest lepiej skonstruowany. 

A jeżeli chodzi o takie projekty, które się ciągną ze sprintu na sprint, mamy przyrost, faktycznie dużo się w nich dzieje, to myślę, że trzeba przyjąć takie założenie, że spłacamy ten dług non stop, robimy continuous refactoring, jesteśmy transparentni.  

W przypadku zaciągania świadomie tego długu piszemy ADR-a – wrzucamy tę drugą część do backlogu, która powinna zostać zrobiona lepiej. Priorytetyzujemy to w jakiś sposób, normalnie planujemy to w sprintach, jeżeli nie jesteśmy w stanie czegoś rozwiązać. Np. w kodzie wrzucamy jakiegoś to do’s-a, prosimy na cold review, żeby nam ktoś pomógł. Jeżeli nie pomoże, to niech ten to do’s sobie wisi, niech ktoś to rozwiąże w przyszłości. 

Można też zastosować jakieś głębsze rzeczy. Ja np. ostatnio interesuję się bardzo evolutionary architecture. Nie zastosowaniem tego jeszcze nigdy w praktyce, ale to też jest fajny sposób na to, żeby tego długo unikać, czyli definiujemy sobie jakieś tam drivery naszej architektury, które informują nas o tym, że w tym momencie wypadałoby zrobić może jakąś zmianę, pivot, cokolwiek w tej architekturze, żeby ona była bardziej dopasowana do tego co robimy. No i korzystać na przykład z automatyzacji, sprawdzać pokrycie testami, sprawdzać vulnerabilities,  wrzucić sobie jakiegoś Dependabota, który nam wystawia MRki z podbitymi paczkami itd.

 

Chciałbym jeszcze pociągnąć ten temat strategii spłacania długów. W przypadku zwykłego długu możemy go nadpłacać, możemy go spłacić jednorazowo, możemy go spłacać w wielu ratach, a właśnie jak to jest z długiem technologicznym? Czy według ciebie sprawdzają się strategie pod tytułem „specjalne sprinty”, które na to są przeznaczone? Czy też może continuous refactoring, że wręcz przy prawie każdym pull requeście, który robimy, jest jakaś forma spłacenia, jakaś część polegająca na spłaceniu zastanego długu, a może np. część sprintu powinna być na to przeznaczona? Jakie strategie według ciebie sprawdzają się najlepiej? 

 

Myślę, że jeżeli jesteśmy transparentni z naszymi stakeholderami, czy jesteśmy w jakiejś firmie inhouse’owej z jakimś Engineering Managerem, czy to jest nasz klient, kiedy jesteśmy usługodawcą, to myślę, że wszystko tak naprawdę zadziała tak, jak się z nim dogadamy. 

Ale myślę, że lepiej starać się zwiększać częstotliwość tego spłacenia długu, czyli nie starać się robić tak, że np. trzaskamy ficzery przez pół roku, a potem robimy sobie dwa sprinty na refactoring i spłatę długu, a potem znowu. Bo już widziałem takie historie, że w przypadku np. software house to jest tak, że robimy sobie sprint na refactoring, potem trzaskamy ficzery i potem mówimy klientowi, że znowu refactoring, a  on mówi: „no ale jak to, przecież przed chwilą robiliście!”. 

 

Właśnie, myślę, że ważne jest to dogadanie się z tym przysłowiowym biznesem, bo nieraz bardzo trudno jest zaakceptować osobom produktowo-biznesowym, że np. zatrzymujemy tę produkcję na tydzień, dwa, miesiąc, jakkolwiek trzeba. 

Lepiej z mojego doświadczenia wychodzi jednak „przemycanie” takich zadań właśnie refactoringowych albo podbijania paczek, czy czegokolwiek takiego w sprintach. To, co powiedziałeś właśnie wcześniej – że gdzieś tam dodajemy to w miarę na bieżąco do backlogu. 

I tutaj jest trochę nasza odpowiedzialność, nasza w sensie myślę tutaj developerów, że jeśli widzimy, że coś takiego jest, to najczęściej my jesteśmy świadomi, że coś takiego istnieje jak dług techniczny w tym kodzie, więc tworzymy np. ten issue gdzieś tam na GitHubie, Dearze, gdziekolwiek, żeby to nam nie uciekło, a później staramy się to też włączać po prostu w te normalne sprinty, żeby to w miarę na bieżąco było usuwane, żebyśmy nie musieli zatrzymywać tej przysłowiowej produkcji na jakiś tam czas, bo to zawsze trudno sprzedać niestety. Bardzo trudno jest biznesowi zaakceptować. że musimy się zatrzymać i teraz robić refactoring. 

 

Tak, dokładnie. Ja się z tym zgadzam w stu procentach, że to zdecydowanie jest lepsze rozwiązanie. Najlepiej kiedy klient jest świadomy, wie, że takie rzeczy istnieją w backlogu i tak naprawdę trzeba się nimi zająć.

Reguła skauta jest w porządku – jeżeli np. ruszamy jakiś plik, w którym są to do’s-y, to rozwiążmy je albo na przykład załóżmy, że zmieniliśmy trochę architekturę albo styl pisania, załóżmy, że nagle pojawiło się functional programming, a mamy sporo jakichś komponentów klasowych i chcemy zrobić jakąś zmianę. Niech będzie to frontend i React  i powiedzmy mamy komponent klasowy, ale przyjęliśmy sobie zasadę, że od teraz piszemy tylko i wyłącznie komponenty funkcyjne czy jakieś stateless, to zamieńmy tę klasę może na ten funkcyjny. To nie jest taki big deal, zróbmy to po prostu, będzie jedna rzecz mniej.

 

A czy myślisz, że są jakieś różnice w stopniu np. oddziaływania długu technologicznego, związanego z kodem, z architekturą, z infrastrukturą? Czy to jest wszystko w jednym worku, czy też może znaczenie różnych tych typów jest inne? 

 

Różnice myślę, że na pewno są albo mogą być, ale nie powiedziałbym, że to jest ściśle powiązane z tym, czy to jest dług na poziomie kodu, architektury, czy infrastruktury. Na pewno w jakiś sposób może to być powiązane, ale ja bym to próbował bardziej kategoryzować, tak jak już wspominałem o tym artykule Riot Games, żeby patrzeć na impact, jaki jest koszt naprawy czegoś takiego, jak bardzo to się jakby rozprzestrzenia.

Jeżeli mamy np. jakiś dług technologiczny w architekturze, który powoduje, że wszystkie klasy piszemy w jakiś określony sposób, i to jest zły sposób, to na pewno to ma jakiś wyższy priorytet i wpływ na nas niż coś, co jest lokalne, w obrębie jednego endpointu na backendzie, czy coś takiego. Ale ja tutaj raczej bym chyba nie wiązał tego z infrastrukturą czy z architekturą, że np. dług technologiczny w architekturze jest znacznie gorszy, niż dług technologiczny w kodzie, tylko bardziej analizował to pod kątem tego, jaki to ma na nas wpływ.

 

Ok, pewnie. Myślę, że bardzo dobra odpowiedź. 

Długu technologicznego nie musimy spłacać, tak samo jak nie musimy spłacać długu bankowego, do momentu aż komornik nie zapuka do naszych drzwi. 

Czy w przypadku długu technicznego jest podobnie? Czy istnieje taki moment krytyczny, powiedzmy, że od tego momentu już wiemy, że nie ma innej możliwości  – musimy zatrzymać tworzenie ficzerów i  po prostu skupić się na tym refactoringu, bo inaczej nam się cały projekt przewróci? Czy coś takiego istnieje? Czy to jest raczej takie ciche i trudno jest taki moment złapać? 

 

To raczej jest ciche i trudno, to znaczy mi się wydaje, że jest trudno to złapać, że to zawsze przychodzi jakby z opóźnieniem. Dowiadujemy się o tym, że jest grubo, źle, już długo za późno. Ciężko jest znaleźć taki punkt, bo to troszeczkę tak, jak z takimi zasadami np. dobrego cold review i pull requestów, że mówimy, że np. jakiś branch i merge request nie powinien wisieć x czasu, no ale czasami robimy od tego odstępstwa, bo się nie da, czasami coś musi dłużej poczekać. 

Wydaje mi się, że tutaj zasada jest podobna, że musimy chyba podejść troszeczkę na zdrowy rozsądek, że nie da się wyznaczyć konkretnej daty, terminu albo jakiejś liczby, przy której mówimy: „o nie, teraz to już nie, teraz to już trzeba spłacać”. Najlepiej pewnie spłacać najszybciej jak się da, czyli jeżeli mamy jakiś dług, starajmy się zaplanować spłacanie tego najszybciej jak się da –  tak, żeby nie pokrzyżowało to naszych planów biznesowych, czyli gdzieś tam między ficzerami.

 

Wydaje mi się, że tutaj zasada jest podobna, że musimy chyba podejść troszeczkę na zdrowy rozsądek, że nie da się wyznaczyć konkretnej daty, terminu albo jakiejś liczby, przy której mówimy: „o nie, teraz to już nie, teraz to już trzeba spłacać”. Najlepiej pewnie spłacać najszybciej jak się da, czyli jeżeli mamy jakiś dług, starajmy się zaplanować spłacanie tego najszybciej jak się da –  tak, żeby nie pokrzyżowało to naszych planów biznesowych, czyli gdzieś tam między ficzerami.

 

Dokładnie, czyli najlepiej nie doprowadzać do takiej sytuacji. Najlepszą metodą, żeby nie doprowadzić do takiej sytuacji, jest po prostu w miarę na bieżąco przeprowadzać badanie, mierzenie, szacowanie tego długu, żeby wiedzieć, czy już nie jest za późno. Myślę, że to jest tak samo, jak z naprawą błędów, gdzie im wcześniej w tym cyklu wytwarzania oprogramowania błąd zidentyfikujemy i go naprawimy, tym mniej on nas będzie kosztował – i tutaj pewnie jest podobna sytuacja. 

A teraz chciałbym cię zapytać o twoje doświadczenia, twoje osobiste, ale też z Boldare, jak to robicie, jeśli chodzi o zarządzanie właśnie długiem technologicznym? Czy macie jakieś metody, czy ty masz jakieś metody na jego uniknięcie albo minimalizowanie? 

 

Myślę, że uniknąć się nie da nigdy, dlatego że np. projekty, które realizujemy w Boldare mają taką specyfikę, że np. dużo rzeczy może się zmienić, robią jakieś pivoty, klient ma inny pomysł albo nasze hipotezy po prostu się nie sprawdzają i trzeba sprawdzić coś innego. 

No i ja też wychodzę z takiego założenia, że tak jak już chyba wcześniej mówiłem, to czego nauczysz się jutro, wpłynie na to jak będziesz postrzegał decyzję, którą podjąłeś dziś. Ciężko więc jest tak myśleć z wyprzedzeniem na zasadzie: „mhm teraz to zrobię, to może jutro nie będzie długu technologicznego”. 

Bardziej transparencja i planowanie, tak jak już wiele razy wspominaliśmy tutaj, żeby nie bagatelizować tego długu, odpowiednio nim zarządzać. Jeżeli zaciągamy go świadomie, dokumentujmy to sobie, będziemy potem wiedzieć, że to ciąży na nas cały czas i trzeba to spłacić. No i wiadomo, continuous refactoring. 

Ze swojego doświadczenia mogę podać kilka przykładów. Ostatnio miałem taką sytuację, z mojego błędu oczywiście, że w systemie, który my tworzymy mamy kolejki, które są oparte na brokerze RabbitMQ. Mieliśmy zlokowanego tego Rabbita w wersji trzeciej, po prostu 3. Więc w momencie, w którym wyszedł update np. z 3.8 na 3.9, on został automatycznie zbumpowany u nas, dlatego że nie mieliśmy zlokowanych tych minorów, a RabbitMQ nie stosuje się do semantic versioning, bo oni tak mają. 

No i w takiej sytuacji wstajesz rano i patrzysz, że kolejki nie działają. I co możesz zrobić teraz? Możesz np. poszukać zmiany, która to spowodowała, patrzysz, jaką teraz wersję próbujesz zdiployować tego Rabbita, widzisz, że to jest 3 9. Więc co robisz? Patrzysz, że w tym przypadku akurat to była zmiana taka, że RabbitMQ usunął wszystkie zmienne środowiskowe konfiguracyjne i powiedział, że od teraz trzeba robić to za pomocą pliku. Lokujesz więc sobie tego Rabbita w wersji 3.8 przed tą zmianą i tak naprawdę wrzucasz do backlogu, planujesz to, tu już niekoniecznie musisz pisać ADR-a, bo to nie jest decyzja zaplanowana, tylko coś, co robisz na teraz, żeby przywrócić system do stanu, powiedzmy, operacyjnego. I wrzucasz to do backlogu, że trzeba tego Rabbita podbić na wersję 3.9 i możesz zrobić to sobie później – i w ten sposób masz już zaplanowaną spłatę tego długu, który powstał w taki sposób, że masz nieaktualną wersję swojej kolejki.

 

 Właśnie, bardzo fajnie podałeś metodę, przykład na to, w jaki sposób zarządzać długiem technologicznym. Tak jak powiedziałeś, nie da się tego z wyprzedzeniem przewidzieć, ponieważ uczymy się na temat obecnych decyzji, będziemy wiedzieli dopiero w przyszłości, czy to były dobre decyzje, a jeśli nie, to dlaczego niedobre. 

 

Mam jeszcze jeden fajny przykład, jeżeli chcesz posłuchać.

 

Śmiało, pewnie. 

 

Jak zaczynaliśmy rozwijać ten produkt, który już teraz ma dwa i pół albo trzy lata nawet, zaczęliśmy tworzyć tę usługę w takiej bardzo, można powiedzieć, CRUD-owej wersji, na zasadzie endpointy, które tworzą encje, usuwają, modyfikują itd. Ale z czasem zauważyliśmy, że po prostu problematyka i domena jest bardzo złożona i cała platforma, wszystkie zespoły zaczęły troszeczkę bardziej analizować tę domenę, wytworzyły sobie jakiś wspólny język Ubiquitous Language, i w ten sposób zaczęliśmy troszeczkę odpływać w stronę domain-driver design i architektury opartej o zdarzenia, bo naprawdę bardzo dużo zdarzeń się tam działo. 

Trafiliśmy w naszym produkcie na moment, w którym mieliśmy dużo tych CRUD-ów i nagle zaczęły się pojawiać jakby moduły systemu, które są w pełni zdarzeniowe. I teraz co robić? To, co zrobiliśmy, to w momencie, w którym na przykład wpadał jakiś ficzer, który dotyczył jakiegoś modułu sprzedażowego konfiguracji, to stwierdzaliśmy, że skoro będziemy grzebać przy tym endpoint’cie, to od razu zrobimy go event-driven, a te długi, które nie są zaplanowane w postaci żadnych ficzerów, wrzucimy zwyczajnie do backlogu na takiej zasadzie, że jak nam zostaną te endpointy pod koniec, to po prostu weźmiemy i zmienimy je z CRUD-owych na takie oparte na zdarzeniach.

 

Właśnie, bardzo często warto to robić przy okazji, tak jak powiedziałeś. Wtedy łatwiej jest przełknąć to produktowi, biznesowi też jakoś tak przy okazji, no i wówczas i tak rozgrzebując jakąś funkcjonalność, musimy się z nią najczęściej ponownie zaznajomić, jak to zostało zaimplementowane, dlaczego akurat tak, więc jesteśmy już na bieżąco. Znacznie łatwiej jest robić wtedy takie grubsze zmiany, niż byśmy specjalnie chcieli tylko taki dług technologiczny spłacać. 

A myślę, że warto też dodać, że nie każdy dług technologiczny warto tak całościowo spłacać, bo może się zdarzyć, i ze względów biznesowych, i jakichś technologicznych, po prostu się gdzieś na końcu nie kalkuluje, nie zwraca, i pewnie nie opłaca.  

 

Tak, może się to zwyczajnie nie opłacać.

 

Właśnie i nieraz mamy taki zmysł perfekcjonisty, my jako programiści, chcielibyśmy, żeby wszystko było zgodne z najnowszymi technikami i sposobami tworzenia, najnowsze biblioteki itd. Wtedy czujemy, że to jest fajny kawałek kodu, a okazuje się, że niestety albo stety, to, co robimy, służy gdzieś dalej biznesowi, służy użytkownikom. Jeśli po prostu te zmiany, które planujemy wprowadzić, nie przełożą się na nic, to tak naprawdę jest to trochę stracona  praca. 

 

Dokładnie, myślę, że tutaj dobrą metodą jest po prostu spojrzenie na zasadzie good enough. Załóżmy, że mamy jakąś aplikację i mamy jakiś problem z performancem w niej, ona jest niewydajna. Właśnie, pamiętajmy, że przedwczesna optymalizacja też nie jest zbyt dobra. Jak już coś optymalizujemy, to też zróbmy to good enough, na zasadzie sprowadźmy, załóżmy requesty do czasów, które są rozsądne i akceptowalne, a nie próbujmy przerobić całego kodu na najszybszą maszynę na świecie, bo może to doprowadzić do tego, że nasz kod przestanie być czytelny. Zamiast używać jakichś tam metod na arrayach JavaScriptowych, to zaczniemy trzaskać wszystko w pętle albo w ogóle napiszmy wszystko w asemblerze, to będzie jeszcze szybciej.

 

Właśnie, więc jest wiele takich warstw, które trzeba wyważyć i to po prostu musi mieć jakiś tam logiczny sens. Niekoniecznie dążyć do tego, żeby się jakieś tam liczby czy KPI-e  na końcu zgadzały. 

Dobra, doszliśmy do takiego, mam wrażenie, wspólnego zdania, że próba przewidzenia długu technologicznego nie ma sensu i takie premature optimization, o czym właśnie powiedziałeś, to jest też złe podejście. 

Teraz chciałbym cię na koniec jeszcze zapytać, czy w Boldare macie jakieś takie procesowe, metodyczne podejście do tego, żeby usuwać dług technologiczny? Może ty masz jakieś takie swoje doświadczenia albo dobre praktyki, które już konkretnie z usuwaniem długu technicznego są związane? 

 

Takich sformalizowanych praktyk i procesów  nie mamy. Myślę, że ze względu na to jak w tej chwili działa nasza organizacja. Jesteśmy, wydaje mi się, mocno rozproszeni, bardzo autonomiczni w obszarach, w których działamy, więc myślę, że takich procesowych, odgórnie narzuconych przez Boldare rzeczy nie ma. 

Ale to, co często praktykujemy, kiedy np. zderzamy się z aplikacją brownfieldową albo z jakimś legacy, to zaczynamy tak naprawdę od audytu kodu. Mówimy klientowi, że spoko, my na to spojrzymy, chcemy po prostu przeanalizować, co tam się dzieje. W zamian dostaniesz audyt kodu, który wypunktuje ci, co w tym jest nie tak. To jest dla nas też świetna informacja, od czego warto byłoby zacząć, w jakim stanie jest ta aplikacja. A potem to już trzeba tak naprawdę dobrać metodę do problemu.Pewnie jeżeli to jest jakiś harde Legacy i takie, że faktycznie nie można nic z tym zrobić, to np. budujmy wokół tego, spróbujmy budować jakieś anti-corruption layer, które komunikuje się z tym i zabezpiecza ten nasz system przed tym brzydkim legacy. Albo próbujmy, rozwijając jakieś elementy tego systemu, budować je w postaci nowych modułów i wygaszać poniekąd tamte stare elementy w jakimś wzorcu Stranglera czy coś takiego. 

Albo próbujmy spłacać to – jeżeli aplikacja nie jest w jakimś strasznie złym stanie, to spróbujmy spłacać to wraz z jej rozwojem. Możemy też sobie oczywiście to dawkować, np. stwierdzić, że jeżeli ta aplikacja jest taka sobie, to część rzeczy możemy zrobić jakby upfront np. podbić od razu jakieś najważniejsze paczki, Reacta, TypeScripta albo dodać w ogóle system typowania, a potem powoli kawałek po kawałeczku to poprawiać.

 

Tak jest, dokładnie, zgadzam się jak najbardziej. 

Dawid, bardzo ci dziękuję za rozmowę, za podzielenie się swoimi doświadczeniami, widać, że dużo ich masz z projektów, właśnie z radzeniem sobie z długiem technologicznym, a także wielkie, wielkie dzięki, że tutaj ze słuchaczami się tym podzieliłeś. Ja też jak najbardziej utożsamiam się z tym twoim podejściem, takim bardzo zdrowo rozsądkowym do tego problemu. 

Na koniec powiedz, proszę jeszcze, jak się z tobą skontaktować, jak cię znaleźć w internecie? 

 

Najprościej skontaktować się ze mną przez LinkedIn. Nie mam żadnego jeszcze personalnego bloga czy strony wizytówki, one są work in progress od długiego czasu. Myślę, że może kiedyś powstaną, ale jeżeli ktoś chce się ze mną skontaktować, to myślę, że LinkedIn jest najlepszym punktem, zaglądam tam co jakiś czas. 

Myślę, że możesz po prostu podlinkować gdzieś tam w podcaście i będzie w porządku.

 

Tak zrobię. 

Ja również bardzo, bardzo ci dziękuję. Miło było być tutaj gościem. Cieszę się, że mogłem podzielić się troszeczkę swoimi przemyśleniami na temat długu technologicznego. Dziękuję bardzo.

 

Dziękuję również! 

Oczywiście te linki będą w notatce do odcinka. 

Dzięki jeszcze raz za poświęcony czas. Do usłyszenia, cześć! 

 

Cześć!

 

I to na tyle z tego, co przygotowałem dla Ciebie na dzisiaj! Dawid doskonale pokazał, że z długiem technologicznym musimy się pogodzić, on po prostu jest. Ważne jest, by być jego świadomym, w jaki sposób go dokumentować i mierzyć oraz oczywiście zarządzać, najlepiej usuwając go w drobnych krokach, ale częściej. Ważna jest tutaj też świadomość organizacji, w której się pracuje i transparentne komunikowanie długu i konieczności radzenia sobie z nim do biznesu, produktu, czy klienta.

Jeśli ten odcinek był dla Ciebie interesujący i przydatny, odwdzięcz się proszę recenzją, oceną lub komentarzem w social mediach. Jeśli masz jakieś pytania, pisz śmiało na krzysztof@porozmawiajmyoit.pl. Zapraszam też do moich mediów społecznościowych.

Nazywam się Krzysztof Kempiński, a to był odcinek podcastu Porozmawiajmy o IT o długu technologicznym.

Zapraszam do kolejnego odcinka już za tydzień.

Cześć!

 

+ Pokaż całą transkrypcję
– Schowaj transkrypcję
mm
Krzysztof Kempiński
krzysztof@porozmawiajmyoit.pl

Jestem ekspertem w branży IT, w której działam od 2005 roku. Zawodowo zajmuję się web-developmentem i zarządzaniem działami IT. Dodatkowo prowadzę podcast, kanał na YouTube i blog programistyczny. Moją misją jest inspirowanie ludzi do poszerzania swoich horyzontów poprzez publikowanie wywiadów o trendach, technologiach i zjawiskach występujących w IT.