Как понять, что программу пора переписывать

 

 

 

 

АНАЛИЗ_НАСЛЕДИЯ // LEGACY_CODE_INTRO

Иллюзия устаревания: почему возраст кода не повод для переписывания

Старый код часто выглядит как очевидный кандидат на переписывание.

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

  • › новая функция требует изменений в пяти местах;
  • › разработчик, который создавал систему, уже не работает в компании;
  • › тестов мало, документация устарела.
// СТРАХ ПЕРЕД ДЕПЛОЕМ //
Каждый релиз сопровождается фразой:
«Только бы ничего не сломать».

В такой ситуации очень легко принять эмоциональное решение:

«Всё, эту программу пора переписывать с нуля».
// ОПРОВЕРЖЕНИЕ КРИТЕРИЯ ВОЗРАСТА //

Но возраст системы сам по себе ничего не доказывает.

// СТАРЫЙ ПРОЕКТ //

Написан десять лет назад

При этом может оставаться устойчивым, понятным и относительно дешёвым в сопровождении.

// МОЛОДОЙ ПРОЕКТ //

Относительно новый стек

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

Поэтому правильный вопрос звучит иначе:

Не пора ли переписать старый код, а сколько бизнесу стоит продолжать менять систему в её текущем состоянии?

Это принципиальная разница.

 

 

КРИТЕРИИ // LEGACY_NOT_A_DIAGNOSIS

Старый код — не диагноз

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

Если система:

  • › выполняет свои функции;
  • › выдерживает необходимую нагрузку;
  • › соответствует требованиям безопасности;
  • › поддерживается командой;
  • › позволяет выпускать необходимые изменения;
  • › имеет приемлемую стоимость эксплуатации,
// ГЛАВНЫЙ ФАКТОР //

то сам факт, что её код написан давно, не является причиной для переписывания. В инженерии гораздо важнее не дата появления кода, а стоимость его изменения.

Представим две системы.

// СИСТЕМА А (ЕЙ 12 ЛЕТ) //

Архитектура хорошо известна, основные модули отделены друг от друга, тесты покрывают критические сценарии, развёртывание автоматизировано.

Новая функция занимает пять дней.
// СИСТЕМА Б (ЕЙ 3 ГОДА) //

Добавление небольшой функции требует:

  • • найти зависимости в нескольких модулях;
  • • вручную проверить десятки сценариев;
  • • изменить несколько связанных таблиц;
  • • выполнить ручное тестирование;
  • • несколько раз исправить ошибки после релиза.
Такая функция занимает три недели.

Получается парадокс:

Возраст системыСтарая системаМолодая системаизменения дешёвыеизменения дорогиеможно развиватьпроблема уже есть

Поэтому смотреть только на год разработки бессмысленно.

 

 

ЭКОНОМИКА // TECHNICAL_DEBT_PRACTICE

Что такое технический долг на практике

Технический долг часто используют как универсальное объяснение любой проблемы старой системы. Но сам по себе технический долг — не обязательно катастрофа.

// СОЗНАТЕЛЬНЫЙ ВЫБОР //

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

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

Новая функцияИзменить модуль Aзависит от Bзависит от Cстарая таблицаправило в Dручное тестированиеновый багдополнительный фикс
// ЭКОНОМИЧЕСКИЙ ЭФФЕКТ //

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

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

 

 

МЕТРИКИ // METRICS_DYNAMICS

Главный показатель — не количество старого кода, а динамика

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

Стоимость изменений Январь ████ Февраль █████ Март ██████ Апрель ████████ Май ██████████ Июнь ████████████
// ТЕНДЕНЦИЯ РОСТА ИЗДЕРЖЕК //

Если аналогичные изменения систематически становятся дороже, это уже архитектурный сигнал. Особенно если одновременно растёт количество дефектов.

Стоимость изменений↑время →Количество дефектов↑время →

Это намного полезнее, чем утверждение: «Нашему приложению уже десять лет».

 

 

СВЯЗНОСТЬ // TIGHT_COUPLING_SIGNALS

Признак №1. Любое изменение начинает затрагивать всё

Один из наиболее неприятных симптомов — отсутствие локальности изменений.

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

  • › в API;
  • › в отчётах;
  • › в расчёте стоимости;
  • › в интеграции с ERP;
  • › в мобильном приложении;
  • › в обмене с внешней системой;
  • › в нескольких фоновых обработчиках.

И изменение одной сущности начинает выглядеть так:

