Рефакторинг legacy-системы: как менять работающую систему и не сломать её

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

Обследование — от 200 000 ₽, 2–3 неделиСначала тесты на текущее поведение, потом правкиИсходный код в вашем репозитории с первого коммита

С чем приходят

Когда систему пора приводить в порядок

Каждая правка занимает неделю

Простое изменение требует трогать десять мест, а проверить результат можно только вручную. Команда боится релизов и копит правки в большие выпуски.

Знает один человек

Логика живёт в голове автора или в коде без описания. Уход разработчика остановит развитие, и это понимают все.

Платформа устарела

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

Хотят переписать с нуля

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

Что есть что

Рефакторинг, модернизация платформы и замена: чем различаются

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

Что делаем
Суть
Что меняется
Что остаётся прежним
Что делаемРефакторингпорядок внутри
СутьУлучшаем устройство кода без изменения поведения
Что меняетсяСтруктура, имена, дублирование, связи между модулями; добавляются тесты
Что остаётся прежнимВсё, что видит пользователь, и данные
Что делаемМодернизация платформыновая основа
СутьПереводим систему на поддерживаемые язык, библиотеки или систему управления базой
Что меняетсяВерсия языка, зависимости, способ сборки и запуска; иногда база данных
Что остаётся прежнимБизнес-правила и интерфейс
Что делаемВынос частиграница наружу
СутьВыделяем модуль или сервис, который развивается отдельно
Что меняетсяСпособ вызова: вместо вызова функции запрос; данные делятся
Что остаётся прежнимОстальная система и её поведение
Что делаемЗаменановая система
СутьПишем новую систему и переносим данные по частям
Что меняетсяПочти всё, включая данные и обмены
Что остаётся прежнимТолько то, что явно записано как требование
Страховка

Сначала тесты на текущее поведение: как менять код, который никто не понимает

Рефакторинг без проверки — это угадывание. У унаследованного кода тестов обычно нет, и первая работа — создать то, что позволит увидеть поломку.

Тесты на унаследованный код пишут не по требованиям (требований нет), а по фактическому поведению: что система делает сейчас, правильно или нет. Правильность выясняется отдельно. Сначала нужно зафиксировать поведение, иначе после правки нельзя сказать, что изменилось.

Чем фиксируем поведение

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

Швы: где можно резать без риска

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

Что не берёмся делать без страховки

Если проверить поведение нечем (нет данных, нет тестового стенда, расчёт зависит от рукописных исправлений в базе), мы не начинаем правки кода. Сначала создаём среду для проверки. Иногда это составляет половину работы, и обследование показывает это заранее.

Порядок

С чего начинать: как выбираем места для рефакторинга

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

Признак
Что говорит
Как смотрим
Что делаем
ПризнакЧастота измененийистория репозитория
Что говоритМодуль меняют каждую неделю, и каждая правка медленная и рискованная
Как смотримФайлы с самым большим числом правок в истории хранилища
Что делаемНачинаем отсюда: окупается быстрее всего
ПризнакЧастота поломокобращения и журнал
Что говоритИз этого раздела приходит большинство ошибок
Как смотримСопоставление исправлений ошибок с файлами и модулями
Что делаемТесты и разделение ответственности
ПризнакЦена простоявопрос бизнесу
Что говоритОстановка раздела стоит денег сразу
Как смотримСписок разделов с оценкой «что произойдёт за час, день, неделю»
Что делаемНе трогаем без параллельного прогона и плана отката
ПризнакНоситель знанияопрос людей
Что говоритЛогику знает один человек, и он может уйти
Как смотримСписок разделов, где автор единственный
Что делаемЗаписываем поведение в тестах и описании, пока он доступен
Данные и платформа

База данных и устаревшая платформа: две части, где ломается чаще всего

Меняем схему базы без остановки: «расширить и сжать»

Схему базы нельзя переименовать за ночь, если с ней работает старый и новый код одновременно. Безопасный порядок из трёх шагов. Сначала добавляем новое поле или таблицу рядом со старыми, код пишет в оба места. Затем переносим старые данные и переключаем чтение на новое. Когда на старое никто не смотрит, оно удаляется отдельным выпуском. Каждый шаг можно откатить, а систему не нужно останавливать. Если вместе с этим меняется сама система управления базой, например при переходе на PostgreSQL, смотрите миграцию на PostgreSQL.

