The Jerusalem PostTrump's foreign policy threatens Republicans in midterms as war, tariffs push costs up - analysisCNN Türkİstanbul’dan Muş’a uzaktan ameliyat: Türkiye’de bir ilkPunchNigerians who don’t see progress need ‘Tinubu eyeglasses’ – Remi TinubuInquirer3 fishermen rescued after boat partially sinks off Palawan islandInquirer EntertainmentApl.de.ap says new EP is a ‘shoutout’ to leaders to care for the PhilippinesESPNTransfer rumors, news: Chelsea, Bayern, Barcelona battle for Brighton defenderZDF heuteEntdecken Sie das ZDF-NachrichtenstudioColliderChristopher Nolan's Best Crime Thriller Officially Leaves NetflixSouth China Morning PostThousands evacuated and flights grounded as Typhoon Champi hits eastern China01net« Les écrans tactiles pires que l’alcool au volant » : cette étude choc pointe du doigt les véhicules modernesالنهارمعبر الشيب بين العراق وإيران... لماذا أُغلق وما أهميته؟HipertextualCon este simple truco de Windows, olvídate de volver a “perder” el puntero del mouse
The Daily Newsstand · Free, Always
Saturday, October 24, 2026

Борьба с ИИ-спагетти: C4 + Structurizr

Translate

ИИ пишет код быстро, но за недели превращает проект в спагетти. Мы (инженерная лаборатория «Микрофабрика») попробовали решить это с помощью C4 Model и Structurizr DSL - и получили рабочий инструмент, который помогает и людям, и ИИ-агентам удерживать структуру проекта. Рефакторинг, на который мы закладывали неделю, с его помощью занял один вечер. В статье - что такое C4, почему графическое программирование не спасает, почему Structurizr не просто «ещё один рендерер диаграмм», и как всё это работает на практике.

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

Проблема: ИИ пишет быстро, но не думает об архитектуре

Мы пишем код в связке с ИИ (работаем через DeepSeek Harness и OpenCode; модель Kimi K2.7 Code через провайдеров). Это ускоряет разработку в разы. Но есть и негативный эффект, который проявляется не сразу, а через несколько недель работы.

Каждая правка кода, которую выполняет ИИ, как правило, логична. Но когда таких правок тысячи, архитектура разваливается. Возникает дублирование кода: ИИ не видит, что нужная функция уже есть, и пишет новую. Модули начинают знать друг о друге лишнее - нарушается инкапсуляция. Функции обрастают скрытыми зависимостями, у них появляется общее изменяемое состояние: их поведение зависит от того, что происходит в другом месте. Появляются «временные» решения, которые никто не убирает. В целом это классический технический долг, вот только растёт он гораздо быстрее, чем при работе человека, поскольку ИИ вносит правки быстрее.

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

Можно возразить: а почему просто не дать ИИ весь код в контекст? Контекст ограничен, между сессиями памяти нет, но главное - даже имея весь код, ИИ не выделяет из него структуру. Он видит текст, а не карту. Структура - это отдельное представление, и его надо дать явно.

У людей архитектура живёт на листочке бумаги, у тимлида в голове, на доске в переговорке, в вики (которая устарела три месяца назад). А иногда архитектуры вообще нет - она размазана по коду. ИИ в этом смысле обнажает проблему: он не держит в голове общую картину, у него нет этого «листочка». На каждой правке он видит только тот кусок кода, на который ему указали или который он сам определил как ключевой, и «улучшает» его локально, но при этом ломает структуру глобально.

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

Почему графическое программирование не помогло

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

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

Закономерно возникла идея записывать программу как граф - блоками и стрелочками. Получаем наглядную структуру, на которой видны связи элементов программы. Идея получила развитие: блок-схемы, Visual Basic, LabVIEW, Simulink, Scratch, а теперь ещё Low-code и No-code. Список длинный, но у всех этих подходов одна и та же проблема - графы плохо масштабируются.

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