ЗаказAPIERPОтчётыМобильноеприложениеИнтеграцияАналитикаФоновыепроцессы
// ОЦЕНКА ОГРАНИЧЕНИЙ //

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

И тогда первым кандидатом на модернизацию должен быть не весь проект. Нужно найти наиболее проблемный участок.

 

 

РИСКИ // KNOWLEDGE_BUS_FACTOR

Признак №2. Разработчик боится менять код

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

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

// ШТАТНАЯ ОСТОРОЖНОСТЬ //

Одно дело — обоснованная инженерная осторожность вокруг критического финансового расчёта.

// КРИТИЧЕСКИЙ СИГНАЛ //

Совсем другое — ситуация, когда никто не может объяснить, какие последствия вызовет изменение обычного бизнес-правила.

Особенно опасны системы, где знания существуют только в головах отдельных сотрудников:

СистемаКод знаетформальноИван знаетпочему такИван уходитПоведение системыстановится загадкой
// АНАЛИЗ ПРОЦЕССОВ //

Здесь проблема уже не только в старом коде.

Знания о системе перестали быть частью самой системы и процессов компании.

 

 

ДЕФЕКТЫ // RECURSIVE_BUGS_SIGNALS

Признак №3. Исправление одного дефекта создаёт другой

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

Исправили расчёт скидкисломался отчётисправили отчётизменился экспортсломалась интеграция
// СИСТЕМНЫЙ СБОЙ //

В таком случае бессмысленно считать каждый дефект отдельной случайностью. Нужно посмотреть на структуру системы.

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

 

 

ПРОИЗВОДИТЕЛЬНОСТЬ // PERFORMANCE_BOTTLENECK

Признак №4. Производительность упирается не в сервер

Медленная система не всегда означает, что её пора переписывать.

Иногда проблема решается:

  • › индексом;
  • › оптимизацией запроса;
  • › кэшированием;
  • › изменением структуры данных;
  • › очередью фоновых задач;
  • › настройкой инфраструктуры;
  • › разделением чтения и записи.
// ИМПУЛЬСИВНЫЙ ВЫВОД WORKAROUND //
«Программа тормозит, давайте перепишем»
— практически бесполезна без диагностики.

Нужно сначала установить, где находится ограничение.

ПользовательAPICPU?Database?Network?External API?Lock / Queue?
// ВЫВОД ДИАГНОСТИКИ //

Если приложение тратит 90% времени, ожидая внешний сервис, переписывание внутреннего кода может почти ничего не изменить.

 

 

БЕЗОПАСНОСТЬ // SECURITY_COMPLIANCE_RISKS

Признак №5. Безопасность уже нельзя поддерживать нормально

Здесь ситуация принципиально отличается от обычного технического долга.

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

Появляются риски:

  • - уязвимостей;
  • - невозможности установить обновления;
  • - отсутствия современных механизмов аутентификации;
  • - неконтролируемого доступа;
  • - проблем с аудитом;
  • - невозможности выполнить требования безопасности компании.
// КЛАССИФИКАЦИЯ РИСКА //

Но и здесь важно не путать: «Старый компонент» с «Небезопасный компонент».

// ФОРМАЛЬНЫЙ КРИТЕРИЙ //

Версия сама по себе не определяет уровень риска.

// ФАКТИЧЕСКИЙ КРИТЕРИЙ //

Нужно смотреть на конкретную технологию, способ эксплуатации, доступность обновлений и фактическую поверхность атаки.

 

 

БИЗНЕС_ПРОЦЕССЫ // BUSINESS_VELOCITY_CONFLICT

Признак №6. Бизнес хочет менять систему быстрее, чем она способна меняться

Это один из самых важных критериев.

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

// БИЗНЕС //
новые изменения → новые изменения → новые изменения

быстрее рынка

// СИСТЕМА //
изменение
 └── тестирование
     └── исправления
         └── ручная проверка
             └── релиз
                 └── снова сначала
// ОГРАНИЧЕНИЕ РОСТА //

В этот момент технический долг становится ограничением бизнес-модели. Именно здесь модернизация может иметь экономический смысл.

 

 

УСЛОВИЯ_РЕФАКТОРИНГА // JUSTIFIED_REWRITE_CONDITIONS

Когда переписывание действительно оправдано

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