Обновляем платформу ступенями

Прыжок через несколько версий языка или библиотеки ломает всё сразу, и причину потом не найти. Обновляем по одной ступени: поднимаем версию, прогоняем тесты, чиним то, что сломалось, выпускаем. Устаревшие зависимости, у которых нет замены, изолируем за тонким слоем, чтобы заменить их позже без правки остальной системы. Если вместе с обновлением нужен переход на отечественную операционную систему, см. портирование под Astra Linux.

Что делаем с мёртвым кодом

В старой системе много кода, который никто не вызывает. Мы не удаляем его на глаз: сначала в журнал пишется, какие функции действительно вызываются за месяц-два, затем неиспользуемое помечается и убирается отдельным выпуском. Так система уменьшается, а риск удалить нужное остаётся малым.

Релизы

Как рефакторим, не останавливая бизнес

Малые шаги и частые выпуски

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

Переключатели функций

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

Плановые окна и запреты

Договариваемся, когда нельзя трогать: закрытие периода, сезонные пики, инвентаризация. В эти дни выпусков нет.

План отката на каждый шаг

Перед началом записано, как вернуть прежнее состояние, кто решает и за какое время. Откат проверяется заранее, а не в день проблемы.

Что делаем

Из чего состоит работа и сколько она стоит

Цены — по тарифам. Точная цена называется у обследования, дальше вилка, которая сужается по его результатам. Остановиться можно после любой ступени.

Обследование: одна система

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

200 000 ₽ · 2–3 недели

Обследование: система и окружение

То же вместе с обменами, соседними системами и базой данных; карта связей и порядок изменений.

350 000 ₽ · 3–4 недели

Лёгкий пилот: один модуль

Тесты на текущее поведение, правка одного модуля или одного слоя, сверка результата, выпуск с откатом.

150 000–400 000 ₽ · 2–8 недель

Тяжёлый пилот: несколько модулей и платформа

Рефакторинг связанных модулей, обновление платформы ступенями, изменение схемы базы, параллельный прогон на боевых данных.

400 000–1 200 000 ₽ · 2–3 месяца

Вывод в эксплуатацию

Этапы по разделам системы, опытная эксплуатация каждого, регламент выпусков и отката, передача документации.

от 1 500 000 ₽ этапами по 300 000–700 000 ₽ · от 3 месяцев

Сопровождение

Мониторинг, разбор инцидентов, плановые доработки с пакета на 60 000 ₽. Сверх пакета — 5 000 ₽ в час.

20 000 / 60 000 / 120 000 ₽ в месяц
Процесс

Как идёт работа

2–4 недели — Обследование

Запускаем систему по вашим инструкциям, фиксируем, что пришлось выяснять устно. Строим карту горячих точек и оцениваем, чем можно проверить поведение. Если нужно заключение по состоянию кода, это отдельный <a href="../audit-koda-i-arhitektury/">аудит кода и архитектуры</a>.

Перед работой — Страховка

Снимки на реальных входах, тесты на критичные сценарии, сверка данных, стенд. Договариваемся об окнах, когда выпуски запрещены.

От 2 недель — Первый модуль

Выбранное место проходит весь путь: тесты, правка, сверка, выпуск и откат. По результату уточняем вилку остальных этапов.

Этапами — Следующие разделы

Каждый раздел с отдельной приёмкой и своим планом отката. Работаем в вашем репозитории и показываем результат на тестовом стенде.

Параллельно — Платформа и база

Обновление версий ступенями и изменение схемы по принципу «расширить и сжать», когда это входит в объём.

Дальше — передача или сопровождение

Описание системы, тесты и регламент выпусков остаются у вас. Сопровождение берём по договору с часами.

Цена

Что двигает цену внутри вилки

Возможность проверить поведение

Есть тестовые данные и стенд, и страховка собирается быстро. Нет их, и первые недели уходят на создание среды проверки.

Связанность и размер

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

Состояние данных

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

Доступность знающих людей

Если автор на связи и отвечает на вопросы, правила выясняются быстро. Если его нет, правила восстанавливаются по коду и данным.

Контроль

Что остаётся у вас и чего мы не делаем

Остаётся у вас

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