Иногда говорят, что текст «одномерен», а граф «двумерен». Но настоящая разница не в размерности. Текст - это тотальный порядок (последовательность символов), а граф - частичный порядок (узлы и рёбра). У текста есть каноническая линейная форма, у графа её нет. Один и тот же граф можно разложить бесконечно многими способами, и ни один нельзя назвать единственно правильным.

Из этого следуют вполне практические последствия. Diff текста читается глазами: добавил строку - увидел зелёную, убрал - красную. Изменение локальное, и diff локальный. В графе так не получится: вставка узла требует переукладки, и на картинке едут чужие узлы. Даже идеальный алгоритм сопоставления не спасёт - задача сопоставления графов в общем случае принципиально тяжёлая, а человек, глядя на две картинки, всё равно не поймёт, что именно изменилось. Поэтому текст диффится, мержится, ищется и рефакторится, а граф - нет.

Проблему усугубляет смешение семантики и расположения. В большинстве визуальных редакторов граф и его расположение хранятся вместе. Изменил одну связь - поехала вся картинка, а git diff показывает мусор вместо смысла.

И наконец, графика плохо описывает алгоритмическую логику. Циклы, условия, рекурсия, generics - всё это словами точнее и компактнее, чем мышкой. for i in range(n) - одна строка; тот же цикл в узлах - это узел-счётчик, узел-условие, тело, обратная связь.

Вывод: графическое программирование проиграло как способ писать код. Но оно позволяет смотреть на код под другим углом - описывать структуру программы графикой. Отображать то, чего не хватает при обычном «текстовом» подходе: кто на кого ссылается, где границы модулей, кто за что отвечает. Но для этого нужны две вещи: иерархическое представление (уровни абстракции) и разделение семантики и расположения блоков.

C4 Model: четыре уровня, чтобы не утонуть

Оказалось, что мы не первые, кто задумывался над этой проблемой. Есть C4 Model - методология описания архитектуры от Саймона Брауна. Название - аббревиатура от четырёх уровней: Context, Containers, Components, Code. Идея простая: описывать систему не одной гигантской диаграммой, а четырьмя уровнями абстракции.

  • C1 - System Context. Кто пользователи системы? С какими внешними системами она общается? Уровень «для заказчика», где не нужно объяснять код.

  • C2 - Containers. Из каких высокоуровневых «коробок» состоит система: бэкенд, фронтенд, база данных, кэш, внешние API. Уровень архитектурных решений.

  • C3 - Components. Что внутри конкретного контейнера: какие бизнес-модули и за что каждый отвечает.

  • C4 - Code. Классы и методы. Этот уровень в C4 рисуют редко: источник правды здесь - сам код, а диаграммы классов быстро устаревают.

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

Structurizr: почему не draw.io и не Mermaid

Для работы с C4 нам нужен инструмент, который удовлетворяет требованиям:

  • диаграммы как код: у диаграмм есть текстовое представление, которое можно хранить в Git;

  • разделение семантики и расположения блоков: связи описываются отдельно от координат блоков;

  • иерархическое представление: нативная поддержка уровней C4, а не плоский граф.

Structurizr - это инструмент, который написал тот же человек, что придумал C4 - Саймон Браун. И это принципиально важно - когда методологию и инструмент создаёт один человек, между ними нет зазора в понимании. Structurizr не «поддерживает C4 как одну из диаграмм» - его DSL и есть C4.

В проекте мы создаём директорию docs/architecture/ со следующей структурой:

docs/architecture/
├── workspace.dsl         ← семантика (git-friendly, текстовый файл)
├── workspace.json        ← расположение блоков + состояние редактора
└── mermaid/              ← для GitHub-рендеринга

workspace.dsl - это файл на Structurizr DSL. В нём описываются элементы и связи между ними. Никаких координат, никакого «поставь эту коробочку слева, а эту - справа». Только смысл.

Пример (сокращённый):