Например:

  • › существующая архитектура мешает реализовывать ключевые требования;
  • › стоимость изменений постоянно растёт;
  • › критические части невозможно нормально тестировать;
  • › используемый технологический стек больше нельзя поддерживать;
  • › производительность нельзя исправить локальными изменениями;
  • › требования безопасности невозможно обеспечить без фундаментальных изменений;
  • › система настолько связана, что выделение отдельных компонентов практически невозможно;
  • › бизнес действительно получает выгоду от новой архитектуры.
// БИЗНЕС-ЦЕЛЕСООБРАЗНОСТЬ //

Последний пункт особенно важен.

Техническое желание написать красивый код ещё не является бизнес-причиной для переписывания.

 

 

ОГРАНИЧЕНИЯ // WHEN_NOT_TO_REWRITE

Когда переписывать не стоит

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

// «КОД НЕКРАСИВЫЙ» //

Некрасивый код может отлично выполнять бизнес-функцию.

Если он плохо читается, но изменения стоят приемлемо, проблема может решаться рефакторингом.

// «СТАРАЯ ТЕХНОЛОГИЯ» //

Старая технология может быть стабильной и хорошо поддерживаемой.

Нужно оценивать реальные ограничения, а не возраст технологии.

// «ХОТИМ МИКРОСЕРВИСЫ» //

Микросервисы — архитектурный инструмент, а не лекарство от технического долга.

Если просто перенести старую связанную систему в двадцать сервисов, связность никуда не исчезнет. Она может стать распределённой.

Монолит:ABCDПосле неудачного разделения:A↔B↔C↔D↕↕↕↕E↔F↔G↔H
// ПОБОЧНЫЙ ЭФФЕКТ //

Теперь вместо одного сложного приложения появляется распределённая система со сложными сетевыми зависимостями.

«Проще написать заново»

// КРИТИЧЕСКИЙ РИСК //

Это одна из самых опасных фраз. Старая система содержит не только код. Она содержит накопленное знание о бизнесе.

И значительная часть этого знания может быть нигде не задокументирована.

 

 

СПЕЦИФИКАЦИЯ // HIDDEN_LOGIC_RISKS

Самая опасная часть rewrite — то, чего нет в документации

Представим, что старая система рассчитывает стоимость доставки.

// ДОКУМЕНТАЦИЯ ГОВОРЯТ //
Стоимость зависит от веса и региона.

Но в коде за десять лет накопились исключения:

  • › Если регион = X → специальный тариф
  • › Если клиент = Y → другой коэффициент
  • › Если вес > Z → отдельная формула
  • › Если заказ создан в выходной → дополнительное правило
  • › Если товар относится к категории Q → исключение
  • › Если способ доставки = N → старая интеграция
// ПОТЕРЯ СПЕЦИФИКАЦИИ //

Разработчик нового проекта может даже не знать о существовании половины этих правил.

Поэтому «переписать один в один» невозможно без глубокого исследования поведения старой системы.

И здесь возникает фундаментальная проблема:

Новая системадолжнаповторитьБизнес-поведениедокументациякодтестыинтеграцииданныенеформальные правила

Код — лишь одна часть спецификации.

 

 

УПРАВЛЕНИЕ // MOVING_TARGET_CHALLENGE

Почему большой rewrite часто превращается в движущуюся цель

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

Появляются:

  • › новые функции;
  • › новые интеграции;
  • › новые правила;
  • › изменения законодательства;
  • › новые пользователи;
  • › новые данные.

Получается:

Старая системаработает, получает новые функции,продолжает менятьсяТребования к новойсистеме растутсрок rewrite отодвигается
// СИНХРОНИЗАЦИЯ ВЕРСИЙ //

В какой-то момент новая система должна не просто заменить старую. Она должна заменить старую систему в её новой версии, которая уже успела измениться.

Это одна из причин, почему длительные проекты полной замены так трудно удерживать в первоначальных сроках.

 

 

ЭВОЛЮЦИЯ // STRANGLER_FIG_PATTERN

Альтернатива: менять систему по частям

Во многих случаях разумнее не уничтожать старую систему, а постепенно уменьшать её ответственность.

Подход часто называют Strangler Fig — по аналогии с растением, которое постепенно обрастает вокруг исходного дерева. Идея давно используется как модель постепенной замены legacy-систем: новая функциональность появляется рядом со старой, а отдельные части системы постепенно переводятся на новую реализацию.

БЫЛОПользовательСтарая системаA | B | C | D | EПЕРЕХОДПользовательМаршрутизацияСтараяA B C DНоваяEПОСЛЕПользовательНовая системаA B C D EСтарая система → отключена
// ПОЭТАПНАЯ СТРАТЕГИЯ //

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

