Dług techniczny (ang. technical debt) niemal każdemu, kto zetknął się z tym terminem, kojarzy się automatycznie z wytwarzaniem oprogramowania. Nie wynika to z jej szczególnej skłonności branży IT do kreowania takiego długu, ale z prozaicznego powodu: to programiści najpierw zidentyfikowali problem, a potem zaczęli z nim walczyć – z mniejszym lub większym powodzeniem.

Zjawisko to znane jest dziś każdemu Developerowi zajmującemu się wytwarzaniem oprogramowania. A przynajmniej powinno być znane, bo czy faktycznie tak jest, miewam często wątpliwości… Nie ogranicza się jednak tylko do tej dziedziny. Dług techniczny pojawia się właściwie wszędzie.

Czym jest dług techniczny?

Najprościej rzecz ujmując: jest to marnej jakości rozwiązanie, które powstało z pominięciem niektórych niezbędnych czynności, albo niezgodnie z obowiązującymi standardami. Jest to zatem rozwiązanie, którego da się użyć i uznawane jest zasadniczo za ukończone, ma jednak rozliczne słabości, które manifestują się problemami pojawiającymi się w różnych warunkach.

Przykładem długu technicznego jest pobieżne wykonanie testów oprogramowania przed przekazaniem go do użycia. Sprawdzenie wyłącznie kluczowych rzeczy pozwala mieć nadzieję, że wszystko będzie działać, ale w istocie nie wiadomo, czy jakieś funkcje nie będą szwankować. Skutki mogą być opłakane – od braku stabilności oprogramowania, poprzez jego niską wydajność aż do bezpowrotnego zniszczenia istotnych danych w trakcie ich przetwarzania.

Innym przykładem jest spawanie konstrukcji stalowej zbyt szybko i z użyciem temperatury wyższej niż przewidziana przez projektantów. Efekt może wyglądać dobrze, ale spoiny są zbyt kruche, do tego nadmierna temperatura spowodowała powstanie mikrouszkodzeń w łączonych elementach i nieprzewidzianych naprężeń w całej konstrukcji… katastrofy tylko czekać.

Zwracam uwagę, że nie jest długiem technicznym coś, co nie zostało nigdy ukończone ani jako takie nie było zadeklarowane przez Developerów. Inaczej mówiąc, jeśli oprogramowanie jest marne i sypie się na potęgę, ale jego twórcy otwarcie przyznają, że jeszcze swojej pracy nie zakończyli, wtedy mamy do czynienia z pracą w toku, a nie długiem technicznym. Jeśli spawacze klną w żywy kamień, a konstrukcja wykonana została ledwo w połowie i niebezpiecznie przechyla się w bok, to również nie jest dług techniczny, tylko połączenie fuszerki z niedokończoną pracą.

Nie powinno się również traktować każdego błędnego działania produktu jako skutek istnienia w nim długu technicznego. Błędy mogą wynikać z niezrozumienia problemu przez Developerów albo przemknąć się przez sito testów na skutek ludzkiej omyłki. Oznacza to, że błędy mogą być, ale nie muszą objawem istnienia długu technicznego w produkcie. Z drugiej strony brak błędów nie oznacza bynajmniej, że żadnego długu nie ma.

Przykładem tej ostatniej sytuacji jest stworzenie oprogramowania w sposób urągający wszelkim standardom kodowania, nieczytelnego, o fatalnej strukturze, niemal niemożliwego do dalszego rozwoju. Będzie ono działać, być może zupełnie poprawnie, ale wprowadzenie modyfikacji w przyszłości będzie bardzo trudne i w najlepszym razie kosztowne.

Innym przykładem może być wspomniana konstrukcja metalowa, którą ktoś połączył nitami i śrubami, zamiast spawać zgodnie z projektem. Działa, spełnia swoje zadania, nadaje się do użytku, ale będzie dużo trudniejsza w utrzymaniu, nie jest pewne, czy nie pojawi się niebezpieczna korozja i czy połączenia śrubowe nie będą wymagać regularnego dokręcania.

Skąd ta nazwa: dług techniczny?

