Чтобы рефакторить legacy-систему и не остановить бизнес, нужны три условия. Поведение системы зафиксировано тестами или сверками, чтобы каждая правка показывала, что она задела. Изменения идут малыми выпусками, и любой можно откатить за минуты. Старое и новое живут рядом, пока новое не доказало, что ведёт себя так же. Без любого из трёх условий «не останавливая» превращается в «авось».

Ниже порядок работы и правила, а не обзор модных приёмов. О том, как выбирать между рефакторингом, выносом части и заменой, написано на странице «Рефакторинг legacy-систем», здесь только то, как не сломать работающее.

Коротко. Сначала страховка, потом правки. Один шаг, один выпуск, один откат. Данные меняем в три этапа: добавить, перенести, убрать. Бизнесу обещаем порядок и скорость изменений, а не сроки «переписывания». Если после первого модуля не стало проще менять, останавливаемся и пересматриваем план.

Почему «остановить и переписать» чаще не работает

Идея написать систему заново звучит чисто: убрать накопленный хлам, взять современные инструменты. На практике у неё три слабых места, и все связаны с остановкой бизнеса, которую вы хотите избежать.

  • Старая система продолжает меняться. Пока пишется новая, бизнес просит правки в старой. Новая система догоняет движущуюся цель и каждый месяц отстаёт.
  • Правила спрятаны в коде. Скидка для конкретного клиента, округление, особый порядок проведения: это не записано нигде, кроме старого кода. Новая система воспроизводит только то, что вспомнили.
  • Переключение происходит один раз. Все ошибки накапливаются до дня, когда нужно перейти. В этот день цена ошибки максимальна.

Это не значит, что переписывание запрещено. Для небольшой системы с описанным поведением, где остановка допустима, оно может быть дешевле. Для остальных рабочий путь — менять частями, и дальше о нём.

Первые недели: что делаем до первой правки

Типичная ошибка — начать с кода, который «выглядит хуже всего». Лучше потратить первые недели на то, что сделает остальные безопасными. Условный порядок для системы средней величины такой.

КогдаЧто делаемЧто получаемКак проверяем
Неделя 1Запускаем систему на стенде по имеющимся инструкциям, записываем всё, что пришлось выяснять устноРабочий стенд и список «знаний в головах»Другой человек поднимает стенд по инструкции без помощи автора
Неделя 1–2Собираем реальные входы: запросы, файлы, документы, и сохраняем результаты работы системыНабор снимков поведенияПовторный запуск даёт тот же результат
Неделя 2Строим карту горячих точек: что чаще меняется, что чаще ломается, где остановка дороже всегоСписок мест по порядку очередиБизнес согласен с оценкой цены простоя
Неделя 2–3Пишем тесты на критичные сценарии: расчёт, проведение, выгрузка в учётАвтоматическая проверка при каждой сборкеНамеренно сломанный расчёт вызывает красный тест
Неделя 3–4Настраиваем сборку, выпуск и откат одной кнопкойПовторяемый выпускОткат проверен на стенде, а не описан словами

Последняя строка неочевидна, но важнее остальных. Если выпуск делается руками по памяти, каждый рефакторинг становится рискованным независимо от качества правки. Возможность быстро вернуть прежнее состояние — главное, что позволяет не бояться изменений. Заключение о состоянии кода и риске, если оно нужно до начала, делается отдельно: аудит кода и архитектуры.

Правила выпусков: как менять и не сломать

Дальше работа идёт по правилам, которые легко записать и трудно нарушать в спешке. Их полезно подписать и вам, и исполнителю.

  1. Один выпуск — одна причина. Рефакторинг не смешивают с новой функцией. Если после выпуска что-то сломалось, ищется одна причина, а не пять.
  2. Рефакторинг не меняет поведение. Если изменение поведения нужно, оно оформляется отдельной задачей и отдельным выпуском. Тесты для этого и нужны: они краснеют, когда поведение поменялось случайно.
  3. Переключатель вместо веры. Новая логика включается флагом: сначала у одного сотрудника, затем у отдела, затем у всех. Откат — выключение флага, без нового выпуска.
  4. Параллельный прогон для рискованных мест. Расчёты и проведение документов сначала выполняются обоими способами: ответ даёт старый код, различия пишутся в журнал. Когда журнал неделями пуст, ответ передаётся новому.
  5. Запретные окна. Закрытие периода, сезонный пик, инвентаризация: в эти дни выпусков нет. Календарь согласуется с бизнесом заранее.
  6. Откат проверяется до выпуска. Для каждого этапа записано, кто решает об откате, что нажимать и за какое время всё возвращается.

Частые маленькие выпуски кажутся более рискованными, чем один большой. Это иллюзия: маленький выпуск понятен, его причину в случае проблемы находят за час, а большой превращается в расследование.

Как менять базу данных без простоя

Самое опасное в рефакторинге — схема данных, потому что на неё опираются все: старый код, новый код, отчёты, выгрузки, чужие системы. Переименовать поле за ночь нельзя. Работает порядок «добавить, перенести, убрать».

ШагЧто происходитМожно ли откатитьЧто проверить перед следующим
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 ₽. Обследование вычитается из первого этапа, если продолжаете с нами.

Кто остаётся владельцем кода и тестов?

Вы. Исходный код и тесты лежат в вашем репозитории с первого коммита, результат передаётся по акту, а порядок передачи прав записан в договоре. Остановиться можно после любой ступени.