Microsoft также описывает этот паттерн как постепенную замену частей legacy-системы с сохранением работающей старой системы до момента полного переноса.

 

 

ИЗДЕРЖКИ // INCREMENTAL_EVOLUTION_COST

Но постепенная модернизация — не магия

У неё тоже есть цена.

Какое-то время приходится поддерживать:

Старая система
+
Новая система
+
Интеграционный слой
+
Синхронизация данных
// ВРЕМЕННАЯ АРХИТЕКТУРА //

Поэтому возникает временная архитектура. Она может быть сложнее конечной.

// РАСПРЕДЕЛЕНИЕ РИСКОВ //

Но её преимущество в другом: риск распределяется по этапам.

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

Это особенно важно для критических систем, где ошибка полной миграции может остановить бизнес.

 

 

ПРИОРИТЕТЫ // MIGRATION_CANDIDATE_SELECTION

Что именно переносить первым

Ошибка — начинать с самого большого модуля только потому, что он самый большой.

Лучше искать участок, который одновременно:

  • › создаёт заметную бизнес-боль;
  • › имеет понятные границы;
  • › достаточно независим;
  • › позволяет измерить результат;
  • › не требует переписывания всей системы сразу.

Например:

Legacy
├── Заказы
├── Клиенты
├── Документы       ← кандидат
├── Отчётность
├── Платежи
└── Справочники
// ДЕКОМПОЗИЦИЯ ОТВЕТСТВЕННОСТИ //

Можно сначала заменить работу с документами. Если новая реализация работает независимо, постепенно уменьшается зона ответственности legacy-системы.

Это даёт не только результат. Это даёт опыт самой миграции.

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

 

 

ГРАНИЦЫ // LAYER_MODERNIZATION_STRATEGY

Иногда переписывать нужно не программу, а отдельный слой

Очень важное наблюдение: проблема может находиться только в одном уровне системы.

Например, локализация деградации по слоям приложения:

UI              нормально
API             нормально
Бизнес-логика    сложно менять
База данных      нормальная
Инфраструктура   нормальная
// ОГРАНИЧЕНИЕ ИЗМЕНЕНИЙ //

В таком случае переписывать всё приложение бессмысленно. Можно заменить только проблемный слой.

Другой пример распределения ограничений:

Приложение      работает
База данных     стала ограничением
Интеграции      работают
// ЛОКАЛЬНАЯ ТАКТИКА //

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

// ФУНДАМЕНТАЛЬНЫЙ ЗАКОН МОДЕРНИЗАЦИИ //

Граница переписывания должна совпадать с границей проблемы.

Это один из наиболее полезных принципов при модернизации.

 

 

АНАЛИЗ_РИСКОВ // REWRITE_EVALUATION_PART1

Как оценить решение до начала rewrite

Перед тем как объявлять большой проект, полезно ответить хотя бы на несколько вопросов.

1. Что именно стало неприемлемым?

Не «код плохой», а конкретные измеримые параметры:

  • - время разработки;
  • - количество дефектов;
  • - производительность;
  • - безопасность;
  • - стоимость инфраструктуры;
  • - невозможность интеграции;
  • - отсутствие поддержки технологии.

2. Можно ли устранить проблему локально?

Если да, полный rewrite может оказаться избыточным.

3. Сколько стоит текущее состояние?

Нужно оценить не только зарплату разработчиков. Формула включает скрытые издержки:

Стоимость legacy
=
разработка
+
поддержка
+
инциденты
+
простой
+
ручные операции
+
замедление новых проектов
+
стоимость ошибок

4. Сколько будет стоить новая система?

Причем нужно считать не только разработку. Добавляются накладные расходы:

  • › миграция;
  • › тестирование;
  • › двойная эксплуатация;
  • › обучение;
  • › перенос данных;
  • › интеграции;
  • › поддержка переходного периода.

5. Как будет доказано, что новая система лучше?

Нужны измеримые критерии сравнения:

// МЕТРИКА: СКОРОСТЬ РЕЛИЗА //

Было: релиз → 3 недели

Цель: релиз → 2 дня

// МЕТРИКА: СКОРОСТЬ API //

Было: 95-й перцентиль API → 1,8 с

Цель: 95-й перцентиль → 300 мс

// МЕТРИКА: СКОРОСТЬ ИЗМЕНЕНИЙ //

Было: изменение модуля → 12 дней

Цель: изменение → 3 дня

// ОГРАНИЧЕНИЕ ЦЕЛЕПОЛАГАНИЯ //