Dług powstaje, gdy ktoś, kto nie może pozwolić sobie na zakup produktu lub usługi, nabywa je w zamian za zobowiązanie do zapłaty w przyszłości, powiększonej zwykle o odsetki. Nabywca akceptuje je w zamian za to, że uzyska od razu coś, na czym mu zależy bez konieczności uzbierania najpierw niezbędnych środków.

I dokładnie tak samo dzieje się, gdy Developerzy robią coś, czego nie da się zrealizować w oczekiwanym czasie i we właściwy sposób, poświęcając przy tym – świadomie lub nie – jakość wytwarzanego produktu. Oni też zaciągają dług, który przyjdzie im spłacić z odsetkami, bo w przyszłości, aby doprowadzić rozwiązanie do należytego stanu, nie tylko trzeba będzie w końcu wykonać pracę wcześniej pominiętą, ale konieczne okaże się przerobienie tego, co powstało na początku.

Inaczej mówiąc, gdyby od razu wykonali rozwiązanie tak, jak powinni, sumaryczny koszt, czas i wysiłek byłby mniejszy niż wypchnięcie kolanem czegoś niedopracowanego po to, by później to poprawiać.

To niezaprzeczalne podobieństwo do długu fiskalnego spowodowało, że wybrana została taka, a nie inna nazwa. Przy czym ta analogia nie jest absolutna i jest jeden aspekt długu technicznego, który czyni go zjawiskiem wybitnie szkodliwym, a którego dług fiskalny jest niemal zawsze pozbawiony.

Samoczynnie rozrastający się dług techniczny

Otóż jeśli pożyczymy pieniądze, żeby zakupić dobra, na które nas nie stać, a potem będziemy na bieżąco spłacać jedynie odsetki, sam dług nie będzie się powiększał (nie będzie też malał). Jasne, są różne produkty finansowe, są też lichwiarskie firmy pożyczkowe – o takich praktykach nie chcę nawet wspominać, bo powinny być zakazane tak samo, jak niedozwolony jest rabunek.

Spłacanie odsetek od długu technicznego, niepowiązane z jednoczesnym spłacaniem samego długu, powoduje rozrastanie się tego długu. Najlepiej objaśnić to zjawisko na prostym przykładzie.

Wyobraźmy sobie samochód, w którym niektóre części karoserii montowane są poprzez ich przyklejanie do konstrukcji nośnej nadwozia (uwaga: wszelkie podobieństwo do zdarzeń, o jakich czytamy w mediach, jest zupełnie przypadkowe). Presja czasu i dążenie do cięcia kosztów spowodowało, że posłużono się klejem o nieustalonych właściwościach, a sam proces jego nakładania był mało przemyślany. Niemniej pojazdy zostały dostarczone do salonów, zakupione przez klientów i znalazły się na drogach.

Skutki dają się przewidzieć: w zależności od sposobu użytkowania pojazdu i warunków, w jakich się zazwyczaj przemieszcza, klej pęka, połączenie części karoserii z ramą słabnie, zdarza się, że ten i ów element zaczyna odstawać, grożąc odpadnięciem.

Właściciele pojawiają się w serwisie, który pieczołowicie przylepia je na powrót – tym samym klejem, w takim samym procesie jak w fabryce. Spłacane są więc odsetki od zaciągniętego długu, ale dług pozostaje. Wciąż przecież klej jest niewłaściwy, a sposób jego aplikowania sprzyja nawracaniu problemów.

W końcu producent postanawia spłacić nie tylko odsetki, ale sam dług, czyli wymienić klej na taki, który nie będzie sprawiał kłopotów i nałożyć go w sposób gwarantujący, że nic już nie będzie odpadać. I wtedy okazuje się, że nieszczelności w nadwoziu spowodowały przyspieszone zużycie nie tylko tych odklejających się części, ale również elementów sąsiednich. Na różne fragmenty nadwozia działały siły większe, niż przewidzieli konstruktorzy. Do środka dostawał się brud, ciekła woda, a kawitacja powietrza w trakcie szybkiej jazdy też zrobiła swoje.