Мы этого не делаем

  • Не обещаем переписать систему целиком за один этап: заменяем и меняем частями.
  • Не заменяем системы управления технологическим процессом и SCADA.
  • Не берём внедрение готовой системы на предприятие целиком: ERP и MES ставятся другими проектами.
  • Не проводим аттестацию, лицензии ФСТЭК у нас нет; не дежурим круглосуточно.
  • Не берём работы дешевле 150 000 ₽ и не рефакторим ради красоты, если система работает и не мешает.
Граница

Рефакторинг, аудит, микросервисы или сопровождение: какая услуга нужна

Если нужно сначала узнать, можно ли развивать систему и что с ней не так, начинают с аудита кода и архитектуры: он даёт заключение, а не правки. Если система тормозит и вопрос в границах сервисов, очередях и стратегии замены (душитель, вынос границ, переписывание), смотрите микросервисы и высоконагруженные системы. Рефакторинг в нашем понимании занимается внутренним порядком: тесты, связи, схема, платформа.

Если нужно сменить базу данных или операционную систему, это миграция на PostgreSQL или портирование под Astra Linux. Если система стабильна и нужен только присмотр, подойдёт сопровождение ПО. Разбор типовой задачи, когда система осталась без подрядчика, — в разделе «Разборы».

Инструменты

На чём работаем

Страховка и сборка
  • Тесты в языке вашей системы и снимки результатов
  • Сравнение выгрузок и сверка таблиц на копии базы
  • Статический анализ кода и проверка зависимостей
  • GitLab CI, сборка при каждой правке
Изменения и наблюдение
  • Переключатели функций
  • Миграции схемы базы с откатом
  • Журнал вызовов для поиска неиспользуемого кода
  • Docker и тестовый стенд, повторяющий боевую среду
Материалы

Материалы по теме

Статья

Как рефакторить legacy, не останавливая бизнес

Порядок работы, правила выпусков и откат, коммуникация с бизнесом и признаки, что пора остановиться.

  • Ритм выпусков
  • Откат
  • Остановка
Читать →
Статья

Стоимость владения ИТ-системой

Как посчитать, сколько стоит держать старую систему и когда рефакторинг выгоднее заплаток.

  • Что считать
  • Скрытые расходы
  • Сравнение
Читать →
Статья

Микросервисы или монолит: как выбрать

Как понять, что после наведения порядка нужен вынос части, а не новая архитектура целиком.

  • Критерии
  • Цена сети
  • Границы
Читать →
Заявка

Разберём, с чего начинать вашу систему

Сорок минут созвона: что за система, что в ней болит, чем можно проверить её поведение и кто её знает. Скажем, хватит ли рефакторинга и с какой ступени начинать.

Спасибо, заявка отправлена. Ответим в течение рабочего дня.

Не удалось отправить. Напишите в телеграм или позвоните.

Вопросы

Частые вопросы: рефакторинг legacy-систем

Что такое рефакторинг legacy-системы?

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

Чем рефакторинг отличается от модернизации?

Рефакторинг наводит порядок внутри, модернизация переводит систему на поддерживаемую основу: новая версия языка, библиотеки, иногда другая база. Часто они идут вместе, но решаются отдельно и проверяются отдельно.

Сколько стоит рефакторинг сложной системы?

Обследование — 200 000 ₽ за 2–3 недели (350 000 ₽ для системы с окружением), лёгкий пилот одного модуля — 150 000–400 000 ₽, тяжёлый пилот — 400 000–1 200 000 ₽, вывод в эксплуатацию — от 1 500 000 ₽ этапами. Обследование вычитается из первого этапа, если продолжаете с нами.

Можно ли рефакторить, если нет тестов?

Нужно, но сначала тесты создаются. Мы фиксируем текущее поведение на реальных входах, пишем тесты на критичные сценарии и сверяем данные. Если проверить поведение нечем, начинаем со среды для проверки, а не с правки кода.

Что лучше: чинить, выносить часть или переписывать?

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

Придётся ли останавливать работу системы?

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

Кому принадлежит код?

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

Берётесь ли за систему, которую писали не вы?

Да, если есть исходники или их можно восстановить, и систему можно запустить. Начинаем с обследования: оно показывает состояние и риск. Если исходников нет совсем, скажем об этом до договора. Сопровождение после работ — 20 000, 60 000 или 120 000 ₽ в месяц.

Вы работаете только в Ростове-на-Дону?

Мы в Ростове-на-Дону, работаем с заказчиками по всей России: удалённо и в вашем контуре. Доступ к системам и обследование согласуем на старте с вашей службой безопасности.