МАТЕРИАЛЫ КУРСА
СИИ • НАВИГАЦИЯ

aact: архитектуру проверяет машина

Architecture-as-code tools: паттерны, aact check на C4-диаграммах, чтение вердикта, метрики

aact: архитектуру проверяет машина

Диаграмма as-code даёт неожиданный бонус: её можно проверять автоматически, как код линтером. Это делает aact — architecture-as-code tools: CLI и библиотека для валидации, анализа и генерации архитектуры, описанной в PlantUML C4 или Structurizr.

В лабе 2 критерий DoD: npx aact@beta check проходит с 0 violations. Ту же проверку запускает автопроверка на вашем PR.

Быстрый старт

Всё описанное ниже — третья версия, поэтому везде aact@beta (просто npx aact поставит старую v2).

# Создаёт aact.config.ts и стартовый architecture.puml
# с одним умышленным нарушением — чтобы было что чинить
npx aact@beta init

# Покажет нарушение CRUD-правила (orders → orders_db напрямую)
npx aact@beta check

# Авто-фикс: добавит orders_repo как посредника к БД
npx aact@beta check --fix

Дальше правишь architecture.puml под свою систему — синтаксис C4-PlantUML.

Остальные команды:

npx aact@beta check --dry-run    # preview авто-фикса без записи
npx aact@beta analyze            # метрики coupling/cohesion
npx aact@beta model              # нормализованная C4-модель
npx aact@beta view               # live-workbench в браузере
npx aact@beta rule explain crud  # почему правило существует, с примерами
npx aact@beta generate --format plantuml

Скилл для твоего агента

Самая важная для курса команда — установка скилла aact-architect твоему агенту:

npx aact@beta skill install --claude   # или --codex, --cursor, --all

После этого агент знает дисциплину C4 (что является контейнером, а что нет), каталог паттернов с ADR, шаблон ADR и сам гоняет aact check после правок диаграммы. Архитектурный бред агента лечится не абзацем в промпте, а установленным скиллом — это тот же принцип «жёсткие правила держит машина», применённый к самому агенту.

Теги: как aact понимает роли контейнеров

Правила молчат, когда теги расставлены честно:

  • acl — контейнер-адаптер к внешней системе; без него любая связь с System_Ext триггерит правило acl;
  • repo / relay — контейнер, чья единственная работа — владеть базой; без него связь с ContainerDb триггерит crud;
  • async — тег на связи (не на контейнере): помечает асинхронное ребро (очередь, Kafka) для analyze.

Каталог паттернов

Правила aact — это формализованные паттерны проектирования. Полный справочник с ADR и тестами — в репозитории; основные:

ПаттернСуть
Anti-corruption LayerЗа интеграцию с внешними системами отвечают отдельные адаптеры, инкапсулирующие знания о них
Пассивные CRUD-сервисыСервисы доступа к мастер-данным не имеют лишней логики и зависят только от своей БД
API-GatewayВнешние REST-вызовы не идут в сервисы напрямую
Database per serviceК базе имеет доступ только один сервис
Stable DependenciesЗависимости направлены от менее стабильных модулей к более стабильным
Acyclic DependenciesГраф зависимостей без циклов
Cohesion > CouplingСвязность внутри границы выше связанности с внешним
Common ReuseИспользуешь часть модуля — зависишь от части, а не от всего

Конфиг — с обоснованиями, не по умолчанию

Конфиг лежит рядом с диаграммой. Живой пример боевого aact.config.ts:

export default defineConfig({
  source: { type: "plantuml", path: "./c4-container.puml" },
  rules: {
    // Включено: релевантно нашей архитектуре
    acyclic: true,            // без циклических зависимостей
    cohesion: true,           // границы: внутренних связей больше, чем внешних
    stableDependencies: true, // зависимости направлены к стабильным модулям
    commonReuse: true,        // Common Reuse Principle

    // Выключено: неприменимои написано почему
    acl: false,          // людивнешние актёры, не контейнеры
    dbPerService: false, // Redis осознанно разделён между app и worker
    apiGateway: false,   // нет API-гейтвея в PoC
  },
});

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

Как читать вердикт

Правило сработало — значит диаграмма (или архитектура) врёт:

ПравилоЧто ловитЧто чинить
acyclicЦиклы зависимостей: A → B → AВыдели общую часть в третий модуль или переверни связь
cohesionУ границы больше внешних связей, чем внутреннихГраница нарезана не там: перенеси компонент или объедини границы
stableDependenciesСтабильный модуль зависит от часто меняющегосяИнвертируй зависимость или признай модуль нестабильным
commonReuseМодуль тянет то, что использует наполовинуРазбей модуль
dbPerServiceК одной БД ходят несколько сервисовВыдели сервис-владелец данных
aclПрямая интеграция с внешней системойДобавь адаптер-прослойку

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

Метрики: aact analyze

analyze считает связность и даёт цифры для отчёта: количество элементов, синхронные вызовы, cohesion границ. Пример вывода боевой системы: 10 элементов, 9 sync-вызовов, cohesion 2/5, 0 violations. Эти цифры — хорошая строчка в README проекта и в блоке «почему нам можно верить» на Demo Day.