Зачем это нужно
В уроках 3.1 и 3.2 мы разобрали две вещи: architecture задает границы решений, а ADR фиксирует важные choices и trade-offs. Теперь нужно сделать следующий шаг: превратить эти решения в constraints, которые реально работают в agent workflow.
Если architecture rule существует только как фраза в документе, агент может ее не увидеть или забыть в длинном контексте. Если rule превращена в project instruction, task constraint, review checklist, static check или test, она начинает ограничивать поведение системы.
Главная идея урока: критичные architecture constraints должны быть не просьбой к LLM, а частью инженерного контура проверки.
Основная идея
Architecture constraint - это проверяемое ограничение на структуру или зависимости системы.
Пример:
Controllers must not access database directly.
В учебной архитектуре курса это означает:
controllers
↓
services
↓
repositories
↓
database
Запрещено:
controller -> database
Для agentic development одного текста "не делай так" мало. Constraint должен появляться в нескольких местах:
Architecture docs
+
Project rules
+
Task constraints
+
Static checks or tests
+
Review checklist
Так один принцип становится частью процесса, а не надеждой на память агента.
Ключевые термины
| Термин | Значение |
|---|---|
| Architecture Constraint | Ограничение на структуру, зависимости, ownership или способ реализации. |
| Allowed Dependency | Разрешенное направление зависимости. |
| Forbidden Dependency | Запрещенный shortcut или coupling. |
| Project Rule | Короткое стабильное правило, доступное агенту в каждом relevant run. |
| Static Check | Автоматическая проверка структуры кода без запуска продукта. |
| Architecture Test | Тест, проверяющий dependency boundaries или module rules. |
| Review Checklist | Список вопросов для human или reviewer agent. |
| Enforcement | Механизм, который делает нарушение заметным или невозможным. |
От решения к constraint
Архитектурное решение само по себе не всегда операционально.
ADR:
Используем layered architecture:
Controller -> Service -> Repository -> Database.
Constraint:
Controller files must not import database client or repository directly.
Проверяемый вариант:
No file matching src/**/controllers/** may import:
- database client
- ORM model
- repository implementation
Чем конкретнее constraint, тем проще:
- дать его агенту;
- проверить diff;
- автоматизировать lint/static check;
- включить в task acceptance.
Схема enforcement layers
Идея не в том, чтобы все автоматизировать сразу. Идея в том, чтобы важные constraints не жили только в одном prompt.
Allowed и forbidden dependencies
Для агента полезнее всего явно видеть both sides: что можно и что нельзя.
Пример для backend:
Allowed:
- controllers -> services
- services -> repositories
- services -> external service interfaces
- repositories -> database client
Forbidden:
- controllers -> database client
- controllers -> repositories
- repositories -> HTTP request handlers
- domain logic -> framework-specific request objects
Пример для frontend:
Allowed:
- pages/routes -> feature components
- feature components -> shared UI components
- feature hooks -> API client
Forbidden:
- shared UI -> feature-specific API client
- components -> direct localStorage auth token mutation
- UI -> backend database schema assumptions
Forbidden list не должен быть бесконечным. Он должен фиксировать наиболее опасные shortcuts.
Constraint в разных артефактах
Возьмем правило:
Controller не должен обращаться к database напрямую.
В architecture docs
## Layering
HTTP controllers are responsible for request parsing,
response formatting and calling application services.
Controllers must not import database client, ORM models
or repositories directly.
В project rules
When editing backend controllers:
- do not import database client;
- do not import repository implementations;
- call application services instead.
Project rules должны быть короткими. Не надо копировать весь architecture document в rules.
В Agent Task
Constraints:
- Allowed scope: src/auth/auth.controller.ts, tests/auth/auth.controller.test.ts
- Do not import database client in controller.
- Use AuthService for business logic.
В static check
Идея проверки:
Fail if any src/**/controller* imports db/client.
Это может быть реализовано lint rule, dependency-cruiser, import linter, custom script или language-specific analyzer. В этом курсе важна сама модель, а не конкретный инструмент.
В review checklist
[ ] Controller does not access database directly
[ ] Business logic stays in service layer
[ ] Repository owns persistence logic
[ ] No forbidden dependency introduced
Reviewer agent должен видеть этот checklist вместе с diff.
Хорошие и плохие constraints
| Плохо | Лучше |
|---|---|
| Следуй хорошей архитектуре | Controllers must call services, not repositories/database |
| Не делай грязный код | Do not add business logic to route handlers |
| Используй существующие подходы | Follow existing AuthService -> ResetTokenRepository pattern |
| Не ломай API | Do not change response shape of /api/login without explicit approval |
| Сделай безопасно | Do not store raw reset tokens; follow ADR-001 |
Хороший constraint:
- короткий;
- стабильный;
- применим к конкретному scope;
- проверяем review'ом или инструментом;
- не требует читать мысли автора.
Architecture constraints для Password Reset
Пример constraints, которые можно добавить в specs/password-reset/design.md или task files:
ACON-001:
AuthController handles HTTP request/response only.
It must call AuthService for password reset behavior.
ACON-002:
Reset token persistence belongs to ResetTokenRepository.
AuthService must not use database client directly.
ACON-003:
Raw reset token must never be stored.
Follow ADR-001 Password Reset Token Storage.
ACON-004:
Email sending must go through existing EmailService.
Do not import provider SDK from Auth module.
ACON-005:
Audit events must be emitted through AuditLog service.
Do not write audit records directly from controller.
Эти constraints можно использовать в tasks:
TASK AUTH-004:
Add request password reset endpoint.
Relevant constraints:
- ACON-001
- ACON-003
- ACON-004
- ACON-005
Теперь agent task получает архитектурные границы, а reviewer может проверить diff против них.
Constraints и verification
Не все architecture constraints легко автоматизировать. Но каждый constraint должен иметь хотя бы один способ проверки.
| Constraint | Способ проверки |
|---|---|
| Controller не импортирует database client | Static import check |
| Service использует repository interface | Code review или architecture test |
| Raw token не хранится | Unit/integration test + review |
| Email provider SDK только в Email module | Static import check |
| API contract не меняется | Contract/integration tests |
| Audit event пишется | Integration test или audit log assertion |
Если constraint невозможно проверить вообще, он слишком абстрактный.
Практика: превратить rule в working constraint
Возьмите правило:
Controllers must not access database directly.
Создайте документ:
docs/architecture/constraints.md
Опишите constraint в пяти формах:
## Architecture doc version
## Agent project rule
## Agent task constraint
## Static check idea
## Review checklist item
Минимальные требования:
- constraint должен быть сформулирован как allowed/forbidden behavior;
- должна быть указана область применения;
- должен быть хотя бы один automatic или semi-automatic verification method;
- должен быть пример нарушения;
- должен быть пример правильного решения.
Когда constraint должен стать project rule
Не каждый architecture note нужно добавлять в always-on rules. Rules должны быть короткими и стабильными.
Добавляйте constraint в project rules, если он:
- часто применяется;
- нарушение дорого стоит;
- легко формулируется кратко;
- не зависит от одной временной фичи;
- должен быть известен агенту до чтения feature docs.
Не добавляйте в project rules:
- длинные объяснения истории решения;
- временные ограничения конкретной task;
- подробные API contracts;
- большой список edge cases;
- unstable product requirements.
Хороший pattern:
PROJECT RULE:
Controllers call services; they must not import database client directly.
REFERENCE:
For details see docs/architecture/constraints.md.
Типичные ошибки
Ошибка 1. Оставлять constraint только в prompt
Prompt живет один run. Architecture constraint должен жить в source of truth и попадать в проверки.
Ошибка 2. Писать непроверяемые правила
Фраза "сохраняй чистую архитектуру" слишком расплывчата. Нужны конкретные imports, layers и responsibilities.
Ошибка 3. Перегружать project rules
Если rules становятся энциклопедией, агент начинает их хуже использовать. Короткие stable constraints работают лучше.
Ошибка 4. Не связывать ADR с constraints
ADR объясняет decision. Constraint применяет decision. Если связи нет, решение не влияет на agent tasks.
Ошибка 5. Проверять architecture только после большого diff
Чем раньше constraint попадает в task, тем меньше вероятность дорогого rewrite.
Критерии готовности
После урока студент должен уметь:
- сформулировать architecture constraint как allowed/forbidden dependency;
- превратить architecture decision в project rule, task constraint и review checklist;
- предложить static check или architecture test idea;
- объяснить, какие constraints должны быть always-on;
- связать ADR с concrete constraints;
- подготовить constraints для Password Reset tasks.
Краткое резюме
Architecture constraints превращают архитектуру из документа в рабочий механизм контроля.
Один важный constraint должен быть виден в нескольких местах:
ADR / docs
↓
project rules
↓
task constraints
↓
static checks / tests
↓
review checklist
Для AI Agent Development это критично: агент не должен просто "помнить хорошую архитектуру". Он должен работать внутри явных границ, а нарушение этих границ должно быть заметно.
Вопросы для самопроверки
- Чем architecture constraint отличается от architecture decision?
- Почему forbidden dependencies нужно описывать явно?
- Как проверить constraint "controller не ходит в database"?
- Какие constraints стоит добавлять в project rules?
- Почему ADR должен быть связан с task constraints и review checklist?
Что дальше
Модуль III показал, как ограничить пространство решений агента архитектурой. В следующем модуле мы перейдем к Planning и Decomposition: научимся превращать approved spec и architecture constraints в граф маленьких Agent Tasks с goal, inputs, allowed scope, acceptance criteria и verification.