Переписать или отрефакторить: решение по фактам, а не по настроению
Какие признаки говорят за переписывание, какие за рефакторинг, как собрать их за неделю и почему чаще всего выигрывает гибрид.
Рано или поздно в каждом проекте, выросшем из прототипа, кто-то говорит: «Проще переписать». Иногда это правда. Чаще это усталость, сказанная уверенным голосом. Новый код всегда выглядит чище старого — хотя бы потому, что его ещё нет.
Решение стоит принимать не по ощущению от кода, а по нескольким наблюдаемым вещам. Собрать их можно за неделю, и эта неделя дешевле любой ошибки в обе стороны.
Что на самом деле болит
Начни с того, что мешает бизнесу, а не с того, что некрасиво. Вопросы:
- Сколько времени занимает типичная небольшая правка от задачи до продакшна?
- Как часто правка в одном месте ломает что-то в другом?
- Есть ли в коде места, к которым никто не хочет прикасаться?
- Понимает ли кто-нибудь в команде, как работает ключевой сценарий целиком?
Если правки идут быстро и ломается редко, код может быть сколь угодно некрасивым — переписывать его незачем. Если каждая задача превращается в расследование, это уже не про эстетику.
Признаки, что переписывать стоит
- Неправильная модель данных. Это главный признак. Если сущности перепутаны, связи хранятся в JSON-строках, а одно и то же понятие живёт в трёх таблицах под разными именами, рефакторинг кода поверх такой схемы бесполезен. Код можно чинить по кусочку, схему — гораздо труднее.
- Платформа не тянет то, что нужно. Генератор приложений, из которого нельзя выйти, фреймворк без нужной возможности, хостинг, который не даёт фоновых задач.
- Безопасность не лечится точечно. Когда доступ проверяется в сотне мест по-разному и общего слоя нет, проще построить его заново, чем найти все сто мест.
Признаки, что достаточно рефакторинга
- Модель данных в целом верна, даже если поля названы странно.
- Проблемы сосредоточены в нескольких модулях, а не размазаны по всему коду.
- Основные сценарии работают, и пользователи ими довольны.
- Команда может описать, что делает каждая крупная часть.
Чем опасно переписывание
Старый код хранит знание, которое нигде не записано: обработку странных случаев, исправления после жалоб, договорённости с партнёрами. Переписывая, ты теряешь его и находишь заново — уже на пользователях.
Второй риск — заморозка. Пока идёт переписывание, новых функций нет, а старую версию всё равно приходится поддерживать. Две системы вместо одной, и обе недоделаны. Переписывание, которое занимает больше пары месяцев без промежуточных выпусков, часто так и не заканчивается.
Гибрид обычно выигрывает
Почти всегда есть третий путь: заменять по частям, оставляя систему рабочей.
- Начни с данных. Если схема плохая, спроектируй правильную и переведи на неё один сценарий целиком, с миграцией данных. Остальные пусть пока читают через слой совместимости.
- Новые модули — по-новому. Новый функционал пишется на новой основе, а старый код переводится на неё, когда до него доходит работа.
- Худшее — первым. Переписывается не «всё», а два-три модуля, где больше всего ошибок и правок. Остальное рефакторится по ходу.
- Перед заменой — тесты на текущее поведение. Не на то, как «должно быть», а на то, как работает сейчас. Тогда ты увидишь, что изменил, и решишь, хотел ли.
Каждый шаг выпускается в продакшн отдельно. Если на середине пути деньги или приоритеты закончатся, у тебя останется работающая система, которая стала лучше, а не две половины разных систем.
Как оформить решение
Через неделю у тебя должна быть короткая карта: список модулей, для каждого — оценка состояния, частота правок и ошибок, и решение: оставить, отрефакторить или заменить. Такую карту можно обсуждать с командой и с теми, кто платит за работу, — в отличие от «мне кажется, тут всё плохо».
SUBXCAT делает такой разбор для проектов, выросших из прототипов, и помогает пройти выбранный путь без остановки продукта.