Без таких показателей rewrite легко превращается в проект ради самого проекта.

 

 

ЭКОНОМИКА // ECONOMIC_COMPARISON_STRATEGY

Стоит считать не стоимость переписывания, а стоимость двух вариантов

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

СистемаОставить как естьстоимость изменений+ инциденты+ ограничения+ риски+ инфраструктураМодернизироватьразработка+ миграция+ переход+ новая эксплуатация- будущие ограниченияСравнение
// ГОРИЗОНТ ПЛАНИРОВАНИЯ //

Причём сравнивать нужно не только ближайшие шесть месяцев. Если текущая система ежегодно становится на 15–20% дороже в изменении, это уже другой экономический сценарий.

В какой-то момент технический долг начинает приносить такой большой «процент», что инвестиции в модернизацию становятся рациональными.

 

 

КЛАССИФИКАЦИЯ // REWRITE_STRATEGIES_MAPPING

Есть ещё один важный вопрос: что именно означает «переписать»

Под этим словом часто смешивают совершенно разные действия. Важно разделять подходы:

// 1. РЕФАКТОРИНГ //

Внешнее поведение сохраняется, внутренняя структура улучшается.

Старый код
    ↓
рефакторинг
    ↓
Более поддерживаемый код
// 2. МОДЕРНИЗАЦИЯ //

Система получает новые технологические или архитектурные возможности, но бизнес-функции сохраняются.

// 3. ЧАСТИЧНАЯ ЗАМЕНА //

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

// 4. ПОСТЕПЕННАЯ МИГРАЦИЯ //

Новая система постепенно принимает на себя ответственность старой.

// 5. ПОЛНЫЙ REWRITE //

Система создаётся заново и затем целиком заменяет существующую.

// НЕОПРЕДЕЛЕННОСТЬ ТЕРМИНА //

Это пять разных стратегий с разным уровнем риска.

Поэтому фраза «нам нужно переписать систему» ещё ничего не говорит о конкретном плане работ.

 

 

РИСКИ_МИГРАЦИИ // REWRITE_STRATEGY_RISKS

Самая плохая стратегия — переписать всё и только потом проверить

Представим классический сценарий «большого взрыва» при полной замене системы:

12 месяцев разработкиНовая системаМиграцияПервый полноценный запускОбнаружилось:

А дальше выясняется:

  • - одно бизнес-правило забыли;
  • - один внешний контрагент работает иначе;
  • - исторические данные имеют исключения;
  • - пользователи используют функцию, которой не было в документации;
  • - производительность на реальной нагрузке отличается от тестовой;
  • - часть старых интеграций невозможно отключить.
// СТОИМОСТЬ ПОЗДНИХ ИСПРАВЛЕНИЙ //

Чем позже обнаруживается такая проблема, тем дороже её исправление.

// МИТИГАЦИЯ РИСКОВ //

Поэтому хороший процесс модернизации старается уменьшать неопределённость постепенно, а не переносить её на день финального запуска.

 

 

ПОДГОТОВКА // PRE_DECISION_STRATEGY

Что делать перед принятием решения

Полезно начать не с написания нового кода, а с обследования.

Минимальный набор:

СистемаАрхитектураДанныеНагрузкаЗависимостиКачествоПроизводительностьРиски и стоимостьстратегия изменений

Нужно понять:

  • › какие части системы действительно критичны;
  • › где находятся самые сильные зависимости;
  • › какие данные являются источником истины;
  • › какие интеграции нельзя нарушить;
  • › какие функции используются на самом деле;
  • › где находится основная нагрузка;
  • › какие изменения наиболее дороги;
  • › какие участки можно отделить;
  • › какие результаты должна дать модернизация.

После этого уже можно выбирать стратегию.

 

 

ИНЖЕНЕРИЯ // REWRITE_ALTERNATIVE_CONCLUSIONS

Иногда лучший результат — вообще не переписывать систему

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

// КЕЙС 1: ОПТИМИЗАЦИЯ СУБД //
Проблема: старый код
Реальная причина: плохие индексы
Решение: оптимизация БД
// КЕЙС 2: АСИНХРОННОСТЬ //
Проблема: долгие операции
Реальная причина: всё выполняется синхронно
Решение: очередь фоновых задач
// КЕЙС 3: ЛОКАЛИЗАЦИЯ СВЯЗНОСТИ //
Проблема: дорогие изменения
Реальная причина: один связанный модуль
Решение: выделить его и постепенно переработать