workspace "URL Shortener" "Example microservices architecture" {
    model {
        user = person "User" "Creates short links and views stats"

        urlShortener = softwareSystem "URL Shortener" "Shortens URLs" {
            apiGateway = container "API Gateway" "Go" "Reverse proxy to services"
            postgres = container "PostgreSQL" "PostgreSQL 16" "Storage"
            redis = container "Redis" "Redis 7" "Cache"

            linkService = container "Link Service" "Go" "CRUD links" {
                linkHandler = component "Link Handler" "Go" "HTTP handlers"
                linkRepo = component "Link Repository" "Go" "DB access"

                linkHandler -> linkRepo "Reads/Writes"
            }

            user -> apiGateway "Uses"
            apiGateway -> linkService "REST API"
        }
    }

    views {
        systemContext urlShortener "SystemContext" {
            include *
            autolayout lr
        }
        container urlShortener "Containers" {
            include *
            autolayout lr
        }
    }
}

Сохранили файл - Structurizr перерисовал диаграммы. Изменили связь в DSL - картинка обновилась. А ручное расположение блоков, которое вы задали мышкой в интерфейсе Structurizr, сохранилось: оно лежит в workspace.json и не теряется при следующем рендере.

Вот в этом и отличие от альтернатив. draw.io даёт полный контроль над расположением, но смешивает семантику и координаты в одном файле: git diff показывает мусор. Mermaid вообще не хранит расположение элементов, поэтому оно нестабильно: при каждом рендере картинка перестраивается заново, и блоки прыгают. Structurizr разделяет их: семантика в workspace.dsl, расположение в workspace.json.

Таким образом, если вы хотите описывать архитектуру продукта - используйте Structurizr. А если вам понадобится вставить диаграмму связей в README - экспортируйте её в Mermaid.

Как мы это используем

Мы попробовали разные способы работы со Structurizr и в итоге пришли к тому, что запускаем Structurizr в Docker и просто смотрим диаграммы локально в браузере:

cd docs/architecture

# Сгенерировать workspace.json из DSL
structurizr export -workspace workspace.dsl -format json -output .

# Запустить локальный веб-сервер
docker run -it --rm -p 8080:8080 \
  -v "$(pwd):/usr/local/structurizr" \
  structurizr/structurizr local

# Открыть http://localhost:8080/workspace/1/diagrams

Диаграммы обновляются при каждом сохранении workspace.dsl. Расположение блоков сохраняется в workspace.json, который тоже коммитится в Git. Если файла workspace.json ещё нет, Structurizr создаст его сам при старте. Плюс в браузере есть навигация между уровнями - можно щёлкать по элементам и проваливаться в содержимое.

От автоматической генерации PNG/SVG отказались - статичные файлы проигрывают живым диаграммам: в браузере они обновляются на лету. Плюс ко всему старый structurizr-cli из AUR (Arch Linux) не умеет рендерить PNG/SVG - он умеет только текстовые экспорты (PlantUML, Mermaid, JSON, DOT). Технически картинки можно получить связкой Structurizr + Puppeteer (headless Chromium), но это отдельный пайплайн, и ради статичных файлов мы его не держим.

Mermaid-экспорт для GitHub тоже не держим. Диаграмма и так живёт в workspace.dsl - её в любой момент можно открыть в Structurizr. А Mermaid-файл в репозитории - это статичный снимок, который устареет на следующей правке и начнёт врать. Если понадобится показать диаграмму в README, экспорт делается одной командой.

Что в итоге:

Планировали

Реально используем

Единый DSL как источник правды

✅ Да, постоянно

C4 для рефакторинга архитектуры

✅ Да, главный кейс

Локальный Structurizr для просмотра

✅ Да, каждый раз

Автогенерацию PNG в CI

❌ Нет, в браузере удобнее смотреть, плюс есть навигация между слоями

Mermaid-экспорт для GitHub

❌ Нет, разве что для README

