Klient sa pýta: "Keď pridanie tejto funkcie v novej aplikácii trvá týždeň, prečo tu treba tri týždne?"
To je veľmi dobrá otázka.
A odpoveď často neznie: "lebo programátori pracujú pomalšie".
Problém môže byť oveľa hlbšie - v architektúre systému, jeho závislostiach, spôsobe ukladania dát, chýbajúcich testoch, historických rozhodnutiach a ďalších zmenách pridávaných počas rokov.
Práve preto náklady na vývoj softvéru nie sú nemenné.
Tá istá funkcia môže stáť v dvoch rôznych systémoch úplne inú sumu.
Kód sa neoceňuje len podľa počtu funkcií
Na prvý pohľad môže úloha vyzerať banálne.
"Pridajme možnosť exportu dát do Excelu."
Alebo: "Pridajme novú rolu používateľa."
Alebo: "Prepojme systém s naším CRM."
Problém je v tom, že funkcia nikdy neexistuje úplne oddelene od zvyšku systému.
Nová funkcionalita môže vyžadovať zmeny v:
- databáze,
- API,
- backende,
- frontende,
- systéme oprávnení,
- prihlasovaní,
- reportingu,
- integráciách,
- testoch,
- cache mechanizmoch,
- dokumentácii,
- procese nasadenia.
Čím je systém prepojenejší, tým viac prvkov treba pred zmenou analyzovať.
Najväčší náklad môže vzniknúť ešte pred napísaním prvého riadku kódu
V zrelom systéme by programátor nemal jednoducho začať písať.
Najprv treba odpovedať na otázky:
- Kde by mala byť táto funkcia pridaná?
- S akými modulmi bude komunikovať?
- Aké dáta využíva?
- Pokrývajú ju existujúce mechanizmy oprávnení?
- Ovplyvní zmena iné procesy?
- Ktoré testy treba aktualizovať?
- Umožňuje súčasná architektúra vôbec urobiť to správne?
To všetko je súčasťou nákladov na vytvorenie funkcie.
Preto v starom systéme môže podstatnú časť práce tvoriť nie samotné programovanie, ale spoznávanie závislostí a obmedzení existujúceho riešenia.
Technický dlh funguje ako úroky
Dobrý spôsob uvažovania o technickom dlhu je práve náklad ďalších zmien.
Ak bolo niekedy nejaké riešenie urobené rýchlo, môže to byť úplne opodstatnené.
Problém nastáva vtedy, keď sa dočasné riešenie stane trvalou súčasťou systému.
Vznikne ďalšia funkcia.
Potom ďalšia.
Objaví sa výnimka.
Potom ďalšia výnimka.
K tomu sa pridá integrácia, obchádzka problému, manuálny proces a dodatočné pravidlo.
Po niekoľkých rokoch si už nikto nepamätá, prečo systém funguje práve takto.
Ale každá ďalšia zmena musí zohľadniť všetky tieto historické rozhodnutia.
Martin Fowler opisuje technický dlh ako dodatočné úsilie vynakladané pri zmenách systému v dôsledku problémov s jeho vnútornou kvalitou.
Možno teda povedať: technický dlh nemusí hneď zastaviť vývoj. Najprv spôsobí, že každá ďalšia zmena bude drahšia.
Signál prvý: "pri tejto príležitosti treba opraviť ešte päť vecí"
Je to jeden z najcharakteristickejších príznakov.
Klient si objedná jednu funkciu.
Počas analýzy sa ukáže, že aby sa dala implementovať, treba:
- upraviť štruktúru tabuľky,
- zmeniť spôsob autorizácie,
- aktualizovať knižnicu,
- opraviť staré API,
- prepísať časť frontendu.
Zrazu sa malá funkcia prestáva zdať malou. Nie preto, že požiadavka je zložitá. Ale preto, že systém už nemá vhodné architektonické hranice.
Signál druhý: jedna zmena si vyžaduje testovanie celého systému
Ak aj malá úprava vyžaduje plný manuálny regresný test, organizácia platí za chýbajúcu automatizáciu.
S rastom systému rastie aj počet možných kombinácií.
Bez vhodnej sady testov je čoraz ťažšie mať istotu, že nová funkcia nepoškodila starú.
To následne vedie k opatrnosti.
Nasadenia sú menej časté.
Zmeny sú väčšie.
Riziko rastie.
A väčšie nasadenia sa v prípade problémov ťažšie diagnostikujú.
Vzniká bludný kruh.
Signál tretí: "na tento modul je lepšie nesiahať"
Táto veta by mala rozsvietiť výstražnú kontrolku.
Ak sa konkrétny modul stal oblasťou, ktorej sa tím vyhýba, pretože jeho správanie je nepredvídateľné, systém má výrazný problém s udržiavateľnosťou.
Ešte horšie je, ak jeho fungovanie pozná len jeden človek. Vtedy firma nemá len technický dlh. Má aj knowledge risk.
Odchod jedného zamestnanca môže znamenať stratu vedomostí potrebných na bezpečný rozvoj systému.
Signál štvrtý: každá funkcia vyžaduje výnimky
Dobre navrhnutý systém by mal mať predvídateľné pravidlá.
Ak si každá ďalšia funkcia vyžaduje dopísanie špeciálnej výnimky, dodatočnej podmienky alebo individuálnej vetvy, architektúra pravdepodobne začína brzdiť rozvoj.
To často vedie ku kódu, ktorého správanie sa už nedá ľahko predvídať.
A nedostatok predvídateľnosti znamená vyššie náklady na analýzu, testovanie a údržbu.
Treba všetko prepísať?
Nie.
A tu sa dostávame k veľmi dôležitému rozlíšeniu.
Technický dlh automaticky neznamená potrebu rewrite-u.
Možné riešenia zahŕňajú:
Refaktorovanie
Teda zlepšenie štruktúry existujúceho kódu bez zmeny jeho biznisového správania.
Je to vhodný smer, keď systém stále má zmysluplnú architektúru, ale konkrétne časti sa ťažko udržiavajú.
Modernizáciu vybraných komponentov
Netreba vymeniť celú aplikáciu.
Možno začať od najproblematickejšieho modulu, integrácie alebo vrstvy.
Postupnú migráciu
Nové prvky môžu fungovať vedľa starého systému a ďalšie oblasti sa postupne presúvajú.
Tento prístup umožňuje obmedziť riziko jednorazovej migrácie. V literatúre o modernizácii legacy systémov sa často využíva práve postupné vyčleňovanie funkcionalít a nahrádzanie ďalších častí systému.
Rewrite
Budovanie nového systému má zmysel vtedy, keď je súčasná architektúra natoľko obmedzujúca, že ďalšia modernizácia neprináša primeranú návratnosť.
Rewrite by však mal byť rozhodnutím vyplývajúcim z analýzy, nie reakciou na frustráciu tímu.
Kedy sa ešte neoplatí investovať do modernizácie?
Technical debt sám o sebe nie je dôvodom na zastavenie vývoja. Každý systém má určitú úroveň technického dlhu. Niekedy jeho splácanie nedáva ekonomický zmysel.
Ak aplikácia:
- funguje stabilne,
- je bezpečná,
- má malý počet zmien,
- podporuje proces, ktorý sa nebude výrazne rozvíjať,
- nevytvára prevádzkové problémy,
môže byť rozumné ponechať ju v súčasnom stave.
Nejde o to, aby bol každý systém technologicky dokonalý.
Ide o to, aby úroveň dlhu bola vedomým rozhodnutím.
Kedy sa náklad dlhu stáva biznisovým problémom?
Vtedy, keď začne ovplyvňovať výsledky firmy.
Napríklad:
Nová funkcia mala ísť na trh za mesiac, ale potrebuje tri.
Integrácia s novým partnerom sa naťahuje, pretože API starého systému neumožňuje ľahko spracovať nové dáta.
Kľúčová osoba v tíme sa musí pri každej príležitosti zapájať do práce, pretože len ona pozná starý modul.
Každé väčšie nasadenie si vyžaduje niekoľkohodinový regres.
Konkurent rýchlejšie zavádza nové funkcie, pretože jeho platforma umožňuje rýchlejšie experimentovať.
V tomto momente sa technical debt prestáva byť problémom IT oddelenia.
Stáva sa biznisovým problémom.
Ako merať, či sa situácia zhoršuje?
Netreba vytvárať zložitý systém KPI.
Oplatí sa sledovať niekoľko jednoduchých ukazovateľov:
Lead time - koľko času uplynie od začiatku práce na zmene po jej nasadenie.
Frekvencia nasadení - ako často môže tím bezpečne dodávať zmeny.
Change failure rate - ako často nasadenia spôsobujú problémy.
Čas obnovenia prevádzky - ako rýchlo sa možno po výpadku vrátiť k stabilnej prevádzke.
Čas realizácie funkcie - či podobné úlohy vyžadujú stále väčšie úsilie.
K tomu sa oplatí analyzovať počet manuálnych operácií, pokrytie testami, aktuálnosť závislostí a čas potrebný na zapracovanie nového programátora do projektu.
Takéto údaje umožňujú zistiť, či je problém skutočne technický, alebo môže vyplývať z procesu, požiadaviek alebo spôsobu organizácie práce.
Najhorším riešením je "ešte jedna rýchla oprava"
Ak tím vie, že architektúra si vyžaduje zmeny, ale zakaždým túto tému odkladá, systém sa môže dostať do špirály.
"Urobme teraz workaround."
"Refaktorizáciu spravíme neskôr."
"Zatiaľ to stačí."
"Pri ďalšom release."
Problém je v tom, že ďalší release prináša nové požiadavky.
A každý ďalší workaround zvyšuje náklad ďalšej zmeny.
Preto by rozhodnutie o splácaní technical debt malo byť súčasťou stratégie rozvoja produktu, a nie náhodnou reakciou na krízu.
Dobrá aplikácia nie je taká, ktorá nikdy nezostarne
Každý systém sa bude meniť.
Technológie sa budú meniť.
Zákazníci budú mať nové potreby.
Objavia sa nové integrácie.
Zmení sa spôsob práce firmy.
Preto cieľom by nemalo byť vytvoriť aplikáciu, ktorú nikdy nebude treba modernizovať. Cieľom by malo byť vytvoriť takú architektúru, v ktorej je modernizácia možná bez zastavenia biznisu. To je obrovský rozdiel.
Lebo najlepší systém nie je ten, ktorý vyzerá najmodernejšie v deň spustenia. Je ním systém, ktorý aj po niekoľkých rokoch umožňuje firme rýchlo reagovať na zmeny.
A ak každá nová funkcia stojí čoraz viac, nie vždy to znamená, že funkcia je zložitá.
Možno sa už ťažkým stal samotný systém.