И только иногда комплекс факторов требует радикальных шагов:

Проблема:
архитектурные ограничения
+
высокая стоимость изменений
+
неустранимые технологические ограничения
+
бизнесу нужна другая скорость
↓
полноценная модернизация
// СУТЬ ПОДХОДА //

Это и есть инженерный подход.

Не искать повод переписать.

И не защищать старую систему любой ценой.

 

 

ЦЕННОСТЬ // LEGACY_BUSINESS_VALUE

Система должна оправдывать стоимость своего существования

У работающего legacy-приложения есть важное преимущество: оно уже решает реальную бизнес-задачу. Это нельзя недооценивать.

В нём находятся:

  • › годы эксплуатации;
  • › данные;
  • › интеграции;
  • › исключения;
  • › пользовательские привычки;
  • › знания о процессах.
// ИНЖЕНЕРНАЯ АНАЛОГИЯ //

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

// КРИТЕРИЙ КОРРЕКТНОСТИ //

Иногда это действительно необходимо.

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

 

 

ЭКОНОМИКА // JUSTIFIED_REWRITE_CRITERIA

Когда переписывание становится оправданным

Есть простой практический критерий.

Если система всё ещё работает, но каждое изменение становится всё дороже, опаснее и медленнее, нужно смотреть не на её возраст, а на кривую стоимости изменений.

Стоимость изменения │ │ ● │ ● │ ● │ ● │ ● │ ● │ ● └──────────────────────────────► время
// ЛОКАЛЬНЫЙ РЕФАКТОРИНГ //

Если эту кривую можно вернуть вниз локальным рефакторингом — не нужен rewrite.

// ЗАМЕНА КОМПОНЕНТА //

Если проблема решается заменой одного компонента — не нужен rewrite всей системы.

// ПОЭТАПНОЕ РАЗДЕЛЕНИЕ //

Если систему можно постепенно разделить — вероятно, безопаснее идти поэтапно.

// КРИТИЧЕСКАЯ МОДЕРНИЗАЦИЯ //

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

 

 

ИНЖЕНЕРИЯ // MAIN_REWRITE_RULE

Главное правило

// КРИТЕРИЙ ВОЗРАСТА //
Программу не пора переписывать потому, что она старая.

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

И даже тогда «переписать всё» — только один из вариантов. Альтернативные тактические сценарии:

  • › Иногда правильное решение — рефакторинг.
  • › Иногда — заменить один модуль.
  • › Иногда — вынести отдельный контур.
  • › Иногда — изменить базу данных или инфраструктуру.
  • › Иногда — постепенно построить новую систему рядом со старой и переносить ответственность частями.
// КРАЙНЯЯ МЕРА //
А иногда действительно требуется полный rewrite.
Локализация ограничения+ оценка издержек бизнесаИнженерное решениеИсключение фактора вкусаТочный выбор стратегии
// КРИТЕРИЙ СТАРТА //

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

Она начинается с вопроса:

«Что в текущей системе уже стало слишком дорогим — и можно ли решить именно эту проблему, не переписывая то, что продолжает работать хорошо?»

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

 

 

НАВИГАЦИЯ // SUGGESTED_READING
 
[ Модуль // ИНТЕГРАЦИИ ]

API, Webhook или очередь сообщений?

 
[ Модуль // ИНТЕГРАЦИИ ]

Когда API есть, а интеграция всё равно не работает

 
[ Модуль // АВТОМАТИЗАЦИЯ ]

Как соединить производство и корпоративные системы

 
[ EXPERTISE JOURNAL ]

Все инженерные материалы и экспертные статьи

 
[ CORE GLOSSARY ]

Полный алфавитный справочник ИТ-терминов

 

[ DIRECT EMAIL LINE ]
info@log-ai.ru

 

🔒 Данные и доступ к системам заказчика обрабатываются в соответствии с согласованными требованиями к безопасности и конфиденциальности. Условия доступа, хранения и обработки данных определяются архитектурой проекта и договором.

Сайт носит исключительно информационный характер и не является публичной офертой в соответствии со статьёй 437 Гражданского кодекса РФ. Цены, состав и условия предоставления услуг уточняются при проектировании решения и фиксируются в договоре. Условия технического сопровождения и уровень сервиса могут дополнительно определяться отдельным соглашением (SLA).

© 2026 Log-AI Москва
Автоматизация бизнеса и ИИ-решения под ключ
Самозанятый Скопец Антон Викторович ИНН 741709260870
AI Ассистент
×