Большой рефакторинг партиями: как разобрать код без хаоса
Когда правок накопилось на неделю, соблазн сделать всё разом заканчивается сломанным проектом. Показываю на своём кейсе REOS, как я вожу большие переделки батчами: один заход — одна проверка вживую.
Большой рефакторинг пугает не объёмом работы. Пугает другое: момент, когда ты уже переписал половину, ничего не запускается, и непонятно, какая из двадцати правок всё уронила. Я прошёл через это не раз и вывел простое правило: большие переделки идут батчами. Один заход — одна порция изменений — проверка на живом продукте. Дальше разберу на реальном кейсе, как это выглядит.
Почему «сделать всё разом» не работает
Когда правок много, мозг хочет закрыть их одним рывком. Логика вроде здравая: контекст уже в голове, зачем растягивать. На деле выходит наоборот. Двадцать перемешанных изменений превращаются в один непроверяемый ком. Что-то сломалось — а ты не знаешь, что именно, потому что трогал всё сразу. Откатывать больно: вместе с плохим уедет и хорошее. Такой заход невозможно ни отревьюить, ни диагностировать.
Батч снимает ровно эту боль. Ты дробишь большую задачу на куски, каждый из которых проверяется и откатывается отдельно. Стоимость ошибки падает до размера одного батча.
Как я собираю план батчей
Перед тем как трогать код, я фиксирую решения. У меня был проект REOS — система учёта задач по объектам недвижимости. Накопилась пачка правок, и мы с владельцем сели на мозгоштурм, чтобы разложить их по заходам.
Главное на этом этапе — закрыть развилки. Пока не решено, что делаем, батч не начинается. Вот что мы зафиксировали:
- Идею с группами проектов в баре просто выкинули. Меньше кода — меньше проблем.
- Типы задач сделали настраиваемыми наборами: «Недвижка» и «Компания», список правится в настройках.
- Задачи развели на два уровня: привязанные к объекту и уровня компании.
- «Общие финансы компании» реализовали как фильтр задач по типу, без отдельной агрегации.
Половина решений здесь — это отказ от лишнего. Самый дешёвый батч тот, который вообще не нужно писать.
Каждый пункт превращается в отдельный заход. Типы задач — один батч, правка бара — другой, вместе их не мешаем. Свалить несвязанные правки в один заход — та же ошибка, что делать всё разом, только в миниатюре.
Правило: батч заканчивается проверкой вживую
Это ключевой момент. Заход завершается не коммитом. Он завершается проверкой на живом продукте. Открыл, потыкал руками, убедился, что работает так, как задумано. Только после этого берёшь следующий батч.
Зачем так строго. Тесты ловят логику, но пропускают «а вот эту кнопку теперь не видно» или «фильтр работает, но выдаёт не то, что человек ожидает». Живая проверка после каждого батча даёт быструю обратную связь. Сломалось — ты знаешь ровно, в каком заходе, потому что предыдущий уже проверен и зелёный.
Есть и психологический эффект. Большой рефакторинг тянется долго, и легко потерять ощущение прогресса. Когда каждый батч заканчивается видимым результатом, ты идёшь по цепочке маленьких побед. Это держит темп.
Отдельный большой батч — переезд инфраструктуры
Батчи работают и для крупных заходов. В том же REOS был перенос на клиентский VPS. Задача разбивалась на свои части: сделать аналитику провайдер-агностиком, собрать setup.sh, написать DEPLOY.md, подготовить дамп данных.
Это один логический батч — «переезд», но внутри он тоже дробится. Провайдер-агностик отдельно, скрипт установки отдельно. Каждый кусок проверяется, прежде чем строить следующий поверх него. Переезд — как раз тот случай, где соблазн сделать всё за один вечер максимальный, а цена ошибки самая высокая: продакшн переезжает целиком.
Что я вынес
Большой рефакторинг перестаёт быть страшным, когда перестаёт быть большим. Ты режешь его на заходы, фиксируешь решения до старта, и каждый заход закрываешь живой проверкой.
Короткий чеклист, который я держу в голове:
- Сначала реши развилки, потом трогай код.
- Один батч — одна связная правка, ничего лишнего внутри.
- Половину хороших решений просто выкидываешь. Писать их не нужно.
- Заканчивай заход проверкой на живом. «Вроде должно работать» не считается.
- Проверил — берёшь следующий. Не проверил — не берёшь.
Это не про скорость. Это про то, чтобы в любой момент проект был рабочим, а ты понимал, где стоишь. По моему опыту так выходит и быстрее — просто потому, что не приходится разгребать хаос, который сам же и устроил.