Чтобы рефакторить legacy-систему и не остановить бизнес, нужны три условия. Поведение системы зафиксировано тестами или сверками, чтобы каждая правка показывала, что она задела. Изменения идут малыми выпусками, и любой можно откатить за минуты. Старое и новое живут рядом, пока новое не доказало, что ведёт себя так же. Без любого из трёх условий «не останавливая» превращается в «авось».
Ниже порядок работы и правила, а не обзор модных приёмов. О том, как выбирать между рефакторингом, выносом части и заменой, написано на странице «Рефакторинг legacy-систем», здесь только то, как не сломать работающее.
Почему «остановить и переписать» чаще не работает
Идея написать систему заново звучит чисто: убрать накопленный хлам, взять современные инструменты. На практике у неё три слабых места, и все связаны с остановкой бизнеса, которую вы хотите избежать.
- Старая система продолжает меняться. Пока пишется новая, бизнес просит правки в старой. Новая система догоняет движущуюся цель и каждый месяц отстаёт.
- Правила спрятаны в коде. Скидка для конкретного клиента, округление, особый порядок проведения: это не записано нигде, кроме старого кода. Новая система воспроизводит только то, что вспомнили.
- Переключение происходит один раз. Все ошибки накапливаются до дня, когда нужно перейти. В этот день цена ошибки максимальна.
Это не значит, что переписывание запрещено. Для небольшой системы с описанным поведением, где остановка допустима, оно может быть дешевле. Для остальных рабочий путь — менять частями, и дальше о нём.
Первые недели: что делаем до первой правки
Типичная ошибка — начать с кода, который «выглядит хуже всего». Лучше потратить первые недели на то, что сделает остальные безопасными. Условный порядок для системы средней величины такой.
| Когда | Что делаем | Что получаем | Как проверяем |
|---|---|---|---|
| Неделя 1 | Запускаем систему на стенде по имеющимся инструкциям, записываем всё, что пришлось выяснять устно | Рабочий стенд и список «знаний в головах» | Другой человек поднимает стенд по инструкции без помощи автора |
| Неделя 1–2 | Собираем реальные входы: запросы, файлы, документы, и сохраняем результаты работы системы | Набор снимков поведения | Повторный запуск даёт тот же результат |
| Неделя 2 | Строим карту горячих точек: что чаще меняется, что чаще ломается, где остановка дороже всего | Список мест по порядку очереди | Бизнес согласен с оценкой цены простоя |
| Неделя 2–3 | Пишем тесты на критичные сценарии: расчёт, проведение, выгрузка в учёт | Автоматическая проверка при каждой сборке | Намеренно сломанный расчёт вызывает красный тест |
| Неделя 3–4 | Настраиваем сборку, выпуск и откат одной кнопкой | Повторяемый выпуск | Откат проверен на стенде, а не описан словами |
Последняя строка неочевидна, но важнее остальных. Если выпуск делается руками по памяти, каждый рефакторинг становится рискованным независимо от качества правки. Возможность быстро вернуть прежнее состояние — главное, что позволяет не бояться изменений. Заключение о состоянии кода и риске, если оно нужно до начала, делается отдельно: аудит кода и архитектуры.
Правила выпусков: как менять и не сломать
Дальше работа идёт по правилам, которые легко записать и трудно нарушать в спешке. Их полезно подписать и вам, и исполнителю.
- Один выпуск — одна причина. Рефакторинг не смешивают с новой функцией. Если после выпуска что-то сломалось, ищется одна причина, а не пять.
- Рефакторинг не меняет поведение. Если изменение поведения нужно, оно оформляется отдельной задачей и отдельным выпуском. Тесты для этого и нужны: они краснеют, когда поведение поменялось случайно.
- Переключатель вместо веры. Новая логика включается флагом: сначала у одного сотрудника, затем у отдела, затем у всех. Откат — выключение флага, без нового выпуска.
- Параллельный прогон для рискованных мест. Расчёты и проведение документов сначала выполняются обоими способами: ответ даёт старый код, различия пишутся в журнал. Когда журнал неделями пуст, ответ передаётся новому.
- Запретные окна. Закрытие периода, сезонный пик, инвентаризация: в эти дни выпусков нет. Календарь согласуется с бизнесом заранее.
- Откат проверяется до выпуска. Для каждого этапа записано, кто решает об откате, что нажимать и за какое время всё возвращается.
Частые маленькие выпуски кажутся более рискованными, чем один большой. Это иллюзия: маленький выпуск понятен, его причину в случае проблемы находят за час, а большой превращается в расследование.
Как менять базу данных без простоя
Самое опасное в рефакторинге — схема данных, потому что на неё опираются все: старый код, новый код, отчёты, выгрузки, чужие системы. Переименовать поле за ночь нельзя. Работает порядок «добавить, перенести, убрать».
| Шаг | Что происходит | Можно ли откатить | Что проверить перед следующим |
|---|---|---|---|
| 1. Добавить | Новое поле или таблица создаётся рядом со старым. Код продолжает работать по-старому | Да, достаточно убрать добавленное | Старая версия кода не ломается от нового поля |
| 2. Писать в оба места | Новый код пишет и в старое, и в новое. Чтение пока старое | Да, переключением флага | Значения в двух местах совпадают на выборке и на итогах |
| 3. Перенести старые данные | Фоновая задача переносит накопленное порциями, не блокируя пользователей | Да, перенесённое можно перезаписать | Число строк и суммы совпали, нагрузка на базу в норме |
| 4. Переключить чтение | Чтение идёт из нового места, запись по-прежнему в оба | Да, обратным переключением | Отчёты и выгрузки показывают то же, что раньше |
| 5. Убрать старое | Запись в старое отключается, затем отдельным выпуском удаляется само поле | Только из копии, поэтому делается последним | Месяц нет обращений к старому полю по журналу |
Здесь лучше не торопиться: между шагами 4 и 5 стоит выждать полный цикл бизнеса, например месяц с закрытием периода. Если вместе со схемой меняется сама система управления базой, например с MSSQL на PostgreSQL, это отдельная работа, описанная в статье «MSSQL на PostgreSQL: что меняется».
Как говорить с бизнесом: что можно обещать, а что нет
Рефакторинг трудно продавать внутри компании: пользователь не видит результата, а деньги и время уходят. Чтобы не потерять поддержку, разговор строится не вокруг качества кода, а вокруг последствий для бизнеса.
| Вопрос бизнеса | Честный ответ | Чего не обещаем |
|---|---|---|
| Когда это закончится? | Работа идёт этапами с отдельной приёмкой, и после каждого этапа система стала проще в изменении. Общий срок называем вилкой после обследования | Дату окончательного завершения до того, как сделан первый модуль |
| Что я увижу? | Скорость выполнения типовой правки, число ошибок после выпусков, время подготовки выпуска. Договариваемся о них до начала | Новых экранов и функций: рефакторинг их не добавляет |
| А если что-то сломается? | Откат за минуты, журнал различий, запретные периоды. Для критичных разделов параллельный прогон | Что ничего никогда не сломается |
| Можно ли параллельно добавлять функции? | Да, но через один и тот же процесс выпусков. Крупные новые функции в рефакторимый модуль лучше не добавлять | Что обе работы пройдут без взаимных задержек |
| Почему не переписать? | Потому что правила хранятся в старом коде, и переключение происходит один раз | Что переписывание никогда не бывает оправданным |
Метрики стоит выбрать простые и измерять с первой недели, чтобы было с чем сравнивать. Например, сколько дней проходит от запроса на правку до выпуска и сколько выпусков потребовали отката. Если метрики не улучшаются после первых модулей, это сигнал пересмотреть план, а не продолжать из упрямства.
Две системы одновременно: как не застрять навсегда
Любой вариант с постепенным переходом содержит период, когда живут старое и новое. Это дороже, чем любая из систем по отдельности, и именно здесь рефакторинги зависают на годы. Чтобы этого не случилось, нужны правила.
- У старого есть дата отключения. Не календарная, а условная: «когда в журнале нет обращений к функции X за полный цикл периода». Условие записывается в начале этапа.
- У каждого раздела один хозяин данных. Пока идёт перенос, записывается, какая из двух систем главная для каждого поля. Две главные системы — это расхождения.
- Сверка по расписанию. Раз в сутки две системы сравниваются по числу записей и суммам, а расхождения попадают в журнал и разбираются.
- Перенос по разделам, а не по слоям. Лучше полностью перенести один раздел (например, склад), чем наполовину переписать всю систему.
- Нет возврата к старому коду. Когда раздел принят, правки в старом его варианте запрещаются. Иначе приходится поддерживать два варианта.
Какие стратегии замены существуют и в чём риск каждой, разобрано на странице про микросервисы и высоконагруженные системы; здесь важно только, что у любого перехода должен быть конец.
Когда пора остановиться и пересмотреть план
Не всякий рефакторинг стоит довести до конца. Остановка после первого этапа не провал, а результат проверки. Пересматривать план стоит, если проявился один из признаков.
| Признак | Что это значит | Что делаем |
|---|---|---|
| Проверить поведение нечем, и стенд не получается собрать | Рефакторинг превратится в угадывание | Сначала создаём среду проверки; если не получается, меняем только то, что можно проверить вручную |
| Первый модуль занял в несколько раз больше времени, чем планировали | Связанность выше, чем казалось, или правила не записаны | Пересчитываем вилку, возможно, меняем стратегию на вынос части |
| Скорость правок после первых этапов не выросла | Разбирали не то место или узкое место в процессе, а не в коде | Смотрим на сборку, согласования и тестирование, а не на код |
| Единственный знающий человек ушёл | Правила придётся восстанавливать по коду и данным | Откладываем рискованные разделы, расширяем тесты на текущее поведение |
| Система вот-вот будет заменена по другой причине | Рефакторинг её не окупится | Ограничиваемся исправлением безопасности и поддержкой |
Решение об остановке принимается по ступеням: сделанное остаётся у вас по акту, и после любого этапа можно продолжить с нами, с другим подрядчиком или своей командой.
Что делаем мы и с чего начать
Начинаем с обследования: 200 000 ₽ и 2–3 недели за одну систему, 350 000 ₽ и 3–4 недели, если вокруг неё несколько систем и обменов. На выходе рабочий запуск, карта горячих точек, оценка того, чем можно проверить поведение, выбор между рефакторингом, выносом части и заменой и вилка бюджета. Стоимость вычитается из первого этапа, если продолжаете с нами, а документом можно пользоваться и без нас.
Дальше лёгкий пилот на одном модуле (150 000–400 000 ₽, 2–8 недель): тесты, правка, сверка, выпуск с откатом. Затем несколько модулей и платформа (400 000–1 200 000 ₽, 2–3 месяца) и вывод в эксплуатацию этапами (от 1 500 000 ₽). На любой ступени можно остановиться. Мы работаем в вашем репозитории, не заменяем системы управления технологическим процессом, не ставим на предприятие готовые учётные системы целиком и не дежурим круглосуточно. Цены и сроки — на странице «Тарифы», описание услуги — на странице «Рефакторинг legacy-систем».
Частые вопросы
Можно ли рефакторить систему, не останавливая работу?
Да, при трёх условиях: поведение зафиксировано тестами и сверками, изменения идут малыми выпусками с откатом, а старое и новое живут рядом, пока новое не доказало, что ведёт себя так же.
С чего начинать рефакторинг legacy?
Не с кода, а со страховки: рабочий стенд, снимки поведения на реальных входах, тесты на критичные сценарии, повторяемый выпуск и откат. Затем выбирается первое место по частоте изменений, поломок и цене простоя.
Что лучше: переписать с нуля или рефакторить?
Для небольшой системы с описанным поведением, где остановка допустима, переписывание может быть дешевле. Для большинства работающих систем надёжнее идти частями: так не теряются неписаные правила и нет одного опасного переключения.
Как менять структуру базы без простоя?
Добавляете новое рядом со старым, пишете в оба места, переносите накопленное порциями, переключаете чтение и только потом убираете старое отдельным выпуском. На каждом шаге есть откат, кроме последнего.
Что такое переключатель функции и зачем он нужен?
Флаг, который включает новую логику для части пользователей. Откат — выключение флага за минуты, без нового выпуска. Так изменённая логика сначала работает у одного сотрудника, потом у отдела, потом у всех.
Как понять, что рефакторинг идёт правильно?
По простым метрикам, выбранным до начала: сколько дней проходит от запроса на правку до выпуска и сколько выпусков пришлось откатывать. Если после первых модулей они не улучшаются, план пересматривается.
Сколько это стоит?
Обследование — 200 000 ₽ (350 000 ₽ для системы с окружением), лёгкий пилот — 150 000–400 000 ₽, тяжёлый пилот — 400 000–1 200 000 ₽, вывод в эксплуатацию — от 1 500 000 ₽ этапами по 300 000–700 000 ₽. Обследование вычитается из первого этапа, если продолжаете с нами.
Кто остаётся владельцем кода и тестов?
Вы. Исходный код и тесты лежат в вашем репозитории с первого коммита, результат передаётся по акту, а порядок передачи прав записан в договоре. Остановиться можно после любой ступени.