Когда переписывать проект: признаки и типичные ошибки
Переписывание кажется быстрым способом избавиться от старого кода, но часто превращается в дорогую вторую разработку. Разбираем, какие сигналы действительно оправдывают замену и как сравнить её с постепенной миграцией.

Переписывать проект или нет: сначала посчитайте цену простоя
Если команда месяцами исправляет одни и те же дефекты, а каждое изменение затрагивает десятки несвязанных частей системы, переписывание начинает выглядеть разумным. Но старый код хотя бы работает и содержит решения, о которых документация умалчивает. Новый проект может годами догонять его по функциям, пока бизнес платит за две системы сразу.
Универсальной версии языка или фреймворка для такого решения нет: статья относится к проектам на любых стеках. Сравнивайте не «старый код» и «чистую архитектуру», а стоимость конкретных вариантов на горизонте нескольких релизов. Обычно их три: оставить систему и чинить точечно, переписать целиком или заменять по частям.
Какие сигналы действительно важны
Возраст проекта сам по себе не причина для переписывания. Система на устаревшем стеке может быть стабильной и дешёвой в сопровождении. А недавно написанный сервис — плохо разделённым и опасным для каждого изменения.
Соберите факты за последние релизы. Например:
- Сколько времени проходит от готовой задачи до выкладки и какая доля этого времени уходит на ручные проверки и обходные пути.
- Как часто изменения вызывают регрессии в функциях, которые не входили в задачу.
- Сколько инцидентов связано с одной и той же границей системы или компонентом.
- Какие изменения нельзя безопасно внести из-за отсутствия тестов, владельцев или документации.
- Есть ли обязательная причина смены: прекращение поддержки платформы, требования безопасности или недоступность критической зависимости.
Один неприятный релиз ничего не доказывает. Повторяющийся ущерб — повод разбираться. Отдельно оцените цену бездействия: часы инженеров на поддержку, задержанные функции, инциденты и риск, что нужную компетенцию скоро будет трудно найти.
Переписывание оправдано не тем, что новый код будет красивее, а тем, что измеримый ущерб от старого решения превышает стоимость перехода.
Три подхода и их цена
Не сравнивайте только стоимость разработки. В расчёт входят поддержка старой системы во время перехода, перенос данных, проверка эквивалентности поведения, обучение команды и возможный простой.
| Подход | Что выигрываете | Чем платите | Когда рассматривать |
|---|---|---|---|
| Точечное улучшение | Небольшой риск и быстрый эффект для конкретной проблемы | Сложные границы и ограничения могут остаться | Проблема локальна, система в целом поставляет изменения |
| Полная замена | Можно изменить архитектурные предпосылки и убрать накопленные ограничения | Долгая параллельная разработка, потеря скрытых функций, сложный запуск | Есть жёсткая причина менять основу, понятен объём и профинансирован переход |
| Постепенная замена | Переход можно проверять на реальном трафике и ограничивать по масштабу | Временно приходится поддерживать две системы и маршрутизацию между ними | Можно выделить границы и переносить функции по одной |
Постепенная замена1 означает, что старую систему не выключают одним решением: отдельную функцию переносят, проверяют, а затем переключают на новую реализацию. Это не бесплатный компромисс. Пока переход не завершён, двойная поддержка может съесть значительную часть команды.
Типичные ошибки при принятии решения
Путать неприязнь к коду с ущербом для бизнеса
«Здесь невозможно работать» — мнение, а не оценка. Спросите, какая конкретно задача стала медленнее, сколько раз это произошло и сколько времени команда потратила. Если подтверждений нет, начните с небольшого изменения в проблемной области и измерьте результат. Возможно, дефект сидит в одном модуле, а не во всём проекте.
Переносить только видимые функции
Старая система часто выполняет неочевидную работу: принимает нестандартные форматы, повторяет неудачные операции, отправляет уведомления или поддерживает редкий сценарий клиента. Список кнопок в интерфейсе не заменяет карту поведения. До разработки соберите логи, обращения поддержки, фоновые задачи, интеграции и правила обработки ошибок.
Откладывать запуск до полной готовности
Большая новая система долго не получает проверки реальными пользователями и данными. Чем позже обнаружится расхождение, тем дороже исправление. Разбейте переход на вертикальные части: функция должна пройти весь путь от входа до результата, а не существовать только как новый слой базы данных.
Считать параллельную работу бесплатной
Старый проект продолжает требовать исправлений и поддержки, пока команда строит новый. Если план не учитывает это, срок выглядит короче реального, а инженеры переключаются между задачами и теряют контекст. Зафиксируйте, кто поддерживает старую систему, кто переносит функции и какие работы временно не берут в план.
Не определить, как сравнить результаты
До переноса выберите показатели для конкретной проблемы: время выпуска изменения, частоту откатов, число инцидентов, длительность обработки запроса или часы поддержки. Не обещайте улучшение без исходных данных. Сравнивайте одинаковые сценарии и одинаковые условия, иначе «после» не доказывает, что новая система лучше.
Как выбрать подход на практике
- Опишите ущерб. Запишите три повторяющиеся проблемы, их последствия и примеры за последние релизы. Проверка: у каждой проблемы есть событие, а не только общая оценка.
- Ограничьте область. Найдите компонент или сценарий, где ущерб возникает чаще всего. Проверка: можно назвать функцию, поток данных или команду-владельца, а не весь проект целиком.
- Сравните три оценки. Прикиньте работу для точечного исправления, полной замены и поэтапного переноса; включите поддержку старой системы и проверку данных. Проверка: в оценке есть переход, тестирование и эксплуатация, а не только написание кода.
- Проверьте границу на небольшом переносе. Выберите функцию с понятным входом и результатом. Проверка: можно сопоставить поведение старой и новой реализации на реальных сценариях и быстро вернуть прежний путь.
- Решите, продолжать ли. Сравните измеренный эффект с затратами на поддержку двух вариантов. Проверка: у команды есть критерий остановки, а не только дата, к которой «надо закончить».
Полная замена имеет смысл, если ключевое ограничение затрагивает почти всю систему, постепенный перенос технически невозможен или платформа создаёт неприемлемый риск. Если проблема сосредоточена в нескольких областях, обычно безопаснее начать с них. А если команда не может назвать ущерб, сначала улучшите наблюдаемость и зафиксируйте стоимость текущей поддержки.
Когда план ломается
Постепенная миграция тоже может зайти в тупик. Границы функций оказываются тесно связаны, данные одновременно меняют обе системы, а временная маршрутизация становится постоянной. Чтобы это заметить, для каждого перенесённого участка определите владельца, способ сверки результата и условие отключения старого пути.
Особенно рискованны данные, которые обе системы могут изменять независимо. До переключения решите, где находится источник истины и как вы обнаружите расхождение. Если безопасного отката нет, сначала проведите репетицию на копии данных и подготовьте процедуру восстановления. Подробная стратегия миграции данных зависит от хранилища и формата; смешивать её с решением о переписывании не стоит.
Не масштабируйте опыт одного удачного модуля на весь проект автоматически. Следующая область может иметь другие зависимости и цену ошибки. Пересматривайте план после каждого этапа, а не только по календарю.
Что делать дальше
Возьмите ближайшую проблемную область и составьте одностраничную карточку: симптом, ущерб, владельцы, зависимости, варианты решения и показатели до изменения. Затем выберите небольшой перенос или исправление, которое можно проверить и при необходимости отменить. Если после него команда не может показать улучшение в выбранной метрике, расширять переписывание рано.
Отдельно стоит изучить постепенную замену старой системы по шаблону Strangler Fig: это подход к миграции, а не гарантия, что миграция будет дешевле. Для оценки накопленных компромиссов полезно также различать технический долг и просто старый код.
1 Strangler Fig — архитектурный приём, при котором новые реализации постепенно берут на себя функции старой системы, пока её не удаётся отключить.
Редактор изображений: Убрать лишнее, заменить фон, добавить объект, расширить кадр — на вашем изображении.
Спросить за 20 ₽Источники: Martin Fowler: Strangler Fig Application, Martin Fowler: Technical Debt
Частые вопросы
Как понять, что проект действительно пора переписывать?
Что делать, если старый проект написан на неподдерживаемом стеке?
Можно ли переписать проект без поддержки двух систем одновременно?
Как избежать потери функций при переписывании?
Какие версии языка или фреймворка использовать в новой системе?
Что измерять после переноса первой функции?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.