Rain Lag

Аналоговая карта рефакторинга-рельсов: как прокладывать безопасные маршруты через легаси‑код, как по линиям метро

Как относиться к рефакторингу легаси‑системы как к планированию метро: использовать DDD, Clean Architecture и визуальные карты, чтобы проектировать безопасные, поэтапные маршруты изменений во хрупких системах, а не слепо всё переписывать.

Аналоговая карта рефакторинга‑рельсов: как прокладывать безопасные маршруты через легаси‑код, как по линиям метро

Легаси‑системы редко ломаются из‑за одной неудачной строки кода. Они ломаются, когда люди теряют карту.

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

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

В этом посте разберём, как:

  • Относиться к рефакторингу как к организационной и операционной задаче, а не только к написанию кода.
  • Использовать Clean Architecture, SOLID и Domain‑Driven Design (DDD) для структурирования изменений.
  • Совместно моделировать предметную область с помощью досок, стикеров и специализированных инструментов.
  • Применять bounded contexts и context maps для определения безопасных границ.
  • Использовать такие инструменты, как Context Mapper, чтобы формализовать и проверять архитектуру.
  • Обратным анализом строить модели по существующим артефактам (JSON‑схемы, API, Java‑классы).
  • Визуализировать эволюционирующую архитектуру как карту метро, чтобы команды могли безопасно по ней ориентироваться.

1. Рефакторинг легаси — это не просто упражнение в кодинге

У большинства провалившихся рефакторингов есть общий корень: кто‑то попытался отнестись к ним как к «технической уборке», а не как к бизнес‑операции.

Легаси‑система — это:

  • Двигатель выручки (даже если выглядит ужасно).
  • База знаний многолетних бизнес‑правил.
  • Социотехническая система с командами, привычками и политикой, выстроенными вокруг неё.

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

Два принципа помогают оставаться на земле:

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

  2. Относитесь к рефакторингу как к организационному изменению.
    Кто пользуется системой? Кто её финансирует? Кого заденет сбой? Привлекайте этих людей. Планируйте рефакторинг как операционный проект: поэтапный rollout, коммуникацию, пилоты и стратегии отката.

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


2. Clean Architecture и SOLID: перекладка рельсов

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

Clean Architecture и принципы SOLID — не серебряная пуля, но они дают вам:

  • Способ отделить бизнес‑правила от технических деталей (UI, база данных, фреймворки).
  • Структуру, которая позволяет менять внешние слои, не трогая ядро.
  • Ограничители для поэтапной модернизации.

Когда вы трогаете легаси‑код:

  • Начните с поиска швов (seams): мест, где можно ввести адаптеры или фасады вокруг особо грязных участков.
  • Постепенно переносите логику к более понятным границам: сущности (entities), сценарии использования (use cases), интерфейсы.
  • Применяйте SOLID локально:
    • Single Responsibility Principle (SRP): разделяйте классы, которые очевидно делают несколько вещей (например, и парсинг, и бизнес‑логику, и сохранение в БД).
    • Dependency Inversion: завиcьте от интерфейсов, определённых в домене, а не от конкретных классов фреймворка.

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


3. Domain‑Driven Design: нарисуйте карту, прежде чем двигать рельсы

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

Здесь важна совместная модель предметной области:

  • Используйте доски, стикеры или онлайн‑инструменты (Miro, Mural и т.п.).
  • Приглашайте доменных экспертов, не только разработчиков.
  • Рисуйте процессы, сущности, события и правила.
  • Фиксируйте решения по ходу дела — особенно разногласия и компромиссы.

Цель — общая модель домена:

  • Какие основные сущности и понятия? (Orders, Shipments, Policies, Accounts…)
  • Как они связаны? Кто «владеет» какими данными?
  • Где начинаются и заканчиваются зоны ответственности?

Каждый стикер и каждая стрелка на доске — как станции и линии на плане метро. Вы проектируете как люди будут «путешествовать» по системе, а не только как объекты ссылаются друг на друга в коде.


4. Bounded Contexts: где заканчивается одна линия и начинается другая

Проблема многих легаси‑систем: всё говорит со всем. Это как если бы все поезда ездили по одним и тем же рельсам без выделенных линий — чистый хаос.

DDD даёт инструмент — bounded context (ограниченный контекст):

  • Bounded context — это целостный пузырь смысла: поддомен, где термины и модели используются последовательно.
  • «Customer» в Billing может отличаться от «Customer» в CRM.
  • У каждого bounded context — свои модели, правила и схемы.

Это критично для безопасного рефакторинга:

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

