ZpětInženýrství

Refactoring legacy kódu: survival guide

Září 202510 min

Refaktor není přepis. Je to kontrolovaná změna se záchrannou sítí. Přepis vsadí celou roadmapu na kód, který nikdy neběžel v produkci; refaktor je série malých, vratných sázek, při kterých systém celou dobu normálně slouží. Zdědil jsem dost legacy systémů na to, abych tenhle rozdíl bral jako pravidlo přežití, ne jako otázku vkusu.

Začněte správnou definicí. Legacy kód není starý kód — je to kód, kterého se bojíte dotknout. Ten strach pramení z chybějících testů, chybějící dokumentace a z lidí, kteří už ve firmě dávno nejsou. Odvaha to nevyřeší. Záchranná síť ano — a staví se v konkrétním pořadí.

Nejdřív to udělejte měřitelné

Přidejte logy, metriky a testy kolem částí, které chcete měnit. Co nevidíte, nemůžete zlepšit — a v legacy systému je většina podstatného neviditelná, dokud ji nezměříte. Než sáhnu na jediný řádek, chci na dashboardu tři čísla: chybovost, latenci a jednu byznysovou metriku, kterou modul reálně ovlivňuje — třeba dokončené objednávky nebo vystavené faktury. Tahle čísla pak rozhodují každý spor o každé další změně. Bez nich se debata o refaktoru zvrhne v souboj názorů — a vyhraje ten, kdo mluví nejhlasitěji, ne ten, kdo má pravdu.

Potom zafixujte současné chování charakterizačními testy. Ty netvrdí, co by kód měl dělat — to už nikdo neví. Tvrdí, co dělá dnes, včetně chyb, protože na té chybě někde nejspíš závisí zákazník. Pusťte do modulu nahraná produkční data, uložte výstupy a při jakémkoli rozdílu ať test hlasitě spadne:

test('ceny odpovídají současnému chování produkce', () => {
  const result = calculatePrice(recordedOrder);
  expect(result).toMatchSnapshot(); // zafixuj dnešní výstup, i s podivnostmi
});

Dvacet takových testů napsaných za den vás ochrání líp než týden čtení kódu a naděje, že jste ho pochopili.

Refaktorujte za seams

Vytvořte hranice, přidejte adaptéry a posouvejte kód postupně. Seam je místo, kde můžete změnit chování, aniž byste editovali kód, který ho vytváří: rozhraní před cenovým enginem, repozitář před syrovým SQL, fronta mezi dvěma moduly, které si potají sdílejí stav. Najděte seam — nebo ho vyřízněte — a schovejte za něj starou implementaci. Nová implementace pak žije za stejným kontraktem a feature flag rozhoduje, která z nich odpoví na který požadavek.

Provoz pak přesouvejte tak, jak roste škrtivý fíkus — strangler fig: jeden endpoint, jeden tenant, jedno procento requestů na novou cestu, porovnávejte výstupy se starou verzí a s rostoucí jistotou podíl rozšiřujte. Legacy kód umře na nepoužívanost, ne na riskantní delete. Big-bang refaktory jsou cestou do pekla — šest měsíců na dlouho žijící větvi, nula doručené hodnoty a merge day, kterého se bojí celý tým. Ten film jsem viděl; nekončí dobře.

Principy, které vás udrží v bezpečí

  • Malé PR s jasným záměrem. Jeden refaktor na jeden pull request. Reviewer má být schopen potvrdit „chování beze změny“ za pár minut, ne po archeologickém průzkumu.
  • Feature flagy tam, kde je riziko vysoké. Flag promění rollback z nouzového deploye ve změnu konfigurace — vteřiny místo incidentu.
  • Měřte výkon před a po. „Čistší“ kód, který zdvojnásobí latenci, není čistší v ničem, co uživatel pozná. Ať spor rozhodne dashboard.
  • Udržujte rollback cestu. Každý krok musí být vratný. Když změnu nedokážu vrátit během minut, je krok moc velký — rozdělte ho.

Nic z toho není efektní a přesně o to jde. Refaktor legacy kódu je složené úročení: každý vyříznutý seam, každý zafixovaný test, každá přidaná metrika zlevňuje další změnu. Cílem nikdy nebyl krásný kód. Cílem je systém, který změníte v úterý odpoledne bez zatajeného dechu — zatímco celou dobu obsluhuje zákazníky.

Další

Zpět na přehled