Как собрать BPMN, UML, ERD, C4 и API в одну проектную документацию
После знакомства с BPMN, UML, ERD, State Machine, DFD, C4 и API Contracts возникает следующая проблема.
Каждый инструмент по отдельности понятен, но непонятно, как использовать их вместе.
Можно нарисовать:
- BPMN бизнес-процесса;
- ERD базы данных;
- несколько UML-диаграмм;
- C4 архитектуры;
- OpenAPI;
- DFD;
- State Machine.
Но если эти документы существуют независимо друг от друга, проектная документация быстро превращается в набор схем, между которыми нет явной связи.
В хорошей документации должно быть понятно не только:
Как выглядит каждая модель?
но и:
Как требование проходит путь от бизнес-процесса до конкретного API, данных и архитектурных компонентов?
Для одной функции системы этот путь может выглядеть так:
Бизнес-процесс -> требование -> сущности и состояния -> API -> runtime interaction -> архитектурные компоненты -> физическая реализация
Разные модели описывают разные участки этого пути.
Главная задача проектной документации - не создать как можно больше диаграмм, а собрать несколько представлений одной системы так, чтобы они дополняли друг друга.
Одна система - несколько вопросов
У каждой модели должен быть свой вопрос.
Практическую карту можно представить так:
Что происходит в бизнес-процессе? -> BPMN
Кто взаимодействует с системой и зачем? -> UML Use Case
Какие сущности существуют и как они связаны? -> ERD
Как объект меняет состояние? -> State Machine
Как движутся данные? -> DFD
Кто кого вызывает во время конкретного сценария? -> Sequence Diagram
Из каких приложений состоит система? -> C4
Как выглядит точный HTTP-контракт? -> OpenAPI
Как компоненты обмениваются асинхронными событиями? -> Event-Driven Model
Это принципиально важнее выбора конкретного редактора или способа рисования.
Перед созданием любой диаграммы полезно сначала спросить:
Какой вопрос я пытаюсь решить?
Если нужно понять бизнес-процесс, C4 не поможет.
Если нужно определить таблицы PostgreSQL, BPMN не является подходящим инструментом.
Если нужно понять точную структуру JSON request, недостаточно Sequence Diagram.
Проблема появляется тогда, когда одна схема пытается отвечать сразу на все вопросы.
Сквозной пример
Возьмём одну функцию CRM образовательной программы:
Подача и обработка заявки
Пользователь выбирает программу, заполняет форму и отправляет заявку.
Оператор проверяет данные.
Если данные некорректны, заявка возвращается пользователю.
Если всё заполнено правильно, заявка передаётся руководителю на согласование.
После согласования система создаёт участника программы и отправляет уведомление.
Один и тот же сценарий можно посмотреть с нескольких сторон.
И именно здесь становится понятно, зачем существует несколько моделей.
BPMN - что происходит в процессе
Сначала можно описать бизнес-процесс.
Например:
Подать заявку -> Проверить заявку -> Данные корректны?
Да -> Согласовать -> Создать участника -> Отправить уведомление
Нет -> Вернуть на исправление -> Получить исправления -> Проверить повторно
BPMN позволяет добавить участников:
Applicant - подаёт заявку
Operator - проверяет
Manager - согласовывает
Information System - выполняет автоматические операции
Здесь нас пока не интересует:
какой endpoint вызывается
какая таблица изменяется
какой Python class выполняет действие
BPMN отвечает на бизнес-вопрос:
Как проходит процесс?
Из неё начинают появляться требования к системе.
Use Case - что пользователь может делать
Теперь можно посмотреть на систему со стороны возможностей пользователей.
Например:
Applicant -> Create Application
Applicant -> Edit Application
Applicant -> Submit Application
Operator -> Review Application
Manager -> Approve Application
Manager -> Reject Application
Use Case не повторяет BPMN.
BPMN показывает последовательность процесса.
Use Case фиксирует:
Actor -> цель взаимодействия с системой
Например, BPMN может содержать Task:
Проверить заявку
Из него появляется Use Case:
Operator -> Review Application
Но это не механическое правило вида:
каждый BPMN Task = отдельный Use Case
Некоторые технические или промежуточные Tasks вообще не являются самостоятельными пользовательскими целями.
От BPMN к требованиям
BPMN можно использовать как один из источников требований.
Некоторые связи действительно прослеживаются довольно естественно:
BPMN Task -> операция пользователя или системы
BPMN Lane -> роль или зона ответственности
BPMN Gateway -> business rule
BPMN Message Event -> интеграция или обмен сообщением
BPMN Timer Event -> отложенная операция
BPMN Service Task -> автоматизированная операция
BPMN Error Event -> сценарий обработки ошибки
Например:
Manager Lane
+
Approve Application Task
подсказывают:
существует роль Manager
+
у неё должна быть операция Approve Application
Gateway:
Документы проверены?
может породить business rule:
Application может перейти в Approved только если documents_verified = true
Timer Event:
через 3 дня отправить напоминание
может привести к требованию:
система должна уметь планировать delayed notification
Message Event:
получить результат оплаты
может означать необходимость:
webhook
API callback
message broker event
BPMN не определяет конкретную реализацию.
Она помогает найти то, что системе необходимо уметь делать.
Из процесса появляются сущности
После описания сценария можно перейти к данным.
В исходном требовании встречаются понятия:
Applicant
Application
Program
Document
Participant
Это кандидаты в сущности.
Но сущности не стоит выделять простым правилом:
нашёл существительное -> создал таблицу
Нужно проверить:
- имеет ли объект собственный смысл;
- нужно ли хранить его отдельно;
- существует ли у него идентификатор;
- есть ли жизненный цикл;
- какие отношения существуют с другими объектами.
Например:
Application
явно является самостоятельной сущностью.
А:
Approval
может оказаться либо отдельной сущностью, либо просто переходом состояния Application.
Это уже решение модели данных и требований к истории.
ERD - какие данные существуют
Для нашего процесса ERD может начинаться так:
Applicant 1:N Application N:1 Program
Application 1:N Document
Application 0..1:1 Participant
Сразу появляются Primary Key и Foreign Key.
Например:
Application
id
applicant_id
program_id
status
created_at
submitted_at
Теперь бизнес-понятие:
пользователь подаёт заявку на программу
формализовано в модели данных:
Applicant 1:N Application N:1 Program
Это уже другая сторона того же требования.
BPMN показывала действие.
ERD показывает данные, которые позволяют этому действию существовать.
ERD не должна содержать процесс
Одна из распространённых ошибок - пытаться перенести в ERD всё, что было в BPMN.
Например:
SubmitApplication
ReviewApplication
ApproveApplication
начинают превращать в таблицы только потому, что эти элементы есть в процессе.
Но:
Application - данные
ApproveApplication - действие над данными
Они относятся к разным моделям.
Если историю переходов действительно нужно сохранять, тогда может появиться:
ApplicationStatusHistory
Но это уже отдельное требование к данным, а не копирование BPMN Task в таблицу.
State Machine - как живёт сущность
В BPMN видно, что заявка проходит несколько этапов.
Теперь можно формализовать именно жизненный цикл Application.
Например:
Draft -> Submitted -> UnderReview -> Approved
и альтернативно:
UnderReview -> Rejected
или:
UnderReview -> NeedsCorrection -> Submitted
Получается State Machine:
Draft -> Submit -> Submitted
Submitted -> StartReview -> UnderReview
UnderReview -> Approve -> Approved
UnderReview -> RequestCorrection -> NeedsCorrection
NeedsCorrection -> Resubmit -> Submitted
UnderReview -> Reject -> Rejected
Теперь система знает не только множество статусов, но и допустимые transitions.
Например:
Draft -> Approved
может быть запрещён.
BPMN объясняет:
почему в процессе вообще происходит согласование
State Machine объясняет:
в каком состоянии Application должна находиться, чтобы согласование было допустимо
Из State Machine появляются бизнес-правила
Например, переход:
UnderReview -> Approved
может иметь Guard:
documents_verified == true
и требование к actor:
role == manager
Теперь появляется конкретное правило:
Application может быть согласована только Manager, если она находится в UnderReview и документы проверены
Это уже не просто нарисованная стрелка.
Такое правило влияет на:
- backend;
- permissions;
- API;
- тесты;
- интерфейс;
- audit log.
От State Machine к API
После определения бизнес-операций можно проектировать API.
Для Application могут существовать обычные resource endpoints:
GET /applications
POST /applications
GET /applications/{id}
PATCH /applications/{id}
Но State Machine показывает, что некоторые изменения являются отдельными бизнес-командами.
Например:
POST /applications/{id}/submit
POST /applications/{id}/start-review
POST /applications/{id}/approve
POST /applications/{id}/reject
Теперь переход:
UnderReview -> Approved
связан с:
POST /applications/{id}/approve
Backend проверяет:
authentication -> authorization -> current state -> guards -> transition -> persistence -> side effects
Так между State Machine и API появляется явная связь.
API Contract - точная граница системы
На уровне требований можно сказать:
Manager должен иметь возможность согласовать Application
Но consumer API нужен точный контракт.
Например:
POST /applications/42/approve
Authorization: Bearer <token>
Content-Type: application/json
{
"comment": "Documents verified"
}
Successful response:
200 OK
{
"id": 42,
"status": "approved",
"approved_at": "2026-09-29T10:00:00Z"
}
Ошибки:
401 - пользователь не authenticated
403 - пользователь не имеет права согласования
404 - Application не существует
409 - Application находится в недопустимом состоянии
422 - данные запроса не проходят validation
Теперь требование стало техническим контрактом.
Путь можно проследить:
BPMN Approve Application
-> State Machine UnderReview -> Approved
-> API POST /applications/{id}/approve
-> OpenAPI operation
Это и есть связность документации.
OpenAPI фиксирует контракт
После проектирования endpoint его можно формализовать в OpenAPI.
OpenAPI описывает:
method
path
parameters
request schema
response schema
status codes
authentication
Теперь frontend и backend могут работать относительно одного контракта.
При этом OpenAPI не должна повторять BPMN.
В ней не нужно объяснять весь бизнес-процесс обработки заявки.
Она отвечает на более узкий вопрос:
Как именно вызвать конкретную операцию через HTTP?
Sequence Diagram - как операция выполняется во времени
API говорит:
POST /applications/{id}/approve
Но не показывает, что происходит внутри системы.
Для этого можно построить Sequence Diagram.
Например:
React -> Django API: POST /applications/42/approve
Django API -> Keycloak/JWT validation: проверить identity
Django API -> PostgreSQL: получить Application
Django API -> Application Service: проверить transition
Application Service -> PostgreSQL: сохранить Approved
Application Service -> Outbox: сохранить ApplicationApproved
Django API -> React: 200 OK
Outbox Publisher -> RabbitMQ: publish ApplicationApproved
Теперь видно runtime interaction.
Sequence Diagram отвечает:
кто -> кого вызывает -> в каком порядке
Это другой вопрос, чем OpenAPI.
OpenAPI показывает внешний контракт.
Sequence показывает выполнение конкретного сценария.
C4 - какие компоненты вообще существуют
Sequence Diagram показывает один сценарий во времени.
Но архитектура системы существует постоянно.
Для этого нужна C4 Model.
Container Diagram может выглядеть так:
React SPA -> Django API -> PostgreSQL
Django API -> Redis
Django API -> RabbitMQ -> Celery Worker
Django API -> MinIO
Django API -> Keycloak
Теперь видно:
- какие приложения существуют;
- какие хранилища используются;
- какие крупные зависимости есть у системы.
Это статическая архитектурная карта.
Sequence Diagram показывает:
что произошло во время Approve Application
C4 Container Diagram:
какие элементы системы вообще существуют и связаны между собой
C4 Component Diagram связывает архитектуру с backend
Если Django API слишком крупный для понимания как один блок, можно раскрыть его:
Applications API
Application Service
Application State Machine
Document Service
Notification Service
Reporting Service
Repositories
Тогда Sequence Diagram можно связать уже с этими компонентами:
Applications API -> Application Service -> State Machine -> Repository
Так архитектура постепенно приближается к реализации, но ещё не превращается в список Python-файлов.
От API к C4
API также помогает находить архитектурные границы.
Например, существует endpoint:
POST /documents
который:
принимает metadata -> выдаёт presigned upload URL -> сохраняет информацию о Document
Это может показать необходимость:
Document component
Object Storage
Но здесь тоже нет автоматического правила:
endpoint = component
Десятки endpoints могут принадлежать одному component.
Граница component определяется ответственностью, а не количеством HTTP routes.
DFD - как данные проходят через архитектуру
C4 показывает:
React SPA -> Django API -> PostgreSQL
Но иногда этого недостаточно.
Нужно понять:
Какие именно данные проходят по этим связям?
Тогда используется DFD.
Например:
Applicant -> Application data -> Application Processing
Application Processing -> Application record -> Applications Store
Manager -> Review decision -> Application Processing
Application Processing -> Application status -> Applicant
Если нужно перейти к физическому уровню:
React SPA -> Application JSON -> Django API
Django API -> Application row -> PostgreSQL
DFD особенно полезна там, где важны:
- чувствительные данные;
- PII;
- внешние интеграции;
- trust boundaries;
- security analysis.
DFD и C4 не дублируют друг друга
Представим связь:
Django API -> Payment Provider
На C4 этого может быть достаточно.
DFD добавляет:
Django API -> Payment request -> Payment Provider
Payment Provider -> Payment result -> Django API
То есть:
C4 -> между какими компонентами существует связь
DFD -> какие данные по этой связи проходят
Event-Driven Modeling - что происходит после события
Теперь представим, что после:
Application -> Approved
система должна:
- создать Participant;
- сформировать документы;
- отправить уведомление;
- обновить аналитику.
Можно выполнить всё синхронно.
Но если используется event-driven архитектура:
ApplicationApproved -> RabbitMQ
а затем:
ApplicationApproved -> Participant Consumer
ApplicationApproved -> Document Consumer
ApplicationApproved -> Notification Consumer
ApplicationApproved -> Analytics Consumer
Появляется ещё один слой документации.
State Machine говорит:
UnderReview -> Approved
Event model:
этот transition порождает ApplicationApproved
C4:
Django API -> RabbitMQ -> Workers
Sequence:
в каком порядке выполняется конкретный сценарий
Каждая модель снова отвечает на свой вопрос.
Один сценарий во всех моделях
Теперь можно собрать всё вместе.
Сценарий:
Applicant подаёт Application
BPMN
Заполнить заявку -> Отправить заявку -> Проверить заявку
Показывает бизнес-процесс.
Use Case
Applicant -> Submit Application
Показывает цель пользователя.
ERD
Applicant 1:N Application N:1 Program
Показывает структуру данных.
State Machine
Draft -> Submit -> Submitted
Показывает изменение состояния Application.
API Contract
POST /applications/{id}/submit
Показывает техническую операцию на границе системы.
Sequence Diagram
React -> Django API -> Application Service -> PostgreSQL
Показывает runtime interaction.
DFD
Applicant -> Application data -> Application Processing -> Application Store
Показывает движение данных.
C4
React SPA -> Django API -> PostgreSQL
Показывает архитектурные элементы.
Event-Driven Model
ApplicationSubmitted -> RabbitMQ -> Review Notification Consumer
Показывает асинхронные реакции.
Одна функция системы породила несколько моделей, но ни одна из них не повторяет другую полностью.
Не стройте модели независимо
Главная проблема плохой документации выглядит так:
аналитик отдельно нарисовал BPMN
архитектор отдельно нарисовал C4
backend отдельно написал OpenAPI
разработчик отдельно создал database schema
Через некоторое время оказывается:
в BPMN статус называется Approved
в backend status называется Accepted
в API используется confirmed
в базе хранится SUCCESS
Каждый документ по отдельности выглядит правдоподобно, но общей модели системы нет.
Поэтому важна traceability - прослеживаемость между уровнями.
Traceability
Для ключевых функций полезно уметь пройти цепочку от требования до реализации.
Например:
Business requirement:
Manager approves Application
BPMN:
Approve Application
State Machine:
UnderReview -> Approved
Permission:
Manager
API:
POST /applications/{id}/approve
OpenAPI operationId:
approveApplication
ERD:
Application.status
ApplicationStatusHistory
Domain Event:
ApplicationApproved
C4:
Django API -> RabbitMQ
Sequence:
Frontend -> API -> Service -> DB -> Outbox
Это не значит, что нужно обязательно создавать одну огромную таблицу со всеми связями.
Но разработчик должен иметь возможность восстановить такую цепочку.
Если невозможно понять, какое бизнес-требование реализует endpoint:
POST /api/v1/action/173
документация потеряла связь с предметной областью.
От требований к ERD
Практический переход обычно начинается с бизнес-сценариев.
Например:
Абитуриент подаёт заявку на выбранную программу и прикладывает документы.
Выделяются потенциальные сущности:
Applicant
Application
Program
Document
Дальше определяются связи:
Applicant 1:N Application
Program 1:N Application
Application 1:N Document
Затем обязательность:
Application обязательно имеет Applicant
Application обязательно имеет Program
Application может не иметь Document
После этого ограничения:
Application.status NOT NULL
Program.start_date NOT NULL
История:
ApplicationStatusHistory
Получается путь:
Business scenario -> entities -> relationships -> constraints -> ERD -> database schema
От ERD и State Machine к API
ERD показывает ресурсы.
Например:
Application
Program
Document
Из них естественно появляются resource endpoints:
GET /applications
POST /applications
GET /applications/{id}
GET /programs
GET /programs/{id}
POST /documents
GET /documents/{id}
State Machine добавляет business commands:
POST /applications/{id}/submit
POST /applications/{id}/approve
POST /applications/{id}/reject
Получается полезное разделение:
ERD -> какие ресурсы существуют
State Machine -> какие переходы и действия над ними существуют
API -> как consumer выполняет эти операции
Но API не нужно генерировать механически из ERD.
Если в базе существует техническая таблица:
OutboxEvent
это не означает, что автоматически нужен:
GET /outbox-events
Database model и public API имеют разные границы.
От API к Sequence Diagram
После определения операции:
POST /applications/{id}/approve
можно разобрать её выполнение.
Например:
1. Frontend -> Django API: approve
2. Django API -> Auth: проверить identity
3. Django API -> Application Service: выполнить команду
4. Application Service -> PostgreSQL: получить Application
5. Application Service -> State Machine: проверить transition
6. Application Service -> PostgreSQL: сохранить Approved + Outbox Event
7. PostgreSQL -> Application Service: COMMIT
8. Django API -> Frontend: 200 OK
9. Outbox Publisher -> RabbitMQ: ApplicationApproved
Так обнаруживаются скрытые архитектурные вопросы.
Например:
где проверяются permissions?
где находится transaction boundary?
кто публикует событие?
что произойдёт при ошибке RabbitMQ?
Sequence Diagram становится инструментом проверки дизайна, а не просто красивой иллюстрацией.
От Sequence к C4
Если в Sequence постоянно появляются:
Frontend
Application API
Document Service
Notification Worker
PostgreSQL
RabbitMQ
MinIO
можно проверить Container и Component Diagram.
Архитектурная документация должна подтверждать, что эти элементы действительно существуют и имеют понятные обязанности.
Например:
Container: Django API
Component: Application Service
Container: Celery Worker
Component: Notification Handler
Container: PostgreSQL
Если Sequence Diagram ссылается на компонент, которого нигде больше нет, стоит проверить согласованность документации.
Что не нужно связывать один к одному
Очень важно не превратить эту методику в механический генератор.
Неверно:
каждый BPMN Task -> endpoint
каждая ERD entity -> API resource
каждый API endpoint -> отдельный component
каждый component -> отдельный microservice
Таких правил нет.
Например, один BPMN Task:
Проверить заявку
может внутри использовать:
GET /applications/{id}
POST /applications/{id}/start-review
POST /applications/{id}/approve
POST /applications/{id}/reject
Один backend Component может обслуживать десятки endpoints.
Один C4 Container может содержать десятки Components.
Одна ERD entity может вообще не иметь публичного API.
Модели связаны семантически, а не количеством элементов.
Минимальная документация небольшого проекта
Небольшой системе не нужно создавать полный каталог всех существующих типов диаграмм.
Для многих проектов достаточно:
System Context Diagram
Container Diagram
ERD
несколько ключевых BPMN
State Machine критичных сущностей
OpenAPI
несколько Sequence Diagram сложных сценариев
Дополнительно:
DFD -> если важны потоки данных, безопасность и внешние интеграции
Event-Driven Model -> если есть broker и сложные asynchronous flows
Deployment Diagram -> если инфраструктура уже имеет существенную сложность
Component Diagram -> если отдельный Container стал достаточно большим
Документация должна расти вместе со сложностью системы.
Не нужно заранее создавать:
40 diagrams
для приложения из одного Django backend и PostgreSQL.
Какие BPMN стоит документировать
Не обязательно рисовать BPMN для каждого действия.
Имеет смысл выбрать процессы, где присутствуют:
- несколько участников;
- бизнес-решения;
- исключения;
- ожидание;
- внешние взаимодействия;
- сложный жизненный цикл.
Например:
обработка заявки
оплата
выдача документов
возврат
регистрация участника
Простой CRUD:
пользователь изменил номер телефона
может вообще не требовать BPMN.
Какие State Machine стоит документировать
State Machine особенно полезны для сущностей:
Application
Order
Payment
Document
Deal
Task
где:
- много статусов;
- существуют запрещённые переходы;
- важны права;
- переходы вызывают side effects.
Для сущности:
Country
с полями:
id
name
code
State Machine, скорее всего, ничего не добавит.
Какие Sequence Diagram стоит документировать
Sequence Diagram полезны там, где невозможно сразу понять runtime interaction.
Например:
authentication
payment
file upload
report generation
webhook processing
event publication
distributed transaction
Не нужно рисовать Sequence Diagram для каждого:
GET /countries
если сценарий очевиден.
Документация должна концентрироваться на сложных участках.
OpenAPI обычно нужен целиком
В отличие от BPMN или Sequence Diagram, API-контракт лучше документировать системно.
Consumer должен иметь возможность узнать контракт любого поддерживаемого endpoint.
Поэтому OpenAPI естественно становится почти полной технической спецификацией HTTP API.
Но при этом OpenAPI не обязана подробно объяснять всю бизнес-логику.
Для этого остаются:
BPMN
State Machine
обычная документация
Архитектурные решения и ADR
Некоторые вопросы плохо выражаются диаграммами.
Например:
Почему для асинхронных задач выбран RabbitMQ?
или:
Почему используется модульный монолит вместо микросервисов?
или:
Почему документы хранятся в MinIO, а не в PostgreSQL?
Для таких решений полезны ADR - Architecture Decision Records.
ADR обычно фиксирует:
контекст
решение
рассмотренные альтернативы
последствия
Например:
ADR-005: Использовать Transactional Outbox для публикации domain events
C4 показывает:
Django -> PostgreSQL -> RabbitMQ
Но ADR объясняет:
Почему архитектура устроена именно так.
Диаграмма и архитектурное решение выполняют разные функции.
Документация должна иметь источник истины
Одна из самых неприятных ситуаций:
Confluence говорит одно
README другое
OpenAPI третье
реальный backend четвёртое
Документация перестаёт быть полезной, когда ей нельзя доверять.
Для каждого типа информации полезно определить source of truth.
Например:
API contract -> OpenAPI
database schema -> migrations + ERD
architecture -> C4 diagrams
business process -> BPMN
architecture decisions -> ADR
state transitions -> State Machine specification / code
Это не означает, что модель обязана генерироваться автоматически.
Но должно быть понятно, какой источник считается актуальным при расхождении.
Documentation as Code
Для технической документации часто удобно хранить исходники рядом с кодом.
Например:
/docs
/architecture
context.puml
containers.puml
/bpmn
application-review.bpmn
/erd
domain.dbml
/adr
ADR-001.md
ADR-002.md
openapi.yaml
Преимущества:
- version control;
- code review;
- история изменений;
- связь документации с release;
- возможность обновлять её в том же pull request.
Например, разработчик изменяет:
Application State Machine
и в том же PR обновляет:
state diagram
OpenAPI
Sequence Diagram
Документация становится частью изменения системы, а не отдельной задачей "обновить когда-нибудь потом".
Но не всё нужно хранить рядом с кодом
Бизнес-документация может жить:
- в базе знаний;
- BPM-системе;
- Confluence;
- внутреннем портале.
Важно не конкретное место хранения.
Важно, чтобы было понятно:
где находится актуальная версия
кто отвечает за неё
когда она должна изменяться
Документация должна иметь владельца
Документ без владельца почти гарантированно устареет.
Например:
BPMN -> Business/System Analyst
OpenAPI -> Backend Team
ERD -> Backend/Data Team
C4 -> Tech Lead / Architect
ADR -> команда, принявшая решение
Это не означает, что только один человек имеет право вносить изменения.
Речь о том, кто отвечает за актуальность модели.
Когда нужно обновлять документацию
Хорошее правило:
Если изменение системы делает существующую схему неверной, документацию нужно менять вместе с системой.
Например, изменился:
API contract -> обновить OpenAPI
Добавился новый:
Application state -> обновить State Machine
Появилась новая внешняя система:
Payment Provider -> обновить System Context
Появился новый Container:
Notification Service -> обновить Container Diagram
Изменился бизнес-процесс:
появилось дополнительное согласование -> обновить BPMN
Не обязательно обновлять всё при каждом commit.
Обновляются модели, смысл которых действительно изменился.
Не документируйте нестабильные детали без причины
Если внутренний код постоянно меняется:
ApplicationService
ApplicationCommandHandler
ApplicationFacade
ApplicationManager
может не иметь смысла поддерживать C4 Component Diagram, где каждый такой класс показан отдельно.
Именно поэтому документация должна оставаться на достаточно стабильном уровне абстракции.
Например:
Application Management Component
может существовать месяцами, даже если внутри него были десятки рефакторингов.
Хорошая документация описывает устойчивую структуру системы.
Изменение требования должно распространяться по моделям
Представим новое требование:
После согласования Application должна пройти проверку службой безопасности.
Раньше:
UnderReview -> Approved
Теперь:
UnderReview -> SecurityReview -> Approved
Изменение проходит по документации.
BPMN
Добавляется:
Проверить заявку -> Проверка безопасности -> Согласовать
State Machine
Изменяется:
UnderReview -> SecurityReview -> Approved
Roles
Появляется:
Security Officer
API
Возможно появляются:
POST /applications/{id}/start-security-review
POST /applications/{id}/approve-security-review
ERD
Может потребоваться:
security_reviewed_at
security_reviewed_by
или отдельная:
SecurityReview
если проверка имеет собственный жизненный цикл.
Sequence Diagram
Добавляется взаимодействие с новым компонентом или ролью.
C4
Если появляется отдельный сервис:
Security Verification Service
изменяется Container Diagram.
Events
Могут появиться:
SecurityReviewStarted
SecurityReviewCompleted
Так одно бизнес-изменение проходит через несколько представлений системы.
Именно поэтому документация должна быть связанной.
Documentation change impact
Полезно привыкнуть задавать вопрос:
Какие модели затрагивает это изменение?
Например:
Добавили поле comment -> ERD + API
Добавили статус -> State Machine + API + возможно BPMN
Добавили новую роль -> Use Case + BPMN + authorization
Добавили новый сервис -> C4 + возможно Sequence
Добавили интеграцию -> Context + Container + DFD + API/Event Contract
Изменили бизнес-процесс -> BPMN + возможно State Machine + API
Так документация становится инструментом impact analysis.
Не дублируйте одну информацию во всех документах
Если точная request schema уже находится в OpenAPI, нет смысла копировать полный JSON schema в:
BPMN
C4
ERD
Sequence Diagram
Можно показать только нужную часть:
Sequence:
React -> API: CreateApplicationRequest
а точное определение CreateApplicationRequest оставить в OpenAPI.
Аналогично:
если связи таблиц уже описаны в ERD, C4 не должна повторять все Foreign Keys.
Принцип:
каждая информация имеет основной источник
остальные модели только ссылаются на неё на нужном уровне
Это уменьшает риск расхождения.
Проектная документация как граф знаний
Вместо представления:
у нас есть 15 файлов документации
полезнее думать:
у нас есть одна модель системы с несколькими представлениями
Например:
Application
связана с:
BPMN Process
State Machine
ERD Entity
API Resource
Domain Events
Backend Component
Sequence Diagrams
А:
Manager
связан с:
BPMN Lane
Use Case Actor
Role
API permissions
Система становится не набором схем, а сетью взаимосвязанных понятий.
Уровни проектной документации
Всю документацию удобно условно разделить на несколько уровней.
Бизнес-уровень
Отвечает:
что делает организация и зачем
Инструменты:
BPMN
Use Cases
business rules
Доменный уровень
Отвечает:
какие понятия существуют и как они себя ведут
Инструменты:
ERD / Domain Model
State Machine
Event Model
Контрактный уровень
Отвечает:
как части системы взаимодействуют через формальные границы
Инструменты:
OpenAPI
Webhook Contracts
Event Contracts
Архитектурный уровень
Отвечает:
какие программные элементы существуют
Инструменты:
C4
Component Diagram
Runtime-уровень
Отвечает:
как проходит конкретный технический сценарий
Инструменты:
Sequence Diagram
C4 Dynamic Diagram
Инфраструктурный уровень
Отвечает:
где система физически работает
Инструменты:
C4 Deployment
UML Deployment
Infrastructure diagrams
Так становится намного проще понимать, где должна находиться конкретная информация.
Практическая структура документации проекта
Для реального проекта документацию можно организовать примерно так:
1. Overview
2. Business Processes
3. Domain Model
4. Architecture
5. API and Integration Contracts
6. Runtime Scenarios
7. Deployment
8. Architecture Decisions
Например:
Overview
-> System Context
Business Processes
-> BPMN
Domain Model
-> ERD
-> State Machines
-> Domain Events
Architecture
-> C4 Container
-> C4 Component
API and Integrations
-> OpenAPI
-> Webhook Contracts
-> Event Contracts
Runtime Scenarios
-> Sequence Diagrams
Deployment
-> Deployment Diagram
Decisions
-> ADR
Такая структура лучше, чем отдельные папки:
UML
BPMN
ERD
без связи с задачами проекта.
Пользователю документации обычно важнее вопрос:
Где посмотреть архитектуру?
чем:
Где у нас лежат все UML-диаграммы?
Как читать документацию нового проекта
Новому разработчику полезно идти сверху вниз.
Сначала:
System Context
Чтобы понять, что это вообще за система.
Затем:
Container Diagram
Чтобы увидеть основные приложения и хранилища.
После этого:
ключевые BPMN
Чтобы понять бизнес-процессы.
Дальше:
ERD + State Machines
Чтобы понять данные и жизненный цикл сущностей.
Потом:
OpenAPI
Чтобы увидеть внешние контракты.
Для сложных сценариев:
Sequence Diagram
И уже после этого есть смысл глубоко читать исходный код.
Так архитектурная документация сокращает время, необходимое для построения ментальной модели проекта.
Типичные ошибки проектной документации
Первая ошибка - пытаться описать систему одной диаграммой.
Получается:
users + business process + APIs + tables + classes + servers
и никто не может её читать.
Вторая ошибка - создавать одну и ту же информацию в нескольких местах.
Например, request schema одновременно хранится:
в OpenAPI
в Markdown
в Confluence
в комментарии frontend
Через месяц четыре версии расходятся.
Третья ошибка - документы не связаны.
Есть BPMN и OpenAPI, но невозможно понять:
какой endpoint реализует конкретный Task
Четвёртая ошибка - документируется всё подряд.
Даже простейший CRUD получает:
BPMN
Use Case
Sequence
Activity
Component
State Machine
Стоимость поддержки документации становится выше её пользы.
Пятая ошибка - документация создаётся после разработки как отдельный формальный этап.
К этому моменту часть решений уже забыта, а схемы строятся не для проектирования, а для отчётности.
Шестая ошибка - слишком низкий уровень детализации.
Если архитектурная диаграмма содержит:
serializer.py
helpers.py
utils.py
она будет устаревать после каждого рефакторинга.
Седьмая ошибка - нет владельца документа.
Через несколько месяцев никто не знает:
эта схема ещё актуальна?
Восьмая ошибка - отсутствие ADR.
Диаграмма показывает:
что существует
но никто уже не помнит:
почему было принято именно такое решение
Как проверить комплект документации
Для небольшого проекта полезно пройти по нескольким вопросам.
Понятно ли:
- что делает система;
- кто её использует;
- какие внешние системы существуют;
- какие ключевые бизнес-процессы выполняются;
- какие основные сущности хранятся;
- как связаны сущности;
- какие сущности имеют сложный жизненный цикл;
- какие API доступны;
- какие события и webhooks существуют;
- какие приложения входят в систему;
- как выполняются сложные runtime-сценарии;
- где находятся архитектурные решения;
- кто отвечает за актуальность каждого документа?
Если ответ можно получить без чтения половины исходного кода, документация уже выполняет свою задачу.
Что важно запомнить
BPMN, UML, ERD, C4, DFD, State Machine и OpenAPI не конкурируют друг с другом.
Они описывают разные стороны одной системы.
Основная карта:
BPMN -> бизнес-процесс
Use Case -> пользовательские цели
ERD -> структура данных
State Machine -> жизненный цикл объекта
DFD -> движение данных
Sequence Diagram -> взаимодействие во времени
C4 -> архитектурная структура
OpenAPI -> точный HTTP-контракт
Event Model -> асинхронные события и команды
Deployment -> физическое размещение
ADR -> причины архитектурных решений
Связь между ними можно представить как общий путь:
Бизнес-требование
-> BPMN / Use Case
-> Domain Model
-> ERD + State Machine
-> API / Event Contracts
-> Sequence
-> C4
-> реализация
При этом направление не всегда только сверху вниз.
Изменение API может обнаружить проблему в State Machine.
Изменение ERD может потребовать пересмотра API.
Новый Container может изменить Sequence Diagram.
Новая бизнес-ветка в BPMN может потребовать новой сущности, роли и события.
Поэтому проектная документация является не набором независимых файлов, а несколькими согласованными представлениями одной системы.
Главный принцип можно сформулировать так:
один вопрос -> одна подходящая модель -> один основной источник истины
А хорошая документация позволяет пройти путь:
зачем существует функция -> как работает бизнес-процесс -> какие данные и состояния нужны -> какой контракт предоставляет система -> какие компоненты участвуют -> как всё выполняется технически
Если этот путь прослеживается, документация действительно помогает проектировать и развивать систему, а не существует только ради наличия схем.