Rain Lag

Аналоговый город-рефакторинг: как зонировать кодовую базу по законам градостроительства, прежде чем добавить ещё одну фичу

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

Аналоговый город-рефакторинг: как зонировать кодовую базу по законам градостроительства, прежде чем добавить ещё одну фичу

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

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

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

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


1. Ваша кодовая база — это город, а не головоломка

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

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

Городская метафора помогает по‑другому смотреть на рефакторинг:

  • Районы (districts): функциональные зоны, модули, сервисы.
  • Улицы и магистрали: вызовы функций, очереди сообщений, API, data pipelines.
  • Коммунальные службы: логирование, мониторинг, конфигурация, системы сборки, CI/CD‑пайплайны.
  • Правила зонирования: архитектурные гайды, код‑стандарты, правила зависимостей.

Перед тем как построить ещё одно «здание» (фичу), спросите: где ему место в этом городе и какая инфраструктура ему понадобится?


2. Зонирование: обозначьте границы до того, как строить

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

С кодовой базой можно сделать то же самое.

Определите районы в системе

Даже в запущенном легаси‑монолите можно обнаружить и обозначить фактические районы:

  • Презентационный район: UI‑шаблоны, контроллеры, API‑обработчики.
  • Доменный район: бизнес‑правила, ядро предметной области, сущности, value objects.
  • Инфраструктурный район: доступ к базе данных, внешние API, очереди/сообщения, файловая система.

При этом легко обнаружить:

  • Контроллеры, которые из произвольных мест напрямую ходят в базу.
  • Бизнес‑логику, спрятанную во view‑слой.
  • Утилитарные классы, которые используются как «многофункциональные небоскрёбы» под всё подряд.

Вместо Big Bang‑переписывания начните с границ зонирования:

  • «Новая бизнес‑логика должна жить в доменном слое».
  • «Контроллеры могут зависеть от доменных сервисов, но не ходят напрямую в базу».
  • «Инфраструктурные детали не должны протекать в доменные объекты».

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

Зонирование — это про контроль, а не про идеал

Город не станет чистым и аккуратным мгновенно. Но зонирование даёт возможность:

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

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


3. Градостроительство междисциплинарно — таким же должен быть рефакторинг

Градостроительство — это не просто красивые карты. Оно соединяет в себе:

  • Архитектуру (какими должны быть здания?)
  • Строительство и инженерку (выдержат ли мосты?)
  • Социологию (как люди реально используют город?)
  • Политику и экономику (что мы можем себе позволить? кого это затронет?)

С рефакторингом кодовой базы всё так же:

  • Архитектура: какие должны быть модульные границы и слоистость?
  • Инженерия: что технически возможно при текущих зависимостях и ограничениях рантайма?
  • Дизайн и UX: как изменения повлияют на пользовательские сценарии, юзабилити и паттерны дефектов?
  • Социальные факторы: как работают ваши команды? кто за что отвечает? где ломаются передачи задач?

Если вы нарисуете «идеальную» архитектуру, игнорируя то, как реально работают разработчики, QA и ops/SRE, ваш план зонирования провалится. Люди начнут его обходить.

Вместо этого:

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

Относитесь к этим участникам как к жителям вашего кода‑города, а не как к пассивным получателям сверху спущенных планов.


4. Изучите уличную сеть, прежде чем перестраивать город

Планировщики не сносят магистраль «по ощущениям». Они анализируют трафик, использование земли и потоки пешеходов.

Ваш аналог — это граф зависимостей — «уличная сеть» вашего кода‑города.

Картографируйте зависимости

Минимально важно понимать:

  • Какие модули зависят от каких других модулей?
  • Какие сервисы вызывают какие API или пишут в какие топики/очереди?
  • Где есть плотные циклические зависимости?

Инструменты (static analysis, архитектурные диаграммы, визуализаторы call graph’ов) помогают, но даже грубая схема, нарисованная вручную, лучше, чем чистая интуиция.

Ищите:

  • Магистрали: базовые сервисы или библиотеки, в которые ходят все.
  • Узкие места: классы или модули с огромным числом зависимых от них компонентов.
  • Незаконные «срезы»: низкоуровневые модули, зависящие от высокоуровневых, пересекающие задуманную слоистость.

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

Когда карта перед глазами, можно планировать как городской инженер:

  • Снимать нагрузку с узких мест, вынося наружу стабильные интерфейсы.
  • Создавать объездные дороги (facade’ы или anti‑corruption layers), которые изолируют «грязные» районы.
  • Закрывать опасные сквозные проезды (запретить некоторые сквозные зависимости, добавить линтеры/проверки архитектуры).

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


5. Осторожно: современные build‑системы в разросшемся городе

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

