C4 + Structurizr: как удержать ИИ-код от превращения в спагетти
PrimeCoder · 2026 · формат: tech
Разбор новинки простыми словами: что это, кому нужно и брать ли.
Показывает командам, пишущим код с ИИ, практический способ задать агенту явную карту архитектуры и тем самым сдержать рост техдолга.
Связанные услуги: каталог, AI Boost Team, стать клиентом.
Спагетти вырастает за две недели, а не за два года
Инженерная лаборатория «Микрофабрика» (на Хабре — ZloAlien) выложила разбор того, как команда вытаскивает себя из «ИИ-спагетти». Материал — 9 минут чтения, 710 читателей на момент выгрузки. Интересен он не тем, что кто-то снова пожаловался на качество генерации кода. Интересен он тем, что предложен рабочий контур: описание архитектуры в C4 Model через Structurizr DSL, файл workspace.dsl в каталоге docs/architecture/, рендер диаграмм и экспорт в Mermaid для GitHub.
Команда пишет код в связке с ИИ: DeepSeek Harness и OpenCode, модель Kimi K2.7 Code через провайдеров. Скорость выросла в разы. Вместе с ней вырос и техдолг — только заметили это не сразу, а через несколько недель.
ИИ пишет код быстро, но превращает архитектуру в лапшу за недели.
Механика развала простая и знакомая любому тимлиду. Каждая отдельная правка агента логична. Но правок тысячи, и по отдельности они складываются в дублирование: функция уже есть, модель пишет новую. Модули начинают знать друг о друге лишнее. У функций появляется общее изменяемое состояние, и поведение одной зависит от того, что творится в другом конце проекта. «Временные» решения оседают навсегда. Это обычный технический долг, у которого выросла скорость накопления.
Причина одна. У агента нет структурированного представления об архитектуре.
Весь код в контекст не спасает
Первое возражение звучит логично: дайте модели весь проект в контекст, и вопрос закрыт. Не закрыт. Контекст ограничен, между сессиями памяти нет. И главное — объём не равен пониманию.
ИИ видит функции и классы, но не видит, кто за что отвечает и где границы модулей.
Он читает текст, а не карту. Структура — отдельное представление, и его надо отдать явно.
У людей эта карта обычно живёт на листочке, в голове тимлида, на доске в переговорке или в вики, которая устарела три месяца назад. Иногда её нет вообще — архитектура размазана по коду, и все живут на интуиции. ИИ такое не выдерживает: у модели нет интуиции, есть только тот кусок кода, который попал в окно. Она улучшает его локально и ломает глобально. Каждый раз.
Для собственника или руководителя разработки здесь есть неприятный вывод. Пока архитектура держалась на людях, её распад компенсировался человеческой памятью и разговорами в коридоре. Агент эту компенсацию убирает. Он не спрашивает, куда положить новую функцию.
Почему блоки и стрелочки не выиграли
Дальше напрашивается ход: раз архитектор рисует квадратики со стрелками, давайте и код писать квадратиками. Идея не нова. Блок-схемы, Visual Basic, LabVIEW, Simulink, Scratch, потом low-code и no-code. Список длинный, результат одинаковый — как способ писать код графика проиграла.
Дело не в том, что человек не воспринимает двумерность. Люди прекрасно читают схемы метро и чертежи. Дело в природе графа.
У текста есть тотальный порядок: символы идут друг за другом, и это единственно возможная форма записи. У графа порядок частичный: узлы и рёбра, а раскладок одного и того же графа бесконечно много, и ни одну нельзя объявить канонической. Отсюда практические последствия, которые бьют по команде каждый день.
- Diff. Добавил строку — увидел зелёную. Убрал — красную. В графе вставка узла требует переукладки, и на картинке едут чужие блоки.
- Merge. Два разработчика правят текст — конфликт решается построчно. Два разработчика правят граф — конфликт решается глазами и нервами.
- Поиск и рефакторинг. По тексту работают grep и автоматика. По картинке — нет.
- Логика. Цикл, условие, рекурсия, generics словами записываются компактнее и точнее. Одна строка кода против трёх узлов и обратной связи.
Плюс смешение семантики и расположения. В большинстве визуальных редакторов граф и его координаты лежат в одном файле. Поправил одну связь — поехала вся картинка, а diff показывает мусор вместо смысла.
Вывод, к которому пришла команда: графику надо использовать не для написания кода, а для описания структуры. Показывать то, чего не хватает при текстовом подходе: кто на кого ссылается, где границы модулей, кто за что отвечает. Для этого нужны две вещи — уровни абстракции и разделение смысла и раскладки.
Четыре уровня, чтобы не утонуть
C4 Model — методология описания архитектуры от Саймона Брауна. Название расшифровывается как четыре уровня: Context, Containers, Components, Code. Вместо одной гигантской диаграммы на всю систему — четыре разреза, каждый под свою аудиторию и свою задачу.
| Уровень | Что показывает | Кому смотреть | Как часто трогать |
|---|---|---|---|
| C1 Context | Пользователи системы и внешние системы, с которыми она общается | Заказчик, продукт, новый разработчик | Редко, при выходе на новый контур |
| C2 Containers | Крупные «коробки»: бэкенд, фронтенд, база, кэш, внешние API | Архитектор, тимлид | При архитектурных решениях |
| C3 Components | Бизнес-модули внутри одного контейнера и их ответственность | Команда, ИИ-агент | При появлении нового модуля |
| C4 Code | Классы и методы | Почти никому | Не рисуют: источник правды — сам код |
Ценность здесь не в картинках, а в самих уровнях. Они задают глубину и держат фокус. Смотришь на C3 — видишь взаимодействия компонентов внутри выбранного контейнера и их связи с внешним миром, а не компоненты всех контейнеров сразу. Для агента это ровно то, чего ему не хватало: границы и ответственность в явном виде.
Четвёртый уровень команда фактически не использует, и это правильно. Диаграммы классов устаревают быстрее, чем их успевают отрисовать.
Где Structurizr отличается от draw.io и Mermaid
Рисовать C4 можно в чём угодно. Проблема в том, что рисовалка хранит результат, а не модель. Картинка живёт отдельно от репозитория, устаревает молча и никто не замечает момента, когда она начала врать.
Structurizr устроен иначе, и это ключ ко всей истории. Описание системы пишется на DSL в файле workspace.dsl — там семантика: элементы, связи, границы. Расположение блоков на холсте хранится отдельно, в workspace.json. Смысл и координаты разведены.
Что это даёт на практике:
- Модель лежит в Git рядом с кодом. Правки идут через обычный diff, конфликты решаются как конфликты текста.
- Диаграммы не хранятся как картинки — они рендерятся из модели. Расхождение между описанием и картинкой исчезает по построению.
- Экспорт в Mermaid позволяет выводить схемы прямо в GitHub, в README и в pull request. Разработчик видит карту там, где работает.
- Один и тот же источник даёт несколько уровней — от C1 до C3, без перерисовки вручную.
Для ИИ-агента это удобно именно потому, что DSL — текст. Его можно положить в инструкции, прочитать в начале сессии, использовать как ограничение: новый модуль не создавать, если он попадает в зону ответственности существующего.
Что это дало команде
Единственная цифра эффекта в разборе — про рефакторинг.
Рефакторинг, на который мы закладывали неделю, с его помощью занял один вечер.
Это не бенчмарк и не обещание. Это один эпизод одной команды. Относиться к нему как к гарантии не стоит: у «Микрофабрики» была карта, по которой можно было резать, а у вас её пока нет — её ещё предстоит написать, и вот на это время как раз и уйдёт.
Ценность эпизода в другом. Когда структура описана явно, работа перестаёт быть разговором «а куда это положить» и становится операцией по карте. Человеку это экономит часы. Агенту это заменяет отсутствующую у него память.
Как применить у себя, без героизма
Порядок, который следует из логики разбора:
- C1 и C2 на одном листе. Пользователи, внешние системы, крупные коробки. Полчаса с тимлидом, без перфекционизма.
- Завести
docs/architecture/workspace.dslв репозитории. Не в Confluence, не в Miro. Только рядом с кодом, иначе модель умрёт. - Описать C3 для самого проблемного контейнера. Не для всех сразу. Там, где агент чаще всего дублирует функции и путает ответственность.
- Настроить рендер и экспорт в Mermaid. Схема в pull request читается чаще, чем схема в отдельном каталоге.
- Прописать правило для агента. В инструкциях проекта: перед добавлением модуля сверить с картой. Без этой строчки DSL останется красивым файлом.
Отдельно про дисциплину. Модель живёт, пока её правят вместе с кодом. Появился контейнер — обновили C2. Появился модуль — обновили C3. Пропустили месяц — карта начала врать, и агент начнёт врать вместе с ней, только увереннее.
Подвохи, о которых надо сказать прямо
- Это ещё один артефакт на поддержке. Проблема «вики устарела на три месяца» никуда не делась. Она переехала в DSL. Плюс в том, что здесь устаревание видно в diff.
- Порог входа. Structurizr DSL — не мышкой порисовать. Первый день уйдёт на синтаксис, и это день, который никто не любит.
- Сдерживает, не запрещает. Явная карта снижает вероятность дублирования и протечек через границы модулей. Она не отменяет ревью и не заменяет тесты. Агент по-прежнему способен «улучшить» код локально.
- Доказательств мало. Один проект, одна команда, один эпизод с рефакторингом. Данных, по которым можно считать возврат инвестиций, в разборе нет — и придумывать их не надо.
- Не для всех. Проект на три файла и один разработчик в этом не нуждается. C4 начинает окупаться там, где контейнеров и модулей уже столько, что их не удержать в голове.
Брать или подождать: вердикт за 30 секунд
Брать, если у вас в команде ИИ пишет код каждый день, а архитектура держится на памяти двух человек. Заведите workspace.dsl с C1 и C2, добавьте C3 для худшего контейнера, пропишите правило в инструкциях для агента. Даже это уже даёт эффект.
Подождать, если вы ещё не накопили боли. Один сервис, один разработчик, код без ИИ — заводить DSL рано. Сначала пусть появится то, что нужно держать в структуре.
Не брать как замену ревью, тестов и нормального code review. Карта архитектуры дисциплинирует агента, но не отвечает за качество кода.
FAQ
Чем Structurizr лучше Mermaid?
Mermaid — язык рендера диаграмм. Structurizr — модель: семантика в DSL, раскладка отдельно, из одной модели получаются все уровни C4. Mermaid хорош как способ показать результат в GitHub, поэтому в разборе он и используется для экспорта.
Почему не draw.io?
Потому что draw.io хранит картинку. Картинка не диффится и устаревает незаметно. Модель с текстовым описанием живёт в Git и стареет заметно.
Нужен ли четвёртый уровень C4?
Обычно нет. Классы и методы — источник правды в самом коде, диаграммы этого уровня устаревают быстрее, чем приносят пользу.
Поможет ли это, если команда пишет без ИИ?
Поможет, но мотивация будет слабее. Основной аргумент из разбора — у агента нет своего «листочка» с архитектурой, ему карту нужно отдавать явно.
Сколько времени это занимает?
В разборе нет цифры на внедрение. Есть только про рефакторинг: закладывали неделю, ушёл вечер. Планируйте первый контур как отдельную задачу, а не как «сделаем между делом».
Что сделать на этой неделе
Откройте репозиторий и посмотрите на последние двадцать коммитов от агента. Если среди них есть две функции с одинаковым смыслом и модуль, который знает про внутренности соседнего, — проблема уже есть, просто вы её ещё не считали.
Дальше минимум: каталог docs/architecture/, файл workspace.dsl, C1 и C2, рендер и экспорт в Mermaid, строка в инструкциях для модели. Если после этого рефакторинг займёт вечер вместо недели — считайте, что инструмент окупился. Если нет — у вас появится карта, с которой можно спорить. Это уже лучше, чем лапша, в которой никто не помнит, где чей код.