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.