Legacy-код — це не поганий код, це код, що пережив контекст, для якого його писали. Бізнес працює на ньому, ніхто повністю його не розуміє, і кожна зміна — маленький акт мужності. Ми рефакторимо й модернізуємо такі системи без переписування "з нуля", яке триває рік і нічого не дає.
Як ми підходимо
- Спершу аудит — мапимо, що там насправді: залежності, мертвий код, проблеми безпеки, частини, яких всі бояться торкатись.
- Characterization tests — перед будь-якою зміною пишемо тести, що фіксують, що код робить сьогодні, включно з багами. Поведінку закріплено до того, як її змінено.
- Інкрементальна заміна — патерн strangler: нові фічі йдуть у новий код, гарячі шляхи мігрують модуль за модулем, стара система скорочується, доки її можна вимкнути.
Поступова заміна за патерном Strangler Fig
public function test_invoice_rounding_is_pinned(): void
{
$legacy = new LegacyInvoiceCalculator();
// Characterization test: pins current behaviour, quirks included.
$this->assertSame(1049.99, $legacy->total($this->fixtureOrder()));
}
Перед змінами legacy-коду ми фіксуємо його поведінку характеризаційними тестами — навіть дивацтва. Рефакторинг може змінити код, але не спостережуваний результат.
Старе й нове працюють поруч на одній базі. Роутинг вирішує, яка фіча куди йде. Ніколи не буває моменту, коли бізнес чекає на завершення переписування — цінність відвантажується безперервно.
Що ми зазвичай знаходимо
Кодові бази епохи PHP 5, spaghetti без фреймворку, покинуті застосунки на Symfony 2/3, WordPress-сайти на шістдесятьох плагінах. Типові перемоги: апгрейд на підтримувану версію PHP, обгортка фреймворком навколо наявного коду, заміна найгірших запитів і деплої на рейках, щоб зміни перестали лякати.
Якщо у вас система, що працює, але ніхто не наважується її змінювати — це саме та форма проєкту, з якою ми працюємо. Покажіть код — скажемо, що варто лишити.