Используйте context maps (контекстные карты), чтобы показать, как контексты взаимодействуют:

  • Отношения upstream/downstream.
  • Shared kernel (общие модели между контекстами).
  • Anti‑corruption layer (антикоррупционные слои), которые защищают одну модель от влияния другой.

На вашей аналоговой карте рефакторинга‑рельсов каждый bounded context — это линия метро, а context map показывает, где линии пересекаются и пересадки. Эти пересадки — критические точки, где риск рефакторинга максимален и где нужно действовать особенно осознанно.


5. Формализация карты с помощью Context Mapper

Стикеры на стене — мощный инструмент, но их сложно хранить в Git.

Инструменты вроде Context Mapper помогают превратить вашу концептуальную карту метро в артефакт, который можно:

  • Версионировать в Git.
  • Генерировать из него диаграммы (context maps, UML‑подобные представления).
  • Проверять на соблюдение определённых архитектурных правил.
  • Использовать как основу для полуавтоматических трансформаций.

С Context Mapper вы можете:

  • Описывать bounded contexts и их связи в специализированном DSL.
  • Генерировать визуальные диаграммы, делающие архитектуру обозримой и обсуждаемой.
  • Исследовать паттерны рефакторинга: деление или объединение контекстов, изменение отношений, добавление новых anti‑corruption layers.

Это мост между наброском на доске и изменениями на уровне кода. Ваша карта становится частью кодовой базы и эволюционирует вместе с ней.


6. Обратная разработка линий по существующим артефактам

В brownfield‑системах вы почти никогда не начинаете с чистой доски. У вас уже есть:

  • JSON‑схемы
  • Спецификации API
  • Схемы баз данных
  • Java‑ (и другие) классы
  • Логи событий

Не игнорируйте их — используйте эти артефакты, чтобы обратным путём восстановить карту домена:

  • Группируйте JSON‑схемы или эндпоинты API в кандидаты на bounded contexts по признакам владения и использованного языка.
  • Анализируйте структуру Java‑пакетов и зависимости, чтобы найти неявные модули.
  • Используйте потоки событий (Kafka topics, очереди сообщений), чтобы увидеть, как двигаются данные.

События особенно показательные:

  • «OrderPlaced», «PaymentCaptured», «ShipmentDispatched» описывают бизнес‑процессы.
  • Последовательность и связность событий помогают выявить отношения upstream/downstream.

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

Это фундамент для безопасных изменений:

  • Вы понимаете текущие маршруты, прежде чем предлагать новые.
  • Вы видите «узкие места» (god‑классы, общие БД) как перегруженные пересадочные станции.

7. Мыслить картой метро: визуализация безопасных поэтапных маршрутов

В итоге вам нужна единая связная визуализация, которая:

  • Показывает домены и bounded contexts (линии).
  • Показывает интеграции и зависимости (пересечения, пересадочные станции, рельсы).
  • Подсвечивает критичные потоки (маршруты час‑пик).

Используйте эту карту, чтобы планировать:

  • Поэтапные шаги рефакторинга: «Сначала мы изолируем Billing‑контекст от общей таблицы Customer через anti‑corruption layer, а потом вынесем Customer.billingInfo в собственную модель».
  • Снижение рисков: «Эта пересадочная станция (общая БД) — зона повышенного риска. Давайте введём API и постепенно откажемся от прямого доступа к БД».
  • Коммуникацию: «Смотрите, почему полный rewrite сейчас невозможен. Но вот три безопасных маршрута, как поддержать вашу новую модель ценообразования».

Аналоговая карта рефакторинга‑рельсов — это не просто диаграмма; это инструмент коммуникации между инженерией, продуктом и операциями.


Заключение: не вырывайте рельсы — перепроектируйте сеть

Легаси‑код сам по себе не враг; враг — легаси без карты.

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

  • Связать технические изменения с реальными бизнес‑целями.
  • Использовать Clean Architecture и SOLID, чтобы ввести структуру на уровне кода.
  • Применять DDD для проведения осмысленных границ и снижения связности.
  • Совместно моделировать домен, чтобы у всех была общая ментальная карта.
  • Использовать инструменты вроде Context Mapper для формализации и проверки эволюционирующего дизайна.
  • Обратным анализом существующих артефактов понять, с какой системой вы фактически имеете дело.
  • Визуализировать всё это как карту метро, чтобы выбирать безопасные, поэтапные маршруты.

Вам не нужен greenfield‑переписыванием, чтобы модернизировать систему. Вам нужна карта, понятный пункт назначения и дисциплина менять сеть по одной линии, по одной станции, по одной пересадке — пока поезда продолжают ходить.

Аналоговая карта рефакторинга-рельсов: как прокладывать безопасные маршруты через легаси‑код, как по линиям метро | Rain Lag