Engineering · 7 min čtení
Jak splácet technický dluh, aniž byste zastavili vývoj funkcí
Technický dluh splácíte bez zastavení vývoje funkcí tak, že ho berete jako stálou položku, ne jako projekt. Změřte, kde dluh skutečně bolí, veďte seřazený registr, v každém sprintu vyhraďte pevný podíl kapacity a riskantní části nahrazujte postupně za testy, abstrakcemi a feature flagy. Jestli to funguje, vám řeknou metriky DORA.
Autor BacklooPublikováno
Hlavní body
- Nejdřív měřte: dluh v kódu, na který skoro nikdo nesahá, je levný; dluh v souborech, které se mění každý týden a způsobují incidenty, je drahý.
- Veďte registr dluhu s cenou, rizikem a jmenovitým vlastníkem a vyhraďte pro něj pevný díl každého sprintu, místo abyste vyjednávali o každé položce zvlášť.
- Systémy nahrazujte po částech pomocí vzoru strangler fig, branch by abstraction a feature flagů. Přepis naráz je nejriskantnější možnost.
- Před refaktoringem napište charakterizační testy a jako výsledkovou tabuli, kterou přečte každý, používejte čtyři klíčové metriky DORA.
Proč je zmrazení vývoje funkcí špatné řešení
Zmrazení vývoje funkcí vyměňuje pomalý, viditelný náklad (dluh) za náhlý, viditelný náklad (žádný posun produktu), takže první zasedání představenstva přežije jen zřídka. Vydrží přístup, který je průběžný: malé, předvídatelné množství práce na dluhu v každém cyklu, mířené na kód, který bolí nejvíc, s výsledky, které byznys vidí.
Ten náklad je skutečný. Dluh se projevuje pomalejšími dodávkami, více regresemi, delším zaškolováním a únavou z pohotovostí. V rozpočtu se jako samostatná položka objeví jen zřídka, a proto ve srovnání s funkcemi pořád prohrává.
10–20 %
Tuhle daň už platíte. Otázkou je, jestli ji platíte jako úroky, tedy pomalými a křehkými dodávkami, nebo jako jistinu, tedy plánovanou prací, která zlevní každou další změnu.
Měřte dluh tam, kde bolí: hotspoty a incidenty
Dluh měříte tak, že zkombinujete, jak často se kód mění, s tím, jak těžké je ho změnit. Složitý soubor, na který nikdo nesahá, je kuriozita. Složitý soubor, který se mění každý týden, je hotspot — a v hotspotech se dluh mění v náklady. Přidejte data o incidentech a máte obhajitelný seznam priorit.
Četnost změn × složitost
Četnost změn (churn) získáte přímo z verzovacího systému. Složitost může být jednoduchá jako počet řádků kódu, nebo přesná jako cyklomatická či kognitivní složitost z linteru. Obě hodnoty vynásobte a seřaďte. Prvních deset souborů obvykle odpovídá za velkou část bolesti, na kterou si váš tým už stěžuje.
# počet commitů na soubor za posledních 6 měsíců (churn)
git log --since="6 months ago" --name-only --pretty=format: \
| grep -E '\.(ts|tsx|py|go)$' \
| sort | uniq -c | sort -rn | head -30
# hrubý ukazatel složitosti: počet řádků na soubor
wc -l $(git ls-files 'src/**/*.ts') | sort -rn | head -30Nekomplikujte to. Tabulka, která oba seznamy spojí, stačí k tomu, abyste začali užitečnou debatu. Specializované nástroje přidají trendy a mapy vlastnictví, až budete vědět, že se to vyplácí.
Propojte dluh s incidenty
Každý postmortem by měl odpovědět na jednu otázku navíc: která část kódu to zhoršila nebo ztížila opravu? Incident označte příslušným modulem. Po čtvrtletí jsou moduly s nejvíce incidenty a nejvyšší četností změn vašimi prvními cíli — a máte to čím doložit.
Veďte registr dluhu, ne hřbitov v backlogu
Registr dluhu je krátký, seřazený seznam známého dluhu s odhadovanou cenou, mírou rizika a vlastníkem. Od backlogu plného ticketů „refaktorovat X“ se liší tím, že každá položka uvádí, kolik dluh stojí dnes a co jeho splacení odemkne, takže ji lze prioritizovat proti funkcím stejným jazykem.
| Pole | Příklad | Proč na tom záleží |
|---|---|---|
| Položka | Logika cen objednávek duplikovaná v API a v administraci | Pojmenovává problém, ne řešení |
| Důkazy | Mezi 3 největšími hotspoty; 2 incidenty minulé čtvrtletí | Váže ji na měřitelnou bolest |
| Úrok | Každá změna cen zasahuje do 2 kódových bází, ~1 den navíc | Průběžná cena za to, že se nic neudělá |
| Riziko | Vysoké: k zákazníkům se dostanou špatné ceny | Dopad na byznys, když to selže |
| Navržený krok | Vyčlenit modul cen za jedno rozhraní | Nejmenší změna, která pomůže |
| Vlastník | Jmenovitý inženýr | Někdo za to odpovídá |
| Stav | Příští sprint | Viditelný pokrok |
Řaďte podle úroku × rizika, ne podle toho, jak moc vás kód uráží. Registr jednou měsíčně projděte, vyřaďte položky, na kterých už nezáleží, a držte ho zhruba do dvaceti záznamů. Registr, který nikdo nečte, je jen druhý backlog.
V každém sprintu vyhraďte pevnou kapacitu
Nejjednodušší pravidlo, které přežije střet s termíny, je pevný podíl kapacity vyhrazený na dluh v každém sprintu, jednou dohodnutý s produktem a znovu nevyjednávaný položku po položce. Zvolte číslo, které dokážete udržet, například jeden den z deseti, a chraňte ho jako každý jiný závazek.
- Pevně, ne ze zbytku. Práce na dluhu „až bude čas“ se nikdy neudělá. Naplánujte ji jako první.
- Brané z registru. Tým si bere položky shora, takže se nevede debata o tom, co se počítá.
- Navíc pravidlo skauta. Drobné úklidy v kódu, který už stejně měníte, jsou součástí funkce, ne rozpočtu na dluh.
- Pružné v rámci čtvrtletí. Kvůli spuštění můžete sprint vynechat a pak to dohnat. Zůstatek sledujte otevřeně.
Nahrazujte, nepřepisujte: strangler fig, branch by abstraction, flagy
Velký dluh se splácí tak, že systém nahrazujete po částech, zatímco dál běží — nikdy přepisem naráz. Většinu práce odvedou tři techniky: strangler fig pro celé subsystémy, branch by abstraction pro kód uvnitř jedné kódové báze a feature flagy pro bezpečné přepínání provozu. Pokud stejně zvažujete přepis, přečtěte si nejdřív záchrana, refaktoring, nebo přepis.
Vzor strangler fig
Martin Fowler pojmenoval tento vzor podle škrticího fíkovníku, který obrůstá strom, dokud ho nenahradí. Před starý systém postavte směrovací vrstvu, novou implementaci stavějte postupně po jedné routě nebo schopnosti a provoz přesouvejte, jakmile je každá část hotová. Starý kód se zmenšuje, dokud ho nejde smazat. V žádném okamžiku vás nečeká riskantní víkend s přepnutím.
Branch by abstraction
U kódu v jednom repozitáři vložte před část, kterou chcete nahradit, rozhraní, převeďte na něj všechna volání, za ním postavte novou implementaci, pak přepněte a starou smažte. Všechno se průběžně dodává do mainu; na konci nečeká žádná dlouho žijící větev k mergi.
Feature flagy jako přepínač
Flag za běhu rozhoduje, která implementace obslouží požadavek. Nasaďte nejdřív interním uživatelům, pak malému procentu a pak všem — a vracejte se přepnutím flagu, ne novým nasazením.
// Jedno rozhraní, dvě implementace, jeden přepínač.
interface PriceCalculator {
quote(order: Order): Money;
}
const calculator: PriceCalculator = flags.isOn("pricing-v2", { userId })
? new PricingModule() // nová, otestovaná, s vlastníkem
: new LegacyPricing(); // stará cesta, smažeme ji, až flag dosáhne 100 %I flagy jsou dluh. Každému flagu přiřaďte vlastníka a datum odstranění a smažte ho do jednoho až dvou sprintů po plném nasazení.
Než začnete refaktorovat, natáhněte záchrannou síť
Refaktoring bez testů je jen měnění kódu a doufání. Než sáhnete na hotspot, zafixujte jeho současné chování testy, i když je to chování zvláštní. Tyto charakterizační testy vám v tu ránu řeknou, že vaše změna mění něco, na čem uživatelé závisí.
- Charakterizační testy pokrývají hlavní vstupy a výstupy modulu, který budete měnit
- Alespoň jeden end-to-end test pokrývá kritickou uživatelskou cestu, která přes něj vede (registrace, pokladna, rezervace)
- CI spouští testy u každého pull requestu a při selhání blokuje merge
- Sledování chyb a základní metriky běží, takže regrese v produkci je vidět během několika minut
- Existuje cesta zpět: flag, revert nebo předchozí nasazení, které můžete povýšit
Pokud kód vznikl rychle s AI nástroji a nemá téměř žádné testy, začněte tam. Minimální záchrannou síť popisuje náš produkční checklist pro aplikace z vibecodingu.
Čtyři klíčové metriky DORA jako výsledková tabule
Čtyři klíčové metriky DORA ukazují, jestli se práce na dluhu vyplácí, protože sledují rychlost a stabilitu dodávek zároveň: frekvenci nasazení, dobu realizace změn, podíl neúspěšných změn a dobu obnovy služby. Pokud splácení dluhu funguje, první dvě se zlepšují a poslední dvě klesají.
| Metrika | Co měří | Jak jí dluh škodí | Kde ji získat |
|---|---|---|---|
| Frekvence nasazení | Jak často dodáváte do produkce | Kvůli křehkému kódu týmy změny shromažďují do dávek | Logy nasazení z CI/CD |
| Doba realizace změn | Od commitu po běh v produkci | Pomalé code review, nestabilní testy, ruční kroky | Git + časy nasazení |
| Podíl neúspěšných změn | Podíl nasazení, která způsobí incident nebo rollback | Provázaný kód se rozbíjí na nečekaných místech | Evidence incidentů + nasazení |
| Doba obnovy služby | Jak dlouho trvá zotavení | Slabá observabilita, riskantní rollbacky | Časy incidentů |
Než začnete, zaznamenejte výchozí stav, čtyři čísla procházejte každý měsíc a nepodlehněte pokušení dělat z nich individuální cíle. Popisují systém, ne lidi.
Jak vysvětlit dluh netechnickým stakeholderům
Vysvětlujte dluh v měně, kterou stakeholdeři už používají: čas uvedení na trh, riziko a peníze. Nikdo mimo engineering nepotřebuje slyšet o provázanosti nebo pokrytí testy. Potřebují slyšet, že změna cen trvá týden místo dne a že poslední dva výpadky vzešly ze stejného modulu.
- Pojmenujte byznysový symptom. „Každá změna cen trvá pět dní a tohle čtvrtletí dvakrát rozbila pokladnu.“
- Vyčíslete úrok. „Stojí nás to zhruba jeden inženýrský den na každou změnu plus čas na incidenty.“
- Navrhněte ohraničený krok. „Dva sprinty v rámci našeho běžného rozpočtu na dluh, abychom vyčlenili modul cen.“
- Slibte měřitelný výsledek. „Doba realizace změn cen pod dva dny, sledovaná na dashboardu DORA.“
- Podejte zprávu. Ukažte stav před a po. Důvěra, kterou tím získáte, zafinancuje další položku.
Práce na dluhu, kterou nejde vysvětlit jako rychlejší nebo bezpečnější produkt, obvykle není ten dluh, který splácet jako první.
Jak vám Backloo může pomoct
Pokud je váš tým přetížený, externí inženýr může provést měření, sestavit první registr a udělat nejriskantnější refaktoringy, zatímco váš tým dál dodává. To je jádro našich plánů údržby a SLA: pevný měsíční rozpočet na aktualizace, monitoring a plánovanou práci na dluhu.
U větších strukturálních problémů, jako je backend, který přerostl svůj první návrh, plánujeme migraci podle vzoru strangler fig v rámci backendových systémů. Nevíte, kde začít? Rescue Audit vám dá seřazený písemný přehled dluhu — a vždycky se nám můžete nejdřív ozvat.
Otázky
Kolik kapacity sprintu by mělo jít na technický dluh?
Univerzální číslo neexistuje. Zvolte pevný podíl, který dokážete udržet v každém sprintu, třeba jeden den z deseti, chraňte ho a po čtvrtletí ho upravte podle metrik DORA a vývoje incidentů.
Je úplný přepis někdy správná volba?
Někdy ano, když platforma přestala být podporovaná nebo je datový model zásadně špatně. I tehdy je ale postupná náhrada podle vzoru strangler fig obvykle bezpečnější než přepnutí naráz. Než se zavážete, sepište argumenty i s důkazy.
Jaký je rozdíl mezi registrem dluhu a backlogem?
Backlog vypisuje práci. Registr dluhu vypisuje známý dluh s důkazy, průběžnou cenou, rizikem a vlastníkem, takže každou položku lze seřadit proti funkcím v byznysových pojmech. Zůstává krátký a prochází se jednou měsíčně.
Jaké nástroje potřebuji k měření technického dluhu?
Na začátek jen historii gitu, linter a evidenci incidentů. K nalezení prvních hotspotů stačí spojit četnost změn, složitost a označení incidentů v tabulce. Specializované nástroje přidejte, až se z toho stane zvyk.