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

Переписывать унаследованную систему стоит, когда стоимость и риск ее изменения превышают стоимость и риск замены. Возраст, язык и архитектурные предпочтения на этот вопрос не отвечают. Ответ дают четыре показателя: доля неудачных изменений, доля команды, способная безопасно менять код, доля неподдерживаемой среды выполнения и стоимость одного серьезного инцидента.
Я видел, как команды одобряли переписывание из-за устаревшего на вид фреймворка, а затем выясняли, что старое приложение менялось дважды в год и не создавало проблем. Видел и защиту «постепенного улучшения», когда единственный оставшийся специалист держал рабочую систему на неподдерживаемой среде. Оба решения опирались на интуицию под видом инженерного расчета. Сведите четыре числа на одну страницу, и подогнать спор под желаемый вывод станет намного сложнее.
Для решения нужны измерения, а не предельный возраст
Нет возраста, после которого программу автоматически нужно переписывать. Пятнадцатилетний сервис со стабильными интерфейсами, поддерживаемыми зависимостями, хорошими тестами и несколькими уверенными специалистами может обходиться дешевле трехлетнего сервиса, который ломается при каждом выпуске. Календарный возраст подсказывает, куда смотреть, но ничего не решает.
То же относится к языку. COBOL, RPG, VB6, Delphi или старая версия PHP могут затруднять найм и поддержку, но само название языка не измеряет проблему. Хорошо понятная пакетная задача на COBOL, которая каждую ночь обрабатывает один формат файла, может прожить еще десять лет. Маленький сервис на JavaScript, понятный только одному подрядчику, уже может быть операционным риском.
Выберите период, включающий обычные поставки и хотя бы один напряженный для бизнеса этап. Команде с частыми развертываниями обычно подходит квартал. Медленно меняющейся системе может понадобиться более долгий период, но не ждите идеальных данных бесконечно. Записывайте неопределенность рядом с каждым числом и уточняйте измерение по ходу работы.
Для всех четырех показателей используйте одну единицу анализа. Решите, оцениваете ли вы приложение, отдельно развертываемый сервис или тесно связанную группу, которую приходится менять вместе. Если считать сбои для всего портфеля, а специалистов для одного репозитория, получится аккуратная, но бессмысленная таблица.
Четыре числа отвечают на разные вопросы:
- Может ли команда менять систему, не ломая рабочую среду?
- Сколько людей могут сделать это без надзора?
- Какая доля исполняемого ПО больше не получает исправлений?
- Сколько бизнес потеряет при серьезном инциденте?
Универсального порога нет ни у одного показателя. Установите границу с учетом допустимого риска и запишите действие при ее пересечении. Одна и та же норма должна действовать до аварии, когда никто еще не пытается приспособить ее к заранее выбранному выводу.
Доля неудачных изменений показывает цену каждого выпуска
Доля неудачных изменений показывает, какая часть производственных изменений потребовала исправления из-за ухудшения сервиса, остановки, отката или срочного патча. DORA использует это понятие как показатель качества поставки ПО. Я бы сохранял узкое определение: считайте сбои, вызванные изменением, а не все инциденты рядом с развертыванием.
До расчета определите, что считается производственным изменением. Включите развертывания приложений, миграции баз, выпуски конфигурации, изменения расписаний и инфраструктуры, если команда управляет ими как единым процессом. Обычный повторный запуск не считайте отдельным сбоем. Десять срочных коммитов после плохого выпуска тоже не должны превращаться в десять независимых неудач.
Базовый расчет прост:
change_failure_rate = failed_production_changes / total_production_changes
Сложность возникает при классификации. Для каждого сбоя запишите исходное изменение, влияние на клиентов, способ восстановления и источник дефекта: код, данные, конфигурация или неизвестное взаимодействие. Метки change-failure в задаче достаточно, если все ставят ее одинаково. Спорные случаи ежемесячно разбирайте вместе с разработкой и эксплуатацией.
Не сравнивайте сырые доли систем с совершенно разной схемой поставки. Одно приложение выпускает сто мелких изменений, другое публикует один большой пакет. Показывайте долю вместе с объемом изменений и медианным временем восстановления. Десять процентов среди десяти обратимых флагов несут иной риск, чем десять процентов среди квартальных выпусков базы с шестичасовым восстановлением.
Динамика важнее отдельного значения. Если показатель снижается после улучшения тестов, наблюдаемости и уменьшения выпусков, патчи возвращают контроль. Если после двух или трех целевых попыток он остается высоким, архитектура может мешать самому способу поставки. Ищите повторяющиеся причины: общее изменяемое состояние, недокументированный порядок пакетных задач, скрытые контракты базы и этапы развертывания, которые нельзя отрепетировать. Такие свойства удорожают каждую новую функцию.
Не поощряйте команду за отказ от изменений. У системы без развертываний показатель не определен или обманчиво идеален. Отслеживайте запросы, отложенные из-за риска выпуска. Если нужные бизнесу изменения копятся из-за страха трогать рабочую среду, отсутствие сбоев доказывает паралич, а не надежность.
Безопасно владеющих кодом меньше, чем имеющих доступ
Доля безопасного владения показывает, какая часть нужной инженерной команды может самостоятельно внести значимое изменение, проверить, развернуть и восстановить его. Доступ к репозиторию не считается. Умение править файл под диктовку единственного эксперта тоже не считается.
Определите значимое изменение на основе реальных задач системы. Это может быть добавление поля через базу, сервис и интерфейс, изменение расчета с финансовыми последствиями или правка ночной задачи без нарушения повторного запуска. Задача должна пересекать границы, на которых обычно теряются знания.
Проверьте у каждого инженера четыре способности:
- Объяснить затронутый путь исполнения и его зависимости.
- Реализовать и проверить изменение без копирования непонятного образца.
- Выпустить его через настоящий производственный процесс.
- Найти причину сбоя и восстановить сервис без ожидания системного «оракула».
Учитывайте человека только при наличии свежих доказательств всех четырех пунктов. Парная работа полезна для обучения, но не доказывает самостоятельность. Проверки кода, участие в инцидентах и успешное изменение в рабочей среде надежнее самооценки.
Затем рассчитайте:
safe_touch_share = independent_safe_maintainers / relevant_engineers
Запишите и абсолютное число. Доля 50% выглядит здоровой, пока не выясняется, что это один человек из двух. И наоборот, четыре способных специалиста в команде из двадцати могут достаточно поддерживать стабильное внутреннее приложение, если дежурства и отпуска не убирают всех четверых одновременно.
Показатель выявляет различие, которое часто стирают: наличие документации не равно рабочему знанию. В руководстве на тысячу страниц могут быть экраны и таблицы, но не причина запускать расчет до сверки, не правила ручного ремонта поврежденных записей и не способ продолжить задачу без двойных проводок. Дайте новому специалисту воспользоваться документом под наблюдением. Его вопросы входят в недостающую спецификацию.
Падающая доля безопасного владения часто раньше других указывает на переписывание, потому что скрывает срок. Выход на пенсию, увольнение или уход поставщика может за день превратить сложную систему в неизменяемую. Если передача знаний повышает долю, а обученные люди продолжают вносить изменения через шесть месяцев, патчи еще можно защищать. Если вся работа снова возвращается к одному эксперту, перестаньте называть происходящее обучением.
Доля неподдерживаемой среды измеряет воздействие, а не неловкость
Это доля производственного стека, для которой ответственный поставщик или проект больше не выпускает исправления безопасности и ошибок. Сюда входит больше, чем язык приложения. Учитывайте операционные системы, базы, серверы приложений, среды выполнения, основные фреймворки, драйверы и обязательное связующее ПО.
Инвентаризируйте то, что действительно исполняется, а не нарисовано на схеме. Получайте версии с серверов, из образов контейнеров, файлов фиксации пакетов, описаний задач и запросов к базе. Для мейнфрейма или системы среднего класса добавьте компиляторы, мониторы транзакций, планировщики и компоненты поставщика на пути исполнения. Запишите источник каждой даты поддержки, чтобы слухи отдела закупок не стали политикой.
Полезен взвешенный расчет:
unsupported_runtime_share = sum(weight_of_unsupported_components) / sum(weight_of_all_components)
Задавайте вес по открытости и роли в бизнесе. Публичный сервер приложений без поддержки заслуживает большего веса, чем изолированный конвертер отчетов, запускаемый раз в месяц. Схема должна быть достаточно простой для повторения другим инженером. Если комитет час объясняет вес 7,3 для одного компонента, точность выдумана.
Отсутствие поддержки не означает взлом, а наличие поддержки не означает безопасность. Первое означает, что разработчик перестал давать обычный путь получения исправлений. Команда может компенсировать это изоляцией, виртуальными патчами, строгим контролем входа или платным продленным договором. Запишите каждый компенсирующий контроль рядом с компонентом и проверьте все точки входа.
Ищите неподдерживаемое ядро под современными краями. Новый браузер, обратный прокси и база не спасают бизнес-логику, требующую брошенной среды. Иногда команда обновляет все вокруг старого ядра и отчитывается о малом числе устаревших компонентов. Взвешивание по роли в исполнении пресекает такой учет.
Патчи разумны, когда неподдерживаемые компоненты изолированы, стабильны, заменяемы по отдельности и защищены недорогими контролями. Их труднее защищать, когда компонент принимает недоверенный ввод, блокирует обновление ОС или требует целой устаревшей цепочки развертывания. Воздействие накапливается: каждое соседнее обновление вынуждено учитывать самую старую часть.
Стоимость инцидента превращает технический риск в предел бизнеса
Стоимость серьезного инцидента включает все потери с обнаружения до восстановления и исправления, а не только счет за облако или сверхурочные инженеров. По возможности используйте настоящий инцидент. Если его не было, составьте сценарий с финансами, эксплуатацией, безопасностью и владельцем бизнеса и пометьте все допущения.
Считайте по проверяемым категориям:
incident_cost = lost_margin
+ staff_hours * loaded_hourly_cost
+ customer_remediation
+ contractual_or_regulatory_cost
+ data_reconciliation
+ delayed_business_events
Берите потерянную маржу, а не валовую сумму операций, если операции не исчезают навсегда. Отделяйте задержанный доход от потерянного. Считайте ручную работу эксплуатации, финансов, поддержки, разработки и руководства. Добавьте дни после восстановления, когда люди сверяют записи, исправляют дубли, отвечают клиентам и готовят обязательные уведомления.
Не умножайте пугающую часовую сумму на самый долгий вообразимый простой. Точно опишите инцидент: например, четыре часа без приема заказов и день сверки или неверный расчет цен, дошедший до клиентов. Задокументируйте объем, маржу, оплату труда, условия договоров и допущения о восстановлении. Финансы должны суметь оспорить каждую строку.
Используйте две стоимости, если у системы разные виды отказа. Сбой доступности и тихое нарушение целостности редко выглядят одинаково. Второй сначала кажется дешевым, потому что его никто не заметил, а при восстановлении обходится намного дороже. Среднее значение скрывает разницу.
Стоимость меняет спор о переписывании, потому что задает разумные расходы на снижение воздействия. Хрупкую систему для небольшого внутреннего процесса можно рационально латать. Столь же хрупкая система с бухгалтерскими проводками или управлением движением на заводе требует меньшей терпимости по трем другим показателям.
Не превращайте стоимость в фокус с ожидаемыми потерями без надежных данных о частоте. Умножение угаданной годовой вероятности на смоделированное последствие дает аккуратную сумму из двух слабых входов. Оставьте видимыми доказательства частоты, последствий и неопределенности. Руководство может решить без притворства, что это актуарный расчет.
Сведите четыре числа на лист решения
Лист решения должен показывать текущее значение, динамику, уверенность, согласованную границу и действие при ее пересечении. Одной страницы достаточно. Она заставляет явно обсудить компромиссы, а не выдает ответ, которому руководство обязано подчиниться.
Используйте такую таблицу и замените примерные границы своими:
| Показатель | Сейчас | Динамика | Уверенность | Граница решения | Действие |
|---|---|---|---|---|---|
| Доля неудачных изменений | 18% из 50 изменений | Растет | Высокая | 15% в двух проверках | Финансировать проект замены |
| Доля безопасного владения | 2 из 14 инженеров | Падает | Средняя | Меньше 3 человек | Заморозить необязательные функции |
| Доля без поддержки | 35% с весами | Без изменений | Средняя | 25% при внешнем вводе | Начать изоляцию или замену |
| Стоимость инцидента | 480 000 долларов по модели | Растет | Низкая | Выше допустимого риска | Финансы проверяют сценарий |
Это иллюстрации, а не ориентиры. Интерфейсу больничных расчетов, принтеру складских этикеток и публичному каталогу нужны разные границы. Владельцы должны выбрать пределы до следующего инцидента и хранить доказательства каждого значения.
Не сворачивайте четыре показателя в один взвешенный балл слишком рано. Число 62 скрывает частые дешевые сбои или одну катастрофическую зависимость без поддержки. Сохраняйте четыре оси. Если руководству нужен статус, используйте три состояния:
- Продолжать ставить патчи, пока показатели не выходят за границы и улучшаются.
- Изолировать и готовиться, когда один показатель пересек границу или несколько ухудшаются.
- Переписывать, когда воздействие превысило предел, а надежное исправление не помогло.
Назначьте дату проверки и ответственного за каждый вход. Данные о сбоях берутся из записей развертываний и инцидентов. Доказательства владения находятся у руководителя разработки. Поддержку среды проверяет платформенная команда или безопасность. Финансы и владелец бизнеса подтверждают последствия.
Лист также защищает от разрастания объема. Если воздействие создает только пакетный планировщик, замените его, а не объявляйте весь комплекс негодным. Если слабо только владение, помогут ротация и документация. Переписывание заслуживает одобрения, когда показатели указывают на границу, которую нельзя экономично исправить на месте.
Патчи выигрывают при ограниченном и обратимом риске
Патчи остаются правильным ответом, когда изменения редко ломаются, несколько людей умеют ими владеть, неподдерживаемые части надежно изолированы, а инцидент укладывается в допустимый риск. Переписывание забирает внимание у продуктов, которые замечают клиенты. Не заменяйте стабильную программу ради красивой схемы.
Есть несколько сильных случаев в пользу патчей. Систему могут планово вывести из эксплуатации из-за закрытия направления. Ее поведение может быть закреплено нормой или договором, а изменений ожидается мало. Поставщик может предложить поддерживаемое обновление, которое убирает открытую среду без изменения логики. Либо приложение работает за узким контролируемым интерфейсом без недоверенного ввода и с проверенным восстановлением.
У патчей должны быть область и условие выхода. Финансируйте обновление зависимостей, характеризационные тесты, автоматизацию развертывания, наблюдаемость и передачу знаний. Затем измерьте снова. Если доля сбоев падает, а безопасное владение растет, работа помогает. Если каждый цикл команда заново собирает хрупкое развертывание или защищает среду, блокирующую остальные обновления, программа стала дорогой отсрочкой.
Я не согласен с популярным правилом сначала делить любой старый монолит на микросервисы. Совет кажется постепенным и потому безопаснее переписывания. На практике извлечение сервисов из кода с неизвестным поведением часто распределяет неопределенность по сети. Частичные отказы, версии интерфейсов и операционная нагрузка появляются до доказательства равенства. Сначала зафиксируйте поведение на границе системы, затем выбирайте границы по функциям бизнеса и владению данными.
Еще один разумный вариант - выборочная замена. Сохраните стабильный расчет или пакетную логику и замените неподдерживаемый интерфейс. Спрячьте зависимость от базы за поддерживаемым сервисом. Удалите неиспользуемые отчеты до переноса. После каждого удаления пересчитывайте показатели для оставшейся границы: маленькое старое ядро может стать достаточно дешевым для постоянной изоляции.
Не путайте патчи с бездействием. Решение сохранить систему означает конкретную работу: договоры поддержки, проверки контролей, учения по восстановлению, кадровое покрытие и плановую переоценку. Если это не финансируется, организация выбрала не патчи, а неуправляемое угасание.
Сначала переписывание сохраняет поведение, затем меняет архитектуру
Защищаемое переписывание фиксирует наблюдаемое поведение, запускает старую и новую реализации на одинаковых случаях и меняет архитектуру только при наличии доказательств. Построчный перенос сохраняет случайную структуру и может повторить дефекты без операционного контекста, который позволял с ними жить.
Начните с данных, похожих на рабочие. Записывайте запросы и ответы, если это разрешено, сохраняйте входы и выходы пакетных задач, характерные ошибки и побочные эффекты: файлы, сообщения, записи в базе, запросы оператору. Удаляйте секретные значения, но сохраняйте распределения, порядок и неверные случаи, проходящие реальные ветви.
Соберите стенд паритета, который отправляет один случай обеим системам и сравнивает нормализованные результаты. Явно нормализуйте время, созданные идентификаторы, незначимый порядок и другие недетерминированные поля. Не скрывайте различия широким текстовым фильтром. Каждое правило должно объяснять, почему отличие несущественно.
Для поведения с состоянием сравнивайте переходы, а не конечные экраны. Подготовьте одинаковое состояние базы, выполните действие и сравните измененные строки, сообщения, файлы и результаты. Для пакетной задачи проверьте чистое завершение, продолжение после остановки, повторный и поздний ввод, частичный сбой следующей системы. Операторы часто зависят от этих случаев сильнее, чем думают разработчики.
После этого архитектуру можно безопасно менять. Комплекс COBOL и JCL может стать сервисами Go с Postgres, числовое ядро может оправдать Rust, настольный клиент может перейти на TypeScript. Это проектные решения, а не самостоятельные цели. Цель - равное бизнес-поведение в модели, доступной нынешней команде.
CodeHero читает все дерево исходников и проверяет обновленную систему стендом паритета на записанном производственном трафике, а не переводит файлы по отдельности. Проекты поставляются менее чем за 30 дней, включая регулируемые среды, где предоставленные модели могут работать изолированно внутри периметра клиента.
Считайте расхождения паритета находками в спецификации. Одни указывают на дефекты новой реализации. Другие открывают противоречивое старое поведение, зависимую от среды логику или данные, нарушающие предполагаемые правила. Владелец бизнеса решает, какие особенности являются контрактом, а какие ошибкой. Из одного кода инженер это не выведет.
Для одобрения нужна рассчитанная альтернатива, а не энтузиазм
Предложение о переписывании должно конкурировать с полностью рассчитанным планом патчей и планом изоляции. Если альтернатива звучит как «продолжать страдать», сравнение подстроено. Оцените обновления, тесты, специалистов, договоры, контроли, воздействие инцидентов и задержку функций, которых действительно требуют патчи.
Считайте больше, чем реализацию. Включите исследование, фиксацию поведения, преобразование данных, параллельную работу, приемку, переключение, подготовку отката, обучение и вывод старой системы. Назначьте владельцев бизнес-решений и проверки данных. Технически готовая замена провалится, если финансы не сверят начальные остатки, а операторы не восстановят прерванную задачу.
Требуйте доказательств для графика. Перечислите интеграции, хранилища, задания, отчеты, роли, обмен файлами и процедуры. Пометьте каждый пункт как наблюдаемый, выведенный или неизвестный. Неизвестное не обязано блокировать проект, но кто-то должен определить способ проверки до переключения.
На этапе одобрения дайте простые ответы на пять вопросов:
- Какой показатель пересек согласованную границу и чем это доказано?
- Что команда пыталась исправить и как изменился показатель?
- Какая граница будет заменена, сохранена или удалена?
- Как команда докажет паритет и отрепетирует откат?
- Какой владелец бизнеса принимает оставшиеся различия и риск?
При расплывчатых ответах финансируйте короткий этап сбора доказательств, а не переписывание. Он должен дать инвентарь среды, оценку владения, модель инцидента, набор поведенческих случаев и границу системы. Презентация о современности результатом не считается.
В одобрение входят условия остановки. Если в процессе с тяжелыми последствиями остаются расхождения, преобразованные данные не сверяются или замена не выполняет требование восстановления, переключение ждет. Уже потраченные деньги не делают непроверенную систему безопасной.
Пересматривайте решение после каждого существенного изменения
Решение устаревает при изменении системы, команды или последствий. Пересчитайте показатели после крупного обновления, передачи владения, приобретения, изменения нагрузки, нового требования или серьезного инцидента. Лист, забытый на год, становится еще одним старым документом.
Держите доказательства рядом с обычной работой. Записи развертываний должны отмечать исправленные изменения. Разборы инцидентов должны отделять вызванные изменением сбои и хранить реальные затраты на труд и сверку. Навыки подтверждаются поставленной работой. Инвентарь обновляется из исполняемых сред, а не годовой анкеты.
Следите за направлением и порогами. Четыре показателя внутри границ, но ухудшающиеся вместе, оправдывают подготовку. Один показатель за границей, но быстро улучшающийся, может оправдать еще один цикл патчей. Запишите исключение, владельца и срок, чтобы временная терпимость не стала постоянной политикой.
Самые трудные случаи дают противоречивые сигналы. Система может быть стабильной и дешевой при инцидентах, пока владение рушится. У нее может быть много специалистов и неподдерживаемая публичная среда. Не растворяйте неудобную ось в среднем. Решите, способен ли надежный контроль сдвинуть ее до скрытого срока.
Первая полезная встреча - не семинар о переписывании. Это разбор, на который разработка, эксплуатация, безопасность, финансы и бизнес приносят доказательства по одному числу. В конце установите границы и профинансируйте связанное действие. Если числа поддерживают патчи, ставьте их без извинений. Если каждое безопасное изменение зависит от исчезающих знаний, брошенного ПО и неприемлемой цены инцидента, перестаньте платить за иллюзию, что еще один патч вернет контроль.
Вопросы
Когда компании следует переписать старое ПО?
Переписывайте, когда измеренный риск и воздействие на бизнес пересекли заранее согласованные границы, а целевые исправления не помогли. Один возраст и непопулярная технология замену не оправдывают.
Какова хорошая доля неудачных изменений для старой системы?
Универсального значения для всех процессов нет. Задайте границу по своему объему изменений, времени восстановления и последствиям, затем смотрите динамику нескольких проверок.
Как измерить, кто может безопасно поддерживать старый код?
Считайте инженеров, которые самостоятельно объясняют, меняют, проверяют, выпускают и восстанавливают значимое изменение. Доступ к репозиторию, самооценка и работа под руководством старого эксперта не подходят.
Всегда ли неподдерживаемая среда требует переписывания?
Нет. Изоляция, строгий контроль входа, виртуальные патчи или платная продленная поддержка могут оправдать ремонт. Замена становится срочной, если компонент принимает недоверенный ввод, блокирует обновления или слишком дорог в изоляции.
Как оценить стоимость инцидента до аварии?
Опишите конкретный сценарий и попросите финансы, эксплуатацию, безопасность и бизнес проверить каждое допущение. Учтите потерянную маржу, полную стоимость труда, исправления для клиентов, договорные расходы, сверку и задержанные события.
Доказывают ли редкие развертывания стабильность старого ПО?
Нет. Система может выглядеть стабильной из-за страха команды перед выпуском. Учитывайте отложенные запросы вместе с долей сбоев, чтобы паралич не выглядел надежностью.
Нужно ли сначала делить старый монолит на микросервисы?
Обычно нет, пока его поведение не зафиксировано. Деление плохо понятного кода добавляет сетевые сбои и версии интерфейсов, распределяя ту же неопределенность.
Можно ли заменить только часть унаследованной системы?
Да, выборочная замена часто разумнее. Уберите компонент, создающий воздействие или сбои, затем пересчитайте четыре показателя для оставшейся границы.
Как доказать соответствие новой системы старой?
Запустите обе реализации на одинаковых производственных случаях и сравните результаты и переходы состояния. Для любой нормализации времени, идентификаторов или порядка нужна записанная причина, чтобы настоящие различия остались видимыми.
Как часто пересматривать решение о переписывании?
Пересматривайте его после существенного изменения зависимостей, владения, последствий, нагрузки или требований. Также назначьте регулярную дату и владельца каждого показателя.