Если ваш граф зависимостей — переплетённый ком, добавление быстрой «умной» build‑системы не решит проблему — она просто сделает глобальные пересборки быстрее и болезненнее.

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

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

Когда всё зависит от всего:

  • Мелкие изменения в коде выглядят как затрагивающие огромную часть системы.
  • Инструменты сборки по‑консервативному пересобирают колоссальные объёмы кода.
  • Время CI растёт, и рефакторинг с эксперименатми становятся дорогими.

Вместо того чтобы винить build‑систему, исправляйте генплан города:

  • Вводите чёткие границы модулей и слоёв.
  • Минимизируйте перекрёстные вызовы между районами.
  • Двигайтесь к чётким интерфейсам и инверсии зависимостей.

Только упростив планировку города, вы начнёте получать реальную отдачу от современных build‑систем: инкрементальные сборки, параллелизацию и надёжное кеширование.


6. Отдавайте предпочтение «ямочному ремонту» вместо героических бульдозеров

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

В терминах софта: героический полный rewrite.

Реальность:

  • Полные переписывания рискованны, дороги и часто не доходят до feature parity.
  • Бизнес‑задачи не ставятся на паузу, пока вы рисуете новую карту.
  • Теряется накопленная в легаси‑системе экспертиза и обработка редких краевых случаев.

Градостроители обычно работают вокруг уже существующего:

  • Прокладывают новые улицы.
  • Перезонируют отдельные кварталы.
  • Меняют коммуникации квартал за кварталом.

С кодовой базой можно делать то же.

Паттерны поэтапного рефакторинга

  • Strangler Fig pattern: оборачиваете старый функционал новым интерфейсом; часть трафика переводите на новую реализацию, постепенно расширяя её, пока старый код не станет ненужным.
  • Anti‑corruption layer: ставите границу вокруг легаси‑модулей, переводя данные между старой и новой моделями, чтобы остальная система не заражалась легаси‑ограничениями.
  • Правило бойскаута (Boy Scout Rule): при каждом касании файла оставляйте его чуть лучше: улучшите имена, выделите функцию, добавьте тест, переместите логику в правильный «район».

Думайте в категориях:

«Что я могу безопасно перезонировать на этом квартале сегодня?», а не «Как мне перестроить весь город?»

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


7. Вовлекайте жителей: общие правила, а не тайный мастер‑план

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

Чтобы рефакторинг прижился, вовлекайте «жителей» и закрепляйте привычки.

Сделайте правила зонирования явными

  • Пишите короткие Architecture Decision Records (ADR) для ключевых границ: «UI зависит от домена, домен — чистый, инфраструктура — заменяемая».
  • Создайте лёгкие чек‑листы для code review, подчёркивающие границы: «Соблюдает ли новый код слоистость?», «Не утекают ли инфраструктурные детали в домен?»
  • Там, где возможно, добавьте линтеры и автоматические проверки модульных границ.

Советуйтесь с теми, кто делает работу

  • Спросите разработчиков: Где изменения ощущаются куда рискованнее, чем должны быть? Это часто «плохие перекрёстки» или места, где не хватает границ.
  • Спросите QA: Какие области особенно хрупкие и требуют тотальной регрессии? Это признаки того, что зонирование не работает и локальные изменения имеют глобальный эффект.
  • Спросите ops/SRE: Какие сервисы или модули доставляют больше всего проблем в проде? Это ваши перегруженные коммуникации и хлипкие мосты.

Когда люди видят, что планы по рефакторингу соответствуют их реальному опыту работы с системой, они куда охотнее соблюдают новые «строительные нормы».


8. Сводим всё вместе, прежде чем добавить следующую фичу

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

  1. Нарисуйте карту города

    • Определите основные районы (UI, домен, инфраструктура, кросс‑срезы и т.п.).
    • Визуализируйте ключевые зависимости и пути вызовов.
  2. Определите или уточните зонирование

    • Решите, какой код где должен жить.
    • Запишите простые, исполнимые правила для нового кода.
  3. Спланируйте инфраструктурные улучшения

    • Сначала разгребите самые жёсткие узкие места и запутанные развязки.
    • Введите фасады или anti‑corruption layers вокруг особо грязных зон.
  4. Релизьте фичи «дружественно городу»

    • Размещайте новые фичи в подходящих районах, соблюдая границы.
    • Используйте поэтапные паттерны (strangler, boy scout), улучшая то, к чему прикасаетесь.
  5. Вовлекайте жителей

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

Заключение: постройте город, в котором можно жить

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

Относясь к легаси‑кодовой базе как к городу, а к рефакторингу — как к градостроительству, вы:

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

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

Вы можете ответить: «Да — но давайте сначала посмотрим на карту зонирования».

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

Аналоговый город-рефакторинг: как зонировать кодовую базу по законам градостроительства, прежде чем добавить ещё одну фичу | Rain Lag