Перейти к основному содержимому

Что такое легаси и как его узнать

Разработчику Архитектору
Теория данных (раздел 3)

Вы открываете репозиторий — и видите модули, которые писали до вас — другая команда, другой стиль, иногда другой век технологий. Это обычная рабочая ситуация. Раздел помогает снизить страх перед таким кодом и не романтизировать переписывание с нуля.

Дальше: как понять системукак менять безопасностратегии замены.


Два смысла слова "легаси"

В разговорах смешивают два определения. Оба правомерны — важно понимать, о каком говорит собеседник.

СмыслОбычно имеют в видуГлавный риск
НаследиеСтарый стек, чужой стиль, "код не я писал"найм, безопасность, лицензии, совместимость
По Фезерсу (Working Effectively with Legacy Code)Любой код без автоматизированных тестовлюбое изменение может сломать неочевидное поведение

Наследие — про время и контекст — Java 8, монолит, модуль, который три года никто не трогал, но он держит расчёт зарплат. Код может быть аккуратным — и всё равно "легаси" для новичка в проекте.

По Фезерсу — про изменяемость: нет сетки тестов → нет быстрой обратной связи → каждая правка рискованна. Возраст тут ни при чём: вчерашний сервис без тестов уже легаси в инженерном смысле.

В остальных статьях раздела опора на оба смысла — сначала оцениваем стек и знания команды, затем строим защиту изменений (тесты, швы, наблюдаемость). Подробнее про тесты — в Юнит-тестирование; про читаемость и имена — в Культуре кода; про техдолг в коде — 4.06/115.


Почему легаси неизбежен

Легаси появляется из реальных ограничений, а не из "плохих программистов прошлого":

  • смена команд и потеря устного контекста;
  • сроки релиза и осознанные компромиссы (технический долг — в методологии PO);
  • отсутствие или устаревание документации;
  • естественное старение платформ и зависимостей.

Банки, логистика, госсектор, производство десятилетиями крутят системы, которые нельзя выключить на квартал ради rewrite. Переписывание с нуля часто рискованнее, чем эволюция — об этом в стратегиях модернизации.

Работа с легаси — дисциплина — реверс и контекст, маленькие шаги рефакторинга, защита от регресса, фиксация знаний для следующих людей.


"Тихое" и "кричащее" легаси

Удобная метафора для приоритизации:

  • Тихое — работает, инциденты редки, но дорого сопровождать — долго разобраться, страшно менять, мало кто понимает.
  • Кричащее — частые сбои, непредсказуемые баги, ручные обходы в проде, "магия" при деплое.

Оба типа могут быть без тестов. Разница в том, как срочно нужны наблюдаемость и защитный слой тестов: у "кричащего" — в первую очередь.


Признаки легаси-кода

Признаки накладываются — один модуль может попадать сразу в несколько пунктов.

  1. Нет тестов или покрытие формальное. Тесты "для галочки", не ловят регресс на бизнес-путях — по сути то же отсутствие защиты.
  2. Устаревший стек. Неподдерживаемые версии языка, фреймворка, ОС; библиотеки с известными CVE без патча.
  3. Документация врёт или отсутствует. Описан "идеальный" дизайн 2012 года, а в коде — пять слоёв заплаток.
  4. Архитектурная связанность. Всё дергает всё — глобальное состояние, циклы зависимостей модулей, БД из UI.
  5. Высокая когнитивная нагрузка. Непонятные имена, функции на сотни строк, неочевидные побочные эффекты. Отсутствие комментариев само по себе слабый признак — см. культуру кода. Опасны комментарии, противоречащие коду.
  6. Сборка и деплой вручную. "Только на машине Васи", скрипт из письма, секреты в конфиге без версионирования.
  7. Растущий техдолг. Каждая фича занимает всё больше времени; одни и те же места ломаются снова.

Критическое наследие (экстремальный случай)

Не всякий старый код одинаково болезненен. Критическое легаси — когда стоимость ошибки и неопределённость максимальны:

  • бинарные .dll / .so без исходников;
  • история в VCS обрезана или отсутствует (один "initial commit" на весь зоопарк);
  • в одной процедуре смешаны UI, бизнес-логика, SQL и сеть;
  • "хаки" платформы: самописный SQL-конкатенацией, обходы багов ОС;
  • привязка к железу или ОС, которую нельзя воспроизвести в CI;
  • нет логов: падение без сообщения.

Тут нужны навыки разработки и расследования — реверс, интервью, песочница — см. Понимание системы.


Управляемое ("здоровое") легаси

Легаси может быть управляемым. Такое наследие может быть на старом стеке, но:

  • понятные границы модулей;
  • логика соответствует бизнес-правилам (пусть и не самым новым API);
  • есть тесты на критичных путях или жёсткий ручной регресс с чек-листом;
  • есть хотя бы схема архитектуры (C4, блок-схема в /docs);
  • сборка и деплой воспроизводимы скриптом;
  • имена и структура читаемы.

Такой код можно эволюционировать — без clean room и без "большого взрыва". Он может быть неидеален по модным метрикам, но предсказуем.


Мини-пример — один возраст — разная изменяемость

Старый, но понятный модуль с тестом:

# discounts.py — поведение зафиксировано
def legacy_vip_discount(base: int) -> int:
return int(base * 0.9) # исторически округление вниз

# test_discounts.py
from discounts import legacy_vip_discount

def test_vip_discount_unchanged():
assert legacy_vip_discount(100) == 90

Монолитная "простыня" без тестов (фрагмент):

function processOrder(order) {
// валидация, скидка, налог, SQL, email, аудит — 200+ строк
if (order.region === 'EU') { /* ... */ }
}

Первый случай — легаси по контексту, но изменяемый. Второй — легаси по Фезерсу до появления тестов и извлечения функций (безопасные изменения).


Технический долг и легаси

Технический долг — накопленные компромиссы (скорость вместо структуры, отложенные тесты, временные костыли). В легаси он проценты растут: правка в одном месте тянет цепочку неожиданных эффектов.

Долг неизбежен в agile-командах, если его не видят: нет реестра, нет слотов в спринте на погашение — через год "маленькая фича" превращается в неделю риска. Работа с легаси — это и погашение долга маленькими порциями, а не ожидание "когда-нибудь перепишем".


Культура отношения к наследию

Полезные установки в команде:

  • Искать контекст (задача, срок, ограничение платформы), а не винить отсутствующих авторов.
  • Фиксировать открытия в репозитории — ADR, комментарий к модулю, диаграмма — не только в чате.
  • Менять узко: задача → тест → правка → ревью; без "попутного" переписывания соседнего модуля.
  • Уважать то, что работает — странное поведение может быть требованием регулятора или контракта с партнёром.

Чек-лист по разделу — в конце; следующий шаг — как копать систему и восстанавливать контекст.