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 %

technologického rozpočtu na nové produkty sa presúva na riešenie technického dlhu; dlh tvorí 20–40 % hodnoty celého technologického majetku firmy. — McKinsey, „Tech debt: Reclaiming tech equity“ ↗

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.

bash
# 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 -30

Nekomplikujte 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.

Minimálny záznam v registri dlhu
PolePríkladPrečo na tom záleží
PoložkaLogika cien objednávok duplikovaná v API aj v administráciiPomenúva problém, nie riešenie
DôkazTop 3 hotspot; 2 incidenty minulý štvrťrokSpája ho s merateľnou bolesťou
ÚrokKaždá zmena cien sa dotkne 2 kódových báz, ~1 deň navyšePriebežná cena nečinnosti
RizikoVysoké: k zákazníkom sa dostanú nesprávne cenyDopad na biznis, ak to zlyhá
Navrhovaný krokVyčleniť cenový modul za jedno rozhranieNajmenšia zmena, ktorá pomôže
VlastníkKonkrétny inžinierNiekto za to zodpovedá
StavĎalší šprintViditeľ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.

ts
// 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ú.

Štyri kľúčové metriky DORA a ako sa v nich prejavuje dlh
MetrikaČo meriaAko jej dlh škodíKde ju získať
Frekvencia nasadeníAko často dodávate do produkcieKrehký kód núti tímy zmeny zhlukovaťLogy nasadení v CI/CD
Čas dodania zmenyOd commitu po beh v produkciiPomalé review, nestabilné testy, ručné krokyČasové značky z gitu a nasadení
Podiel neúspešných zmienPodiel nasadení, ktoré spôsobia incident alebo rollbackPreviazaný kód sa láme na nečakaných miestachEvidencia incidentov + nasadenia
Čas obnovy službyAko dlho trvá zotavenieSlabá 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.

  1. Pomenujte biznisový symptóm. „Každá zmena cien trvá päť dní a tento štvrťrok dvakrát rozbila pokladňu.“
  2. Uveďte úrok. „Stojí nás to zhruba jeden inžiniersky deň na zmenu, plus čas na incidenty.“
  3. Navrhnite ohraničený krok. „Dva šprinty z nášho bežného rozpočtu na dlh na vyčlenenie cenového modulu.“
  4. Sľúbte merateľný výsledok. „Čas dodania zmien cien pod dva dni, sledovaný na DORA dashboarde.“
  5. 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.

Čítajte ďalej

  • 01 — Záchrana · 10 min čítania

    Aplikácia z Lovable alebo Bolt funguje v náhľade, ale v produkcii padá: príčiny a riešenia

    Väčšina aplikácií postavených s AI, ktoré fungujú v náhľade a v produkcii zlyhajú, sa kazí z tej istej hŕstky dôvodov: premenné prostredia zapečené pri builde, presmerovania prihlásenia stále mieriace na náhľad, chýbajúca autorizácia v databáze, webhooky, ktoré nie sú idempotentné, CORS a žiadny monitoring chýb. Každý z nich má konkrétnu a overiteľnú opravu.

  • 02 — Záchrana · 9 min čítania

    Checklist Supabase Row Level Security pre aplikácie postavené s AI (s SQL)

    Ak vaša aplikácia komunikuje so Supabase priamo z prehliadača, Row Level Security je vaša kontrola prístupu. Zapnite RLS na každej vystavenej tabuľke, napíšte jednu politiku na operáciu s auth.uid(), kľúč service_role držte na serveri, zabezpečte storage buckety a testujte ako anonymný používateľ aj ako druhý účet. SQL na skopírovanie nájdete nižšie.

  • 03 — Biznis · 7 min čítania

    Záchrana, refaktoring, alebo prepis? Ako sa rozhodnúť, čo s kódom postaveným s AI

    Zachraňujte, keď produkt funguje a problémom je bezpečnosť, konfigurácia a chýbajúce poistky. Refaktorujte, keď funguje, ale každá zmena je pomalá a riskantná. Prepisujte iba vtedy, keď je dátový model alebo platforma v jadre zlá — a aj vtedy po častiach. Rozhoduje dátový model, nie to, ako neupratane kód vyzerá.

100 — INSIGHTS

Zaseknutí medzi demom a spustením?

Pošlite nám kontext. Do 24 hodín dostanete odpoveď s plánom — alebo úprimné nie.