C4 для мелких правок

❌ Нет, не детализировали уровень «Code»

Пример из практики: как C4 спас рефакторинг

Мы работаем над проектом «Трафаретка» - сервис, который позволяет заказать бумажный трафарет по вашему изображению (картинка превращается в полутон из точек, поэтому трафарет масштабируется - хоть на всю стену). Загружаешь картинку, настраиваешь преобразование в полутон, указываешь адрес - и через какое-то время получаешь готовый трафарет.

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

Мы сгенерировали workspace.dsl как снимок текущего состояния - не чтобы дальше генерировать его на каждой правке, а чтобы один раз увидеть картину целиком. Посмотрели на диаграмму - и стало видно, где что должно жить. Рефакторинг занял один вечер вместо недели, которую мы на него закладывали. Без диаграммы это был бы долгий разговор «а кто за что отвечает», с диаграммой - решение нашлось за один обзор экрана.

Но C4 - не серебряная пуля. Диаграмма показывает структуру, а не поток данных: у нас был случай, когда стрелка «Editor → Order» на диаграмме есть, а параметр marginHorizontalMm не сохранялся в состоянии. Баг вылез только в runtime. Тесты и логи C4 не заменяет.

Сама «Трафаретка» сейчас в тестовом режиме: весь путь пользователя можно пройти от начала до конца, но реальные заказы пока не исполняются. Если хотите попробовать: https://trafaretka.website.yandexcloud.net/

C4 и ИИ: главное, зачем это всё

Когда ИИ-агент работает с проектом, у него нет общей картины: он видит только тот код, который ему дали.

C4-модель эту картину даёт. Она позволяет описать архитектуру системы, а Structurizr - сохранить описание в файл workspace.dsl. Это не «весь код в контексте», а компактная модель с явными границами между модулями. Теперь ИИ увидит, что Order отвечает за данные заказа, а не за отрисовку. Что логика переходов живёт в Coordinator, а не размазана по обработчикам кнопок. Что Frame Geometry - отдельная сущность, а не набор магических чисел в коде.

Чтобы ИИ нашёл эту карту, нужна точка входа - AGENTS.md в корне репозитория. Файл с правилами: как запускать проект, какой стиль кода, где посмотреть архитектуру. ИИ читает его и перестаёт гадать. Это де-факто стандарт, поддерживается в Cursor, OpenCode и других средах. И в этом же файле стоит записать правила работы с архитектурой - чтобы ИИ их не забывал:

  • Меняешь архитектуру - обновляй workspace.dsl. Иначе диаграмма врёт.

  • C4 не заменяет тесты, логи и внимательность.

  • C4 - не для мелких правок: для CSS и рефакторинга одной функции он не нужен.

Заключение

Мы начинали эту историю с простой боли: ИИ пишет код быстро, но за недели превращает проект в кашу. А закончили тем, что нашли ту самую «цифровую версию листочка» - файл workspace.dsl в репозитории, который видит и человек, и ИИ-агент.

Главный вывод: графическое программирование проиграло как способ писать код, но нашло свою нишу - описывать структуру. C4 Model + Structurizr DSL - это не «ещё один инструмент для диаграмм», а способ удержать архитектуру в проекте, где код генерируется быстрее, чем вы успеваете его читать.

Мы тоже ещё в процессе: продолжаем осваивать Structurizr и улучшать подход к коду с ИИ. Но даже в таком виде это уже экономит время. Если работаете с ИИ - попробуйте: один файл workspace.dsl, AGENTS.md с правилами, две команды для запуска. Дальше Structurizr сам покажет, что у вас в проекте творится. У нас на «Трафаретке» это заняло один вечер - и сэкономило неделю рефакторинга.

А как вы работаете с архитектурой проекта? 😎

Больше заметок про инженерные эксперименты, ЧПУ, ИИ и DevOps - в нашем сообществе во ВКонтакте: https://vk.ru/microfabrica.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.