Konieczne jest więc nie tylko poprawne zamocowanie wcześniej odpadających elementów, ale również wymienienie wielu innych części, które uległy uszkodzeniu. Jeśli producent tego nie zrobi, jeden problem zostanie zastąpiony przez kolejny, np. związany z korozją czy powolną utratą sztywności nadwozia.

Zbyt opieszałe spłacenie długu i ograniczenie się wyłącznie do spłaty odsetek spowodowało, że dług się rozrósł i stał się bardziej dotkliwy, a być może nieusuwalny.

Dług zaciągany bezwiednie

Można powiedzieć, że dług techniczny powstaje, gdy podejmowane są próby przechytrzenia praw fizyki, czyli zrobienia czegoś, co w istniejących warunkach, przy dostępnych środkach i w czasie na to przewidzianym, nie może być zrobione dobrze.

Im mniejsza jest zdolność uczestników procesu do zauważenia, że coś jest niemożliwe, tym większe prawdopodobieństwo, że zrobią coś, co w ich przekonaniu jest dobre, a w istocie zakażone zostanie sporym długiem technicznym. Zauważą go dopiero po pewnym czasie i wtedy, poza wykonaniem pracy niezbędnej, by dług usunąć, powinni wyciągnąć wnioski na przyszłość, aby uniknąć powtórzenia tego samego błędu.

Niewiele więcej można zrobić w przypadku zaciągania długu bez świadomości, że on powstaje. Konieczne jest uzupełnianie braków kompetencyjnych, udoskonalanie standardów (zwłaszcza, jeśli okazują się liche). To wymaga czasu, ale w końcu jest lepiej i długu powstaje mniej (choć nadal się pojawia, o tym jeszcze napiszę później).

Gorzej, jeśli dług zaciągany jest na skutek niskiego morale Developerów, którym zwyczajnie nie zależy (podobnie jak organizacjom, które ich zatrudniają) na tym, żeby wytwarzane produkty nadawały się do użycia. Czy w tym przypadku można wciąż uważać, że dług jest zaciągany nieświadomie? Ciężko zaprzeczyć, że dzieje się to na skutek świadomej decyzji Developerów, ale skutkują one powstawaniem losowych problemów, nad którymi nikt się nie zastanawia, i których nie próbuje przewidzieć. Więc nie jest to dług zaciągany świadomie.

Tak czy inaczej, sytuacja taka wymaga pilnej naprawy, bo może doprowadzić do śmierci technicznej produktu, czyli takiego jego zdegradowania, że albo nie da się przywrócić go do stanu przyzwoitego, albo jest to nieopłacalne.

Dług zaciągany celowo

Czy w ogóle może zdarzyć się, że Developerzy postanowią celowo zrobić coś marniej, niż powinni? Też pytanie! Presja na to, by zrobić coś na wczoraj, jest wywierana na wielu Developerów nieustannie. Choćby dlatego powinni oni być wystarczająco profesjonalni i mieć dość asertywności, by stawić temu opór i dbać o jakość tego, co wytwarzają.

Nie znaczy to, że zaciągnięcie długu technicznego zawsze jest błędem i należy ludzi za to potępiać. Wszystko zależy od powodów podjęcia takiej decyzji oraz tego, w jakim stopniu potrafią oszacować jej skutki.

A zdarza się, że można coś zrobić lepiej lub gorzej, przy czym obydwa rozwiązania spełniać będą obowiązujące standardy (w tym np. wymogi Definicji Ukończenia w Scrumie), a po wytworzeniu da się w pełni potwierdzić poprawność ich działania. Lepsze rozwiązanie zabierze więcej czasu i wysiłku, ale pozwoli uniknąć ograniczeń, które nieuchronnie pojawią się w produkcie, jeśli wybrane zostanie rozwiązanie gorsze. Co więcej, te ograniczenia, ich skala i skutki, dają się w pełni przewidzieć, podobnie jak da się oszacować koszt ewentualnego zastąpienia gorszego rozwiązania tym lepszym w przyszłości.

W tej sytuacji Developerzy i ktoś, kto odpowiada za wartość produktu (np. Product Owner w Scrumie), stają przed wyborem. Mogą pójść na skróty, wiedząc, jaką cenę za to zapłacą. I jeśli to zrobią, zaciągną dług, który jest znany, przewidywalny, o którego usunięcie można zadbać ze stosownym wyprzedzeniem. Tak, rozwiązanie będzie marne, ale jednocześnie najlepsze, jakie mogli wytworzyć bez poświęcania jakości w sposób nieakceptowalny.

Cechą charakterystyczną takiego długu jest jego przejrzystość. Nie przynosi chwały, ale wiadomo, jaki jest i co z nim zrobić. Nie będzie też rozrastał się w sposób niekontrolowany, o ile Developerzy na to nie pozwolą przez własne zaniechania. Pozostaje kwestią decyzji strategicznej, kiedy, czy i jak go usunąć.

Natomiast zdarza się, że dług zaciągany jest równie świadomie, co bezmyślnie. Developerzy np. oceniają, że coś „na pewno będzie działać”, więc nawet tego nie testują. Szukają luk w standardach, by obejść wymogi jakościowe i zrobić coś szybciej – zamiast szukać prostszych rozwiązań, które będzie można w zgodzie z tymi standardami wykonać w dostępnym czasie.

Skutkiem takiej strategii celowego zaciągania długu jest powstanie problemów, których skali ani charakteru nie da się przewidzieć. Nie da się też oszacować, jak kosztowne będzie w przyszłości usunięcie długu i czy w ogóle będzie można to zrobić. Ani nawet monitorować, czy aby nie rozrasta się on nieustannie w postępie geometrycznym. Oczywiście w końcu konsekwencje istnienia długu się ujawnią, tego jednego można być pewnym. I nie będzie to przyjemne wydarzenie…

Produkt pozbawiony długu technicznego?

Nie ma czegoś takiego. Nawet jeśli coś uda się stworzyć w sposób idealny, jest to zawsze ideał wyłącznie w myśl obecnie obowiązujących standardów przyłożonych do aktualnego stanu produktu, jego funkcjonalności, cech użytkowych itd. Z czasem zmieniał się będzie tak produkt, jak i standardy. Coś, co było przez moment ideałem, zacznie w końcu sprawiać problemy.

Wiara w to, że da się zbudować produkt pozbawiony długu technicznego, jest często jego zarzewiem. Objawem tej wiary jest albo nadmierny perfekcjonizm, albo dążenie do zbudowania centrum sterowania wszechświatem, albo wybieranie „jedynie słusznych” technologii, narzędzi i praktyk, jakimi mają posługiwać się Developerzy.

Wraz z taką wiarą idzie też przekonanie, że udało się produkt pozbawiony długu wytworzyć. A skoro tak, wystarczy tylko zapobiegać powstaniu nowego, wtedy powszechna szczęśliwość będzie trwać w nieskończoność. Developerzy skupiają się więc na dbaniu o to, czym zajmują się na bieżąco, a starzenia się (degradowania, popadania w dług techniczny) rozwiązań wytworzonych w przeszłości nikt nie bierze pod uwagę ani nie zauważa. Do czasu, aż problemy wybuchną niczym wulkan.

Zwalczanie długu technicznego

Skoro dług techniczny jest nieunikniony, trzeba dbać o to, by usuwać go na tyle szybko, aby nigdy nie przyrosło go za dużo, bo wtedy produkt wpada w spiralę problemów, z których może nie dać się go wyciągnąć.

Przy czym zwalczanie to powinno mieć charakter systemowy, a nie odbywać się od zrywu do zrywu. Inaczej mówiąc, nie chodzi o to, by usunąć cały znany dług raz na jakiś czas, a potem biernie czekać, aż uzbiera się nowy. Chodzi o to, by na bieżąco eliminować największe problemy, przez co te nowe, które się pojawiają, nigdy nie przerosną skali, z jaką Developerzy sobie skutecznie radzą.

O tym, jak zwalczanie długu technicznego może wyglądać w metodach zwinnych i jak tym procesem zarządzać, napiszę już wkrótce (na przykładzie Scruma). A osobny artykuł poświęcę omówieniu nietypowych form długu, które są wyjątkowo zwodnicze, bo niektórzy Developerzy, zamiast je zwalczać, szczycą się nimi.