Переписать или рефакторить: когда пересобирать продукт
Продвинутое3 минРедакция Innovialabs
Коротко
В большинстве случаев безопаснее постепенный рефакторинг с заменой частей системы по одной; полная переработка оправдана, только когда старая основа мешает бизнесу и не может быть исправлена по частям.
Короткий ответ
По умолчанию выбирайте рефакторинг — постепенное улучшение кода без изменения поведения продукта. Он позволяет продолжать выпускать функции, а риск распределяется на много маленьких шагов.
Полная переработка (rewrite) оправдана реже, чем кажется команде. Она имеет смысл, когда текущая платформа фундаментально не выдерживает требований бизнеса, а исправить это по частям дороже, чем построить заново. И даже тогда лучше переписывать не «всё сразу», а модуль за модулем.
Почему переписать хочется чаще, чем нужно
Старый код всегда выглядит хуже, чем он есть. В нем годами копились исправления реальных проблем: обработка редких случаев, интеграции, особенности поведения клиентов. При переписывании эти знания легко потерять — и потом заново найти их через баги на продакшене.
Еще одна ловушка — движущаяся цель. Пока новая версия строится, старая продолжает меняться, и новой приходится догонять. Проект растягивается, бизнес месяцами не получает новых функций.
Критерии выбора
| Признак | Скорее рефакторинг | Скорее переработка |
|---|---|---|
| Архитектура | Неудобна, но позволяет развиваться | Блокирует ключевые требования: масштаб, безопасность, интеграции |
| Технологии | Устаревшие, но поддерживаемые | Платформа или язык больше не поддерживаются, нет специалистов |
| Знание системы | Команда понимает, как всё работает | Никто не знает, как работает код, документации нет |
| Тесты | Есть или их можно добавить | Добавить невозможно без перестройки |
| Бизнес-модель | Продукт решает ту же задачу | Продукт кардинально изменился |
| Ресурсы | Нужно параллельно выпускать функции | Можно выделить команду и время на переход |
Если большинство признаков в левой колонке — рефакторинг. Если явно доминирует правая — рассматривайте переработку, но поэтапную.
Когда рефакторинг не работает
- Каждое изменение ломает что-то в неожиданном месте, и это не исправляется тестами.
- Невозможно обновить фреймворк или зависимости без переписывания большей части кода.
- Производительность упирается в архитектуру, а не в отдельные медленные места.
- Требования безопасности или регуляторики нельзя выполнить на текущей основе.
Подход к миграции: замена по частям
Самый надежный способ — паттерн Strangler Fig («удушающая смоковница»): новая система постепенно растет вокруг старой и забирает ее функции по одной.
- Зафиксируйте текущее поведение. Напишите тесты на ключевые сценарии, особенно на деньги, заказы, права доступа.
- Поставьте точку маршрутизации. API-шлюз или прокси, который решает, какой запрос обработает старая система, а какой новая.
- Выберите первый модуль. Лучше тот, что достаточно изолирован и при этом приносит ощутимую пользу.
- Перенесите и сравните. Запускайте новую реализацию параллельно, сверяйте результаты, переключайте трафик постепенно.
- Отключайте старое. Удаляйте код старого модуля, когда новый стабилен. Иначе вы будете поддерживать две системы.
- Повторяйте для следующих модулей.
Отдельное внимание — миграции данных. Их нужно прогонять заранее на копии продакшен-данных, проверять целостность и иметь план отката.
Главные риски
- Потеря скрытой логики — решается тестами и общением с теми, кто знает систему.
- Замороженная разработка — бизнес не может ждать месяцами; планируйте так, чтобы новые функции продолжали выходить.
- Две системы навсегда — миграция застревает на последних, самых сложных модулях. Нужен четкий план отключения старого.
- Повторение тех же ошибок — если не понять, почему старый код стал плохим, новый ждет та же судьба.