Klient se ptá: "Když přidání této funkce v nové aplikaci zabere týden, proč tady jsou potřeba tři týdny?"
To je velmi dobrá otázka.
A odpověď často nezní: "protože programátoři pracují pomaleji".
Problém může být mnohem hlouběji - v architektuře systému, jeho závislostech, způsobu ukládání dat, chybějících testech, historických rozhodnutích a dalších změnách přidávaných po léta.
Právě proto nejsou náklady na vývoj softwaru stálé.
Stejná funkce může v dvou různých systémech stát úplně jinou částku.
Kód se neoceňuje jen podle počtu funkcí
Na první pohled může úkol vypadat banálně.
"Přidejme možnost exportu dat do Excelu."
Nebo: "Přidejme novou roli uživatele."
Nebo: "Propojme systém s naším CRM."
Problém je v tom, že funkce nikdy neexistuje úplně odděleně od zbytku systému.
Nová funkcionalita může vyžadovat změny v:
- databázi,
- API,
- backendu,
- frontendu,
- systému oprávnění,
- logování,
- reportingu,
- integracích,
- testech,
- cache mechanismech,
- dokumentaci,
- procesu nasazení.
Čím více je systém propojený, tím více prvků je třeba před změnou analyzovat.
Největší náklad může vzniknout ještě před napsáním první řádky kódu
V zralém systému by programátor neměl prostě začít psát.
Nejprve je třeba odpovědět:
- Kde by měla být tato funkce přidána?
- S jakými moduly bude komunikovat?
- Jaká data využívá?
- Zahrnují ji stávající mechanismy oprávnění?
- Ovlivní změna jiné procesy?
- Které testy je třeba aktualizovat?
- Umožňuje současná architektura vůbec udělat to správně?
To vše je součástí nákladů na vytvoření funkce.
Proto může ve starém systému významnou část práce tvořit nikoli samotné programování, ale rozpoznání závislostí a omezení existujícího řešení.
Technical debt funguje jako úroky
Dobrým způsobem přemýšlení o technical debt je právě náklad dalších změn.
Pokud bylo nějaké řešení kdysi uděláno rychle, může to být zcela opodstatněné.
Problém nastává ve chvíli, kdy se dočasné řešení stane trvalou součástí systému.
Vznikne další funkce.
Pak další.
Objeví se výjimka.
Pak další výjimka.
K tomu se přidá integrace, obejití problému, manuální proces a další pravidlo.
Po několika letech už nikdo neví, proč systém funguje právě tímto způsobem.
Ale každá další změna musí zohlednit všechna tato historická rozhodnutí.
Martin Fowler popisuje technical debt jako dodatečné úsilí vynaložené při změnách systému v důsledku problémů s jeho vnitřní kvalitou.
Dá se tedy říct: technical debt nemusí hned zastavit vývoj. Nejdřív způsobí, že každá další změna bude dražší.
První signál: "při tom rovnou musíme opravit ještě pět věcí"
To je jeden z nejtypičtějších příznaků.
Klient si objedná jednu funkci.
Během analýzy se ukáže, že k jejímu nasazení je potřeba:
- upravit strukturu tabulky,
- změnit způsob autorizace,
- aktualizovat knihovnu,
- opravit staré API,
- přepsat část frontendu.
Najednou malá funkce přestává být malou funkcí. Ne proto, že je požadavek složitý. Ale proto, že systém už nemá odpovídající architektonické hranice.
Druhý signál: jedna změna vyžaduje testování celého systému
Pokud i malá úprava vyžaduje kompletní ruční regresi, organizace platí za nedostatek automatizace.
S růstem systému roste počet možných kombinací.
Bez odpovídající sady testů je čím dál těžší mít jistotu, že nová funkce nepoškodila tu starou.
To zase vede k opatrnosti.
Nasazení jsou méně častá.
Změny jsou větší.
Riziko roste.
A větší nasazení se hůře diagnostikují, když nastanou problémy.
Vzniká začarovaný kruh.
Třetí signál: "tohoto modulu je lepší se nedotýkat"
Tahle věta by měla rozsvítit varovnou kontrolku.
Pokud se konkrétní modul stal oblastí, které se tým vyhýbá, protože jeho chování je nepředvídatelné, má systém zásadní problém s udržovatelností.
Ještě horší je, když jeho fungování zná jen jedna osoba. Pak firma nemá jen technical debt. Má také knowledge risk.
Odchod jednoho zaměstnance může znamenat ztrátu znalostí potřebných k bezpečnému rozvoji systému.
Čtvrtý signál: každá funkce vyžaduje výjimky
Dobře navržený systém by měl mít předvídatelná pravidla.
Pokud každá další funkce vyžaduje přidávání speciální výjimky, dodatečné podmínky nebo individuální cesty, architektura pravděpodobně začíná brzdit rozvoj.
To často vede ke kódu, který už nelze snadno předvídat.
A nedostatek předvídatelnosti znamená vyšší náklady na analýzu, testování a údržbu.
Je nutné všechno přepsat?
Ne.
A tady se dostáváme k velmi důležitému rozlišení.
Technical debt neznamená automaticky nutnost rewriteu.
Možná řešení zahrnují:
Refaktoring
Tedy zlepšení struktury existujícího kódu bez změny jeho obchodního chování.
To je dobrý směr, když systém stále má smysluplnou architekturu, ale konkrétní části se těžko udržují.
Modernizace vybraných komponent
Není nutné vyměňovat celou aplikaci.
Je možné začít od nejproblémovějšího modulu, integrace nebo vrstvy.
Postupná migrace
Nové prvky mohou fungovat vedle starého systému a další oblasti se postupně přesouvají.
Tento přístup umožňuje omezit riziko jednorázové migrace. V literatuře věnované legacy modernizaci se často využívá právě postupné vyčleňování funkcionality a nahrazování dalších částí systému.
Rewrite
Výstavba nového systému dává smysl tehdy, když je současná architektura natolik omezující, že další modernizace nepřináší odůvodnitelnou návratnost.
Ale rewrite by měl být rozhodnutím vycházejícím z analýzy, ne reakcí na frustraci týmu.
Kdy se ještě nevyplatí investovat do modernizace?
Technický dluh sám o sobě není důvodem k zastavení vývoje. Každý systém má určitou úroveň technického dluhu. Někdy nemá jeho splácení ekonomický smysl.
Pokud aplikace:
- funguje stabilně,
- je bezpečná,
- má jen malý počet změn,
- podporuje proces, který se nebude zásadně rozvíjet,
- nezpůsobuje provozní problémy,
může být rozumné ponechat ji v současném stavu.
Nejde o to, aby byl každý systém technologicky dokonalý.
Jde o to, aby úroveň dluhu byla vědomým rozhodnutím.
Kdy se náklady technického dluhu stávají byznysovým problémem?
Ve chvíli, kdy začnou ovlivňovat výsledky firmy.
Například:
Nová funkce měla jít na trh za měsíc, ale potřebuje tři.
Integrace s novým partnerem se protahuje, protože API starého systému neumožňuje snadno zpracovat nová data.
Klíčová osoba v týmu se musí pokaždé účastnit práce, protože jen ona zná starý modul.
Každé větší nasazení vyžaduje několikahodinový regresní test.
Konkurent zavádí nové funkce rychleji, protože jeho platforma umožňuje rychlejší experimentování.
V tomto okamžiku se technical debt přestává být problémem IT oddělení.
Stává se byznysovým problémem.
Jak měřit, zda se situace zhoršuje?
Není nutné vytvářet složitý systém KPI.
Vyplatí se sledovat několik jednoduchých ukazatelů:
Lead time - kolik času uplyne od zahájení práce na změně do jejího nasazení.
Četnost nasazení - jak často může tým bezpečně doručovat změny.
Change failure rate - jak často nasazení způsobují problémy.
Doba obnovení provozu - jak rychle se lze po výpadku vrátit ke stabilnímu fungování.
Doba realizace funkce - zda podobné úkoly vyžadují stále větší úsilí.
K tomu se vyplatí analyzovat počet manuálních operací, pokrytí testy, aktuálnost závislostí a čas potřebný k zaškolení nového programátora do projektu.
Taková data umožňují zjistit, zda je problém skutečně technický, nebo může vyplývat z procesu, požadavků či způsobu organizace práce.
Nejhorším řešením je "ještě jedna rychlá oprava"
Pokud tým ví, že architektura vyžaduje změny, ale pokaždé toto téma odkládá, systém se může dostat do spirály.
"Uděláme teď workaround."
"Refaktorizaci provedeme později."
"Zatím to stačí."
"Při dalším release."
Problém je v tom, že další release přináší nové požadavky.
A každý další workaround zvyšuje náklady na příští změnu.
Proto by rozhodnutí o splácení technical debt mělo být součástí strategie rozvoje produktu, nikoli náhodnou reakcí na krizi.
Dobrý aplikace není ta, která nikdy nezestárne
Každý systém se bude měnit.
Technologie se budou měnit.
Zákazníci budou mít nové potřeby.
Objeví se nové integrace.
Změní se způsob práce firmy.
Cílem proto nemá být vytvoření aplikace, kterou nikdy nebude nutné modernizovat. Cílem by mělo být vytvoření takové architektury, ve které je modernizace možná bez zastavení byznysu. To je obrovský rozdíl.
Protože nejlepší systém není ten, který v den spuštění vypadá nejmoderněji. Je to systém, který i po několika letech umožňuje firmě rychle reagovat na změny.
A pokud každá nová funkce stojí stále víc, nemusí to vždy znamenat, že je funkce složitá.
Možná se už stal obtížným samotný systém.



