Engineering · 7 min čítania
Ako splácať technický dlh bez toho, aby ste zastavili vývoj funkcií
Technický dlh splatíte bez zastavenia vývoja funkcií, keď ho budete brať ako stálu položku, nie ako projekt. Zmerajte, kde dlh naozaj bolí, veďte zoradený register, v každom šprinte vyhraďte pevný podiel kapacity a rizikové časti nahrádzajte postupne pod ochranou testov, abstrakcií a feature flagov. Či to funguje, vám ukážu metriky DORA.
Autor BacklooPublikované
Hlavné body
- Najprv merajte: dlh v kóde, na ktorý sa takmer nesiaha, je lacný; dlh v súboroch, ktoré sa menia každý týždeň a spôsobujú incidenty, je drahý.
- Veďte register dlhu s cenou, rizikom a konkrétnym vlastníkom a namiesto vyjednávania o každej položke mu vyhraďte pevnú časť každého šprintu.
- Systémy nahrádzajte po častiach pomocou vzoru strangler fig, branch by abstraction a feature flagov. Prepis naraz je najriskantnejšia možnosť.
- Pred refaktoringom napíšte charakterizačné testy a ako výsledkovú tabuľku, ktorej rozumie každý, používajte štyri kľúčové metriky DORA.
Prečo je zmrazenie funkcií nesprávne riešenie
Zmrazenie funkcií vymieňa pomalý a viditeľný náklad (dlh) za náhly a rovnako viditeľný (žiadny posun produktu), takže prvé zasadnutie predstavenstva prežije len zriedka. Udrží sa prístup, ktorý je priebežný: malé a predvídateľné množstvo práce na dlhu v každom cykle, zamerané na kód, ktorý bolí najviac, s výsledkami, ktoré biznis vidí.
Náklady sú skutočné. Dlh sa prejavuje pomalšími dodávkami, väčším počtom regresií, dlhším zaúčaním nových ľudí a vyčerpaním z pohotovostí. V rozpočte sa ako samostatná položka objaví len zriedka, a preto proti funkciám stále prehráva.
10–20 %
Túto daň už platíte. Otázka je, či ju platíte ako úrok — pomalými a krehkými dodávkami — alebo ako istinu, plánovanou prácou, vďaka ktorej bude ďalšia zmena lacnejšia.
Merajte dlh tam, kde bolí: hotspoty a incidenty
Dlh zmeriate tak, že skombinujete ako často sa kód mení s tým, ako ťažko sa mení. Zložitý súbor, na ktorý nikto nesiaha, je kuriozita. Zložitý súbor, ktorý sa mení každý týždeň, je hotspot — a práve v hotspotoch sa dlh mení na náklady. Pridajte údaje o incidentoch a máte zoznam priorít, ktorý obhájite.
Frekvencia zmien × zložitosť
Frekvenciu zmien (churn) získate priamo z verziovacieho systému. Zložitosť môže byť jednoduchá ako počet riadkov kódu alebo presná ako cyklomatická či kognitívna zložitosť z vášho lintera. Obe hodnoty vynásobte a zoraďte. Prvých desať súborov zvyčajne zodpovedá za veľkú časť bolesti, na ktorú sa váš tím už sťažuje.
# počet commitov na súbor za posledných 6 mesiacov (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ý ukazovateľ zložitosti: počet riadkov na súbor
wc -l $(git ls-files 'src/**/*.ts') | sort -rn | head -30Nekomplikujte to. Na začiatok užitočnej debaty stačí tabuľka, ktorá oba zoznamy spojí. Špecializované nástroje pridajú trendy a mapy vlastníctva, keď už viete, že sa to oplatí.
Prepojte dlh s incidentmi
Každý postmortem by mal odpovedať na jednu otázku navyše: ktorá časť kódu to zhoršila alebo sťažila opravu? Incident označte príslušným modulom. Po štvrťroku sú moduly s najväčším počtom označení z incidentov a najvyšším churnom vašimi prvými cieľmi — a máte na to dôkazy.
Veďte register dlhu, nie cintorín v backlogu
Register dlhu je krátky zoradený zoznam známeho dlhu s odhadovanou cenou, úrovňou rizika a vlastníkom. Od backlogu plného ticketov „refaktorovať X“ sa líši tým, že pri každej položke uvádza, koľko dlh stojí dnes a čo jeho splatenie odomkne — takže sa dá prioritizovať oproti funkciám v rovnakom jazyku.
| Pole | Príklad | Prečo na tom záleží |
|---|---|---|
| Položka | Logika cien objednávok duplikovaná v API aj v administrácii | Pomenúva problém, nie riešenie |
| Dôkaz | Top 3 hotspot; 2 incidenty minulý štvrťrok | Spája ho s merateľnou bolesťou |
| Úrok | Každá zmena cien sa dotkne 2 kódových báz, ~1 deň navyše | Priebežná cena nečinnosti |
| Riziko | Vysoké: k zákazníkom sa dostanú nesprávne ceny | Dopad na biznis, ak to zlyhá |
| Navrhovaný krok | Vyčleniť cenový modul za jedno rozhranie | Najmenšia zmena, ktorá pomôže |
| Vlastník | Konkrétny inžinier | Niekto za to zodpovedá |
| Stav | Ďalší šprint | Viditeľný pokrok |
Zoraďujte podľa úroku × rizika, nie podľa toho, ako veľmi vás kód uráža. Register raz mesačne prejdite, vyraďte položky, na ktorých už nezáleží, a obmedzte ho zhruba na dvadsať záznamov. Register, ktorý nikto nečíta, je len druhý backlog.
V každom šprinte si vyhraďte pevnú kapacitu
Najjednoduchšie pravidlo, ktoré prežije stret s termínmi, je pevný podiel kapacity vyhradený na dlh v každom šprinte, raz dohodnutý s produktom a neprejednávaný položku po položke. Zvoľte číslo, ktoré dokážete udržať, napríklad jeden deň z desiatich, a chráňte ho ako akýkoľvek iný záväzok.
- Pevná, nie zvyšková. Práca na dlhu „keď bude čas“ sa nikdy neudeje. Naplánujte ju ako prvú.
- Berie sa z registra. Tím si vezme položky z vrchu zoznamu, takže sa netreba hádať, čo sa počíta.
- Pravidlo skauta navyše. Drobné upratovanie v kóde, ktorý aj tak meníte, je súčasťou funkcie, nie rozpočtu na dlh.
- Flexibilná v rámci štvrťroka. Kvôli spusteniu jeden šprint vynechajte a potom to doženiete. Zostatok sledujte otvorene.
Nahrádzajte, neprepisujte: strangler fig, branch by abstraction, flagy
Veľký dlh sa spláca tak, že systém nahrádzate po častiach, kým ďalej beží, nikdy nie prepisom naraz. Väčšinu práce odvedú tri techniky: strangler fig pre celé subsystémy, branch by abstraction pre kód v rámci jednej kódovej bázy a feature flagy na bezpečné prepínanie prevádzky. Ak aj tak zvažujete prepis, prečítajte si najprv záchrana, refaktoring, alebo prepis.
Vzor strangler fig
Martin Fowler pomenoval tento vzor podľa popínavej rastliny, ktorá obrastá strom, až ho nahradí. Pred starý systém postavíte smerovaciu vrstvu, novú implementáciu staviate po jednej route alebo jednej schopnosti a prevádzku presúvate, keď je daná časť pripravená. Starý kód sa zmenšuje, až ho môžete zmazať. V žiadnom momente nehrozí riskantný víkend s veľkým prepnutím.
Branch by abstraction
Pri kóde v jednom repozitári vložte pred časť, ktorú chcete nahradiť, rozhranie, presuňte naň všetkých volajúcich, za ním postavte novú implementáciu, potom prepnite a starú zmažte. Všetko sa priebežne dostáva do main; na konci netreba zlučovať žiadnu dlho žijúcu vetvu.
Feature flagy ako prepínač
Flag za behu rozhoduje, ktorá implementácia obslúži požiadavku. Nasadzujte najprv pre interných používateľov, potom pre malé percento a nakoniec pre všetkých — a vracajte sa späť prepnutím flagu namiesto nového nasadenia.
// Jedno rozhranie, dve implementácie, jeden prepínač.
interface PriceCalculator {
quote(order: Order): Money;
}
const calculator: PriceCalculator = flags.isOn("pricing-v2", { userId })
? new PricingModule() // nová, otestovaná, s vlastníkom
: new LegacyPricing(); // stará cesta, zmazaná, keď flag dosiahne 100 %Aj flagy sú dlh. Každému flagu určte vlastníka a dátum odstránenia a zmažte ho do jedného či dvoch šprintov po plnom nasadení.
Pred refaktoringom si natiahnite záchrannú sieť
Refaktoring bez testov je len menenie kódu s nádejou. Skôr než sa dotknete hotspotu, zafixujte jeho súčasné správanie testami, aj keď je to správanie zvláštne. Tieto charakterizačné testy vám okamžite povedia, keď vaša zmena ovplyvní niečo, na čo sa používatelia spoliehajú.
- Charakterizačné testy pokrývajú hlavné vstupy a výstupy modulu, ktorý budete meniť
- Aspoň jeden end-to-end test pokrýva kritickú cestu používateľa cez tento modul (registrácia, pokladňa, rezervácia)
- CI spúšťa testy pri každom pull requeste a pri zlyhaní blokuje zlúčenie
- Sledovanie chýb a základné metriky bežia, takže regresiu v produkcii uvidíte do pár minút
- Existuje cesta späť: flag, revert alebo predchádzajúce nasadenie, ktoré môžete povýšiť
Ak kód vznikol rýchlo pomocou AI nástrojov a nemá takmer žiadne testy, začnite práve tam. Náš checklist pred spustením aplikácie z vibecodingu pokrýva minimálnu záchrannú sieť.
Používajte štyri kľúčové metriky DORA ako výsledkovú tabuľku
Štyri kľúčové metriky DORA merajú, či sa práca na dlhu vypláca, pretože sledujú rýchlosť dodávok a stabilitu súčasne: frekvenciu nasadení, čas dodania zmeny, podiel neúspešných zmien a čas obnovy služby. Ak splácanie dlhu funguje, prvé dve sa zlepšujú a posledné dve klesajú.
| Metrika | Čo meria | Ako jej dlh škodí | Kde ju získať |
|---|---|---|---|
| Frekvencia nasadení | Ako často dodávate do produkcie | Krehký kód núti tímy zmeny zhlukovať | Logy nasadení v CI/CD |
| Čas dodania zmeny | Od commitu po beh v produkcii | Pomalé review, nestabilné testy, ručné kroky | Časové značky z gitu a nasadení |
| Podiel neúspešných zmien | Podiel nasadení, ktoré spôsobia incident alebo rollback | Previazaný kód sa láme na nečakaných miestach | Evidencia incidentov + nasadenia |
| Čas obnovy služby | Ako dlho trvá zotavenie | Slabá pozorovateľnosť, riskantné rollbacky | Časové značky incidentov |
Pred začiatkom si zaznamenajte východiskový stav, štyri čísla prechádzajte mesačne a odolajte pokušeniu robiť z nich individuálne ciele. Opisujú systém, nie ľudí.
Ako vysvetliť dlh netechnickým ľuďom
Dlh vysvetľujte v mene, ktorú už vaši partneri používajú: čas uvedenia na trh, riziko a peniaze. Nikto mimo vývoja nepotrebuje počuť o previazanosti kódu či pokrytí testami. Potrebujú počuť, že zmena cien trvá týždeň namiesto dňa a že posledné dva výpadky prišli z toho istého modulu.
- Pomenujte biznisový symptóm. „Každá zmena cien trvá päť dní a tento štvrťrok dvakrát rozbila pokladňu.“
- Uveďte úrok. „Stojí nás to zhruba jeden inžiniersky deň na zmenu, plus čas na incidenty.“
- Navrhnite ohraničený krok. „Dva šprinty z nášho bežného rozpočtu na dlh na vyčlenenie cenového modulu.“
- Sľúbte merateľný výsledok. „Čas dodania zmien cien pod dva dni, sledovaný na DORA dashboarde.“
- Podajte správu. Ukážte stav pred a po. Dôvera, ktorú tu získate, zafinancuje ďalšiu položku.
Práca na dlhu, ktorú nedokážete vysvetliť ako rýchlejší alebo bezpečnejší produkt, zvyčajne nie je dlh, ktorý treba splácať ako prvý.
Ako vám môže pomôcť Backloo
Ak je váš tím vyťažený, externý inžinier môže urobiť meranie, zostaviť prvý register a zvládnuť najriskantnejšie refaktoringy, kým váš tím ďalej dodáva. To je jadro našich plánov údržby a SLA: pevný mesačný rozpočet na aktualizácie, monitoring a plánovanú prácu na dlhu.
Pri väčších štrukturálnych problémoch, napríklad pri backende, ktorý prerástol svoj prvý návrh, plánujeme migráciu podľa vzoru strangler fig v rámci backendových systémov. Neviete, kde začať? Rescue Audit vám dá zoradený písomný prehľad dlhu — a vždy sa nám môžete najprv ozvať.
Otázky
Koľko kapacity šprintu by malo ísť na technický dlh?
Univerzálne číslo neexistuje. Zvoľte pevný podiel, ktorý dokážete udržať v každom šprinte, napríklad jeden deň z desiatich, chráňte ho a po štvrťroku ho upravte podľa metrík DORA a vývoja incidentov.
Je úplný prepis niekedy správna voľba?
Niekedy áno — keď platforma už nemá podporu alebo je dátový model v jadre chybný. Aj vtedy je postupná náhrada pomocou vzoru strangler fig zvyčajne bezpečnejšia než prepnutie naraz. Skôr než sa zaviažete, zdôvodnite to písomne a s dôkazmi.
Aký je rozdiel medzi registrom dlhu a backlogom?
Backlog obsahuje zoznam práce. Register dlhu obsahuje známy dlh s dôkazmi, priebežnou cenou, rizikom a vlastníkom, takže každú položku možno zoradiť oproti funkciám v biznisových pojmoch. Zostáva krátky a prechádza sa mesačne.
Aké nástroje potrebujem na meranie technického dlhu?
Na začiatok iba históriu gitu, váš linter a evidenciu incidentov. Na nájdenie prvých hotspotov stačí spojiť churn, zložitosť a označenia incidentov v tabuľke. Špecializované nástroje pridajte, keď sa z toho stane zvyk.