Рефакторинг легаси без слёз: пошаговый сценарий с Vibe Codex
Старый код не «плохой» — он просто помнит больше, чем вы. Задача рефакторинга — не переписать, а перенести знания на бумагу.
«Перепиши этот класс» — худший промпт для большой модели. Хороший рефакторинг легаси состоит из шагов, каждый из которых проверяемый: понять, зафиксировать поведение тестами, заменить один кусок, пройти по тестам, закоммитить, повторить. Vibe Codex здесь не «волшебник», а очень дисциплинированный напарник.
Шаг 1. Explain: распаковать намерение
Сначала — разобраться, что код делает. Не предполагать, не «и так понятно», а спросить вслух.
$ vibe-codex explain src/legacy/OrderProcessor.java
[opus] OrderProcessor — это диспетчер из 2011 года.
[opus] три ответственности смешаны: валидация payload,
расчёт total с учётом купонов, и побочные эффекты
(отправка письма + запись в audit-log).
[opus] критические инварианты:
1) total >= 0
2) audit-log пишется ДО отправки письма
3) coupon применяется ОДИН РАЗ, даже при ретраях
Опасные инварианты вынесли наружу. Теперь рефакторинг не «улучшение», а сохранение этих трёх свойств.
Шаг 2. Characterization tests
Прежде чем что-то двигать, фиксируем поведение. Vibe Codex умеет генерировать тесты, которые описывают «как оно сейчас», а не «как должно бы». Это золото для легаси.
$ vibe-codex test --characterize src/legacy/OrderProcessor.java
[gpt-5.2-codex] 14 cases generated:
- happy path: order with 1 item, no coupon
- coupon DOUBLE_DELIVERY applied twice (currently allowed, bug?)
- audit-log fails: e-mail is still sent (currently true, suspicious)
- retry path: total recalculated (currently true)
...
[result] 14 passing on HEAD, 2 marked @Suspicious
Тесты с тегом @Suspicious — это не «исправь», а «зафиксируй, что это есть». После рефакторинга мы посмотрим, оставлять их или править.
Шаг 3. Точечная замена
Одно изменение за раз. Вынести расчёт total в отдельный класс — это одна правка, одна сессия, один коммит.
$ vibe-codex "вынеси расчёт total в OrderTotalCalculator, \
сохрани сигнатуру OrderProcessor.process"
[plan] 3 files:
+ src/order/OrderTotalCalculator.java
~ src/legacy/OrderProcessor.java (delegate to calculator)
+ src/order/OrderTotalCalculatorTest.java
[diff] 142 +/- 56
[tests] running...
[tests] 14/14 passing, 0 regressions
Шаг 4. Прогон полной регрессии
Сгенерированные тесты — не вся правда. Прогоняем настоящий тест-сьют:
$ ./gradlew test
BUILD SUCCESSFUL in 47s
1284 actionable tasks: 1284 executed
Если что-то падает — это не «модель сломала», а «модель показала, что инвариант не был зафиксирован». Возвращаемся на шаг 2, добавляем тест, повторяем.
Шаг 5. Коммит
Vibe Codex сам пишет коммит-сообщение. Не «refactor stuff», а конкретно: что вынесли, что осталось, что не меняли.
refactor(order): extract OrderTotalCalculator from OrderProcessor
- OrderProcessor.process() теперь делегирует расчёт суммы
в OrderTotalCalculator
- инварианты сохранены: total >= 0, coupon применяется один раз
- характерные тесты пройдены без изменений
Что не делать
«Самая дорогая ошибка в рефакторинге — попросить модель „переписать всё хорошо“. Это не задача, это пожелание».
- Не давать модели весь модуль на «переписать». Дробите.
- Не пропускать characterization-тесты. Они стоят дёшево, а ловят дорого.
- Не коммитить рефакторинг и фикс бага в одном коммите. Это разные сущности.
- Не выключать линтеры на время «временного состояния». Временное живёт долго.
Когда останавливаться
Признак, что пора закрыть терминал: тесты зелёные, diff читается за минуту, инварианты сохранены, и вы понимаете, что произошло. Если вы перестали понимать — откатывайте, дробите шаг ещё мельче.
Vibe Codex не делает рефакторинг за вас. Он делает то, что делать скучно: читает, объясняет, генерирует тесты, переносит блоки. Решение о том, что переносить, остаётся у человека. И это правильно — модель не помнит, почему в 2014 ввели тот странный купон с двойной доставкой. А вы — возможно, помните.
Готов попробовать?
brew tap xrouter-chat/tap && brew install vibe-codex — и за 30 секунд ты в деле.
Поставить Vibe Codex →