1 апреля 2024
Главная проблема архитектурных диаграмм - не «как нарисовать», а «на каком уровне абстракции говорить». UML дал индустрии богатый словарь, но не дал правила, какие элементы уместны на каком уровне; в результате типичная архитектурная диаграмма смешивает классы, контейнеры и облачные сервисы на одном холсте и одинаково непонятна и инженеру, и продакту. C4 Model Саймона Брауна - это не новая нотация, а правило зума: четыре фиксированных уровня детализации (Context, Containers, Components, Code), каждый со своей аудиторией, своим набором допустимых элементов и своим вопросом, на который он отвечает. Статья разбирает, откуда взялась эта модель, что она исправила в практике UML-эпохи, как её применять без типичных ошибок (смешивание уровней, переусложнённый Context, мёртвые Code-диаграммы), какие компании используют похожий подход в production, и почему хранить диаграммы как код важнее, чем выбрать конкретный инструмент.
Проблема абстракции диаграмм
Если попросить десять инженеров нарисовать «архитектуру нашей системы», получится десять разных диаграмм, и почти все они окажутся непригодны хотя бы для одной из аудиторий, которым нужны. Один нарисует boxes-and-arrows из пяти прямоугольников - бесполезно для разработчика, который ищет, куда положить новый сервис. Другой нарисует UML class diagram на 40 классов - бесполезно для продакта, которому нужно понять границы системы. Третий смешает на одном холсте облачные сервисы AWS, контейнеры Docker и слои приложения - бесполезно для всех, потому что элементы разного масштаба нельзя сравнивать визуально.
Это не вина инженеров. UML, доминирующая нотация 1990-х и 2000-х, давал 14 типов диаграмм (class, sequence, activity, component, deployment и т. д.), но не давал правила, как эти типы между собой соотносятся. Grady Booch в «Object Solutions» (Addison-Wesley, 1996) и в более поздней «Object-Oriented Analysis and Design with Applications» (3rd ed., 2007) подробно обсуждал levels of abstraction как ключевую инженерную дисциплину - но в самом UML это правило осталось имплицитным. В результате команды, искренне старавшиеся «делать UML», получали либо переусложнённые class diagrams (которые быстро устаревали и переставали обновляться), либо вырожденные рисунки в Visio, формально похожие на UML, но без какой-либо дисциплины уровней.
К концу 2000-х индустрия молчаливо отказалась от формального UML в пользу свободных «boxes and lines» в Visio, Lucidchart и PowerPoint. Это решило проблему сложности нотации, но создало новую: исчезла любая дисциплина уровней. На одной диаграмме могли соседствовать «бизнес-домен», «микросервис», «класс» и «AWS region» - и так как формальных правил больше не было, никто не мог сказать, что диаграмма неправильная. Просто никому не было понятно, о чём она.
Саймон Браун, британский архитектор и автор «Software Architecture for Developers» (Leanpub, 2014), сформулировал проблему так: команды разучились разговаривать об архитектуре общим языком. Не потому что они не знают паттернов или не умеют рисовать, а потому что у них нет согласованного словаря зума. Когда один говорит «архитектура», он имеет в виду набор сервисов; когда другой - расположение классов в кодовой базе; когда третий - схему деплоя в облако. Все три ответа правильные, но они о разных слоях, и без явной фиксации уровня обсуждение распадается.
C4 Model - ответ на эту проблему. Браун предложил не новую нотацию, а правило: всегда явно фиксировать, на каком из четырёх уровней (Context, Containers, Components, Code) находится диаграмма, и не смешивать элементы разных уровней на одном холсте. Аналогия Брауна, которую он повторяет в большинстве своих выступлений - карты Google: страна → город → район → улица. На каждом уровне виден свой набор объектов, и переключение между уровнями - это именно зум, а не переключение типа карты. Тот же набор объектов реального мира описывается с разной степенью детализации в зависимости от того, какой вопрос вы задаёте.
Четыре уровня абстракции
C4 предлагает четыре уровня детализации для разных аудиторий. Каждый уровень отвечает на свой вопрос и адресован своей аудитории; на одном уровне нельзя ответить на вопрос соседнего, и попытка это сделать - первый признак того, что диаграмма выйдет из-под контроля.
- Context - для всех, включая бизнес. Вопрос: что эта система делает в окружении пользователей и других систем?
- Containers - для технической команды. Вопрос: из каких deployable units состоит система и как они общаются?
- Components - для разработчиков. Вопрос: из каких структурных блоков состоит конкретный container?
- Code - для глубокого погружения. Вопрос: как именно реализован отдельный component?
Идея уровней восходит не к Брауну. Grady Booch писал о levels of abstraction как о фундаментальном инструменте борьбы со сложностью ещё в начале 1990-х в «Object-Oriented Analysis and Design with Applications» (Benjamin/Cummings, 2-е издание 1993): инженер мыслит на одном уровне за раз, и качество архитектурной работы определяется тем, насколько последовательно он удерживает этот уровень. Eric Evans в «Domain-Driven Design» (Addison-Wesley, 2003) применил эту же идею к доменному моделированию: bounded context - это тоже способ зафиксировать уровень обсуждения. Vaughn Vernon в «Implementing Domain-Driven Design» (Addison-Wesley, 2013) развил context maps как способ показать, как несколько bounded contexts соотносятся - это структурно близко к C4 System Landscape Diagram.
Mark Richards и Neal Ford в «Software Architecture: The Hard Parts» (O'Reilly, 2021) формулируют похожий тезис в терминах архитектурных решений: каждое решение принимается на определённом уровне (системном, сервисном, компонентном), и попытка решать вопрос одного уровня инструментами другого - частая причина проваленных миграций. C4 операционализирует эту идею: уровень обсуждения должен быть виден на самой диаграмме, а не подразумеваться.
Майкл Нюгард в оригинальном посте 2011 года «Documenting Architecture Decisions» (cognitect.com) предложил ADR как минимальный артефакт фиксации архитектурных решений; в современной практике C4-диаграммы и ADR живут вместе - диаграмма показывает структуру в моменте, ADR объясняет, почему она такая. Atlassian публично описывает похожий подход в своём engineering blog: каждое значимое решение фиксируется ADR, ключевые системы - C4-подобными диаграммами в Confluence, и оба артефакта лежат рядом с кодом, который они описывают.
Level 1: System Context
Показывает систему как чёрный ящик в окружении пользователей и внешних систем. Это bird's eye view - вид с высоты птичьего полёта.
| Scope | Одна software system |
| Primary elements | Ваша система (в центре) |
| Supporting elements | Пользователи (роли, персоны) и внешние системы |
| Аудитория | Все: технические и нетехнические люди |
Пример: B2B SaaS платформа
Стилизованный пример на основе типичных паттернов B2B SaaS - юридические, финансовые и tax-сервисы для малого бизнеса. Структура персон и интеграций здесь типична для класса систем, а не привязана к конкретной компании.
┌─────────────────────────────────────────────────────────────────┐
│ USERS (Personas) │
├─────────────┬─────────────┬─────────────┬─────────────┬─────────┤
│ Employee │ Client │ Admin │ Support │ SRE │
│ (firm user) │ (end user) │ (system) │ (L2 help) │ (ops) │
└──────┬──────┴──────┬──────┴──────┬──────┴──────┬──────┴────┬────┘
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ │
│ ┌───────────────────┐ │
│ │ THE PLATFORM │ │
│ │ (Our System) │ │
│ └─────────┬─────────┘ │
│ │ │
└──────────────────────────────┼──────────────────────────────────┘
│
┌───────────────────────┼───────────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Payment │ │ E-Signature │ │ Email │
│ Provider │ │ Service │ │ Integration │
└─────────────┘ └─────────────┘ └─────────────┘
EXTERNAL SYSTEMS (Third-Party Services)
Что НЕ включать: технологии, протоколы, низкоуровневые детали. Диаграмма должна быть понятна product manager или CEO. Самая частая ошибка на этом уровне - попытка показать «как у нас устроено внутри»: появляются микросервисы, базы данных, очереди. Это автоматически убивает Context как коммуникационный инструмент с нетехнической аудиторией - им становится непонятно, и они перестают на него смотреть.
Level 2: Containers
Zoom-in внутрь системы. Показывает deployable units: веб-приложения, API, базы данных, очереди сообщений, мобильные приложения.
| Scope | Одна software system |
| Primary elements | Containers внутри системы |
| Supporting elements | Пользователи и внешние системы, связанные с containers |
| Аудитория | Технические люди: архитекторы, разработчики, DevOps |
Показывает:
- High-level структуру архитектуры
- Распределение ответственности
- Основные технологические решения
- Как containers общаются друг с другом
Пример: Backend платформы
Стилизованный пример на основе типичных паттернов B2B SaaS-бэкенда: web app + background jobs + scheduler поверх общего набора storage, плюс несколько внешних gRPC-сервисов для специализированных функций. Конкретные имена обобщены, структура отражает класс систем.
CLIENT APPS: [React SPA] [Mobile Employee] [Mobile Client] [Desktop] [Admin]
| | | | |
+-------+------+-------+-------+-------------+---------+
| |
v HTTPS API v
+--------------------------------------------------+
| BACKEND |
| |
| +----------+ +------------+ +-----------+ |
| | Web App | | Background | | Scheduler | |
| | (Rails) | | Jobs | | (Cron) | |
| +----+-----+ +-----+------+ +-----+-----+ |
| | | | |
| +--------------+--------------+ |
| | |
| v |
| +----------------------------------------------+|
| | DATABASES ||
| | [PostgreSQL] [Redis] [OpenSearch] [S3] ||
| +----------------------------------------------+|
+--------------------------------------------------+
| | |
v gRPC v gRPC v gRPC
+---------+ +---------+ +-----------+
|Payments | | OCR | |Marketplace|
| Service | | Service | | Service |
+---------+ +---------+ +-----------+
Что НЕ включать: кластеризацию, load balancers, репликацию - это для Deployment diagram. Показывать «у нас 3 инстанса web app за nginx-балансировщиком» на Container-диаграмме - распространённая ошибка: вы смешиваете логическую структуру (какие containers есть) с физическим деплоем (как они размещены), и диаграмма перестаёт быть полезной для обоих вопросов.
Level 3: Components
Zoom-in внутрь одного container. Показывает структурные блоки: сервисы, контроллеры, репозитории и их взаимодействие.
| Scope | Один container |
| Primary elements | Components внутри container |
| Supporting elements | Другие containers и внешние системы |
| Аудитория | Архитекторы и разработчики |
Пример: Web Application container
Стилизованный пример на основе типичных паттернов Rails-приложения с разделением на controllers, services, repositories и background jobs. Структура отражает класс архитектур, а не конкретный продукт.
+--------------------------------------------------------------+
| WEB APPLICATION (Rails) |
| |
| +--------------+ +--------------+ +------------------+ |
| | Controllers | | Services | | Background | |
| | | | | | Jobs | |
| | - Invoices |->| - Billing | | - PaymentSync | |
| | - Users | | - Payments |->| - ReportBuilder | |
| | - Reports | | - Analytics | | - Notifications | |
| +------+-------+ +------+-------+ +--------+---------+ |
| | | | |
| v v | |
| +--------------+ | |
| | Repositories |<------------+ |
| | | |
| | - UserRepo | |
| | - InvoiceRepo| |
| +------+-------+ |
| | |
+--------------------------------------------------------------+
|
v SQL
+--------------+
| PostgreSQL |
+--------------+
Level 4: Code
Самый детальный уровень: UML-диаграммы классов, ER-диаграммы и т. д. В большинстве случаев не нужен - код сам себя документирует, а IDE позволяет навигировать по нему.
Когда полезен:
- Сложные алгоритмы, где визуализация помогает понять последовательность шагов
- Design patterns - наглядно показать связи между классами
- Критические части системы, которые редко меняются (ядро платёжной логики, state machine)
Для большинства проектов достаточно уровней 1-3. Если код хорошо структурирован и покрыт тестами, Level 4 создаёт больше работы по поддержанию актуальности, чем приносит пользы. Браун в публичных выступлениях прямо говорит: если вы рисуете Code-диаграмму вручную и обновляете её при каждом коммите, вы тратите время; если Code-диаграмма не генерируется из самого кода, она устареет в течение спринта.
Дополнительные диаграммы
System Landscape Diagram
Когда нужно показать несколько систем в рамках организации. По сути - Context diagram без фокуса на конкретной системе.
| Scope | Enterprise / организация / департамент |
| Аудитория | Все |
Dynamic Diagram
Показывает взаимодействие элементов во время выполнения: user story, use case, конкретный сценарий. Похоже на UML sequence diagram, но с более свободной раскладкой.
| Scope | Конкретная feature / user story |
| Elements | На выбор: systems, containers или components |
Deployment Diagram
Показывает, как containers деплоятся на инфраструктуру: серверы, VM, Kubernetes, cloud services. Основан на UML deployment diagram.
| Scope | Одна или несколько систем в конкретном environment (prod, staging, dev) |
| Elements | Deployment nodes, container instances, infrastructure (DNS, load balancers, firewalls) |
| Аудитория | Архитекторы, разработчики, DevOps, SRE |
Можно использовать иконки AWS, Azure, GCP - но включайте их в легенду. AWS Reference Architectures, публикуемые на aws.amazon.com/architecture, - один из самых известных публичных примеров иерархического подхода: на верхнем уровне они показывают workload как чёрный ящик в окружении managed-сервисов (структурно это Context), на следующем - какие сервисы и каким образом интегрированы (структурно это Containers), и только на глубоких страницах появляется детализация по компонентам и зонам доступности (Deployment view). Сами AWS не называют это «C4», но дисциплина уровней узнаваема.
Стратегия внедрения в команде
Внедрение C4 - это не «договорились рисовать четыре диаграммы вместо одной». Это смена дисциплины обсуждения архитектуры, и она не приживается за счёт одного письма от архитектора. Команды, которые успешно внедряют C4, обычно проходят через несколько шагов в одном и том же порядке.
Шаг 1: одна Context-диаграмма на каждую систему. Это минимальный артефакт, который окупается на первой же встрече с новым человеком в команде. Context рисуется за 30 минут, отвечает на вопрос «что это и кто этим пользуется» и не требует от команды менять процессы. Если за месяц после введения дисциплины каждая ваша система обзавелась актуальной Context-диаграммой - это успех первого этапа.
Шаг 2: Container-диаграмма для каждой системы, которая шире одного приложения. Это уровень, на котором живут технические дискуссии: куда добавить новый сервис, что мигрировать, где провести границу. Здесь важно сразу класть диаграмму в репозиторий рядом с кодом (см. раздел про Diagrams as Code), а не в Confluence - иначе она устареет за квартал.
Шаг 3: Component-диаграммы выборочно. Не для каждой системы, а для тех container-ов, где есть онбординг или где структура нетривиальна. Хороший индикатор: если новый разработчик задаёт вопрос «как у вас устроен этот сервис», и ответ занимает 20 минут устной речи - пора нарисовать Component-диаграмму.
Шаг 4: Deployment-диаграмма как минимум для production. Этот уровень особенно важен для on-call: когда инцидент происходит в 3 утра, дежурный должен по диаграмме понимать, какие узлы за что отвечают и где смотреть метрики. Code-уровень в большинстве команд так и не появляется в явном виде, и это нормально.
Антипаттерны внедрения
Внедрения C4 обычно ломаются на нескольких типовых ошибках. Каждая из них выглядит как мелочь, но в сумме они приводят к тому, что через полгода диаграммы либо устаревают, либо команда возвращается к свободным рисункам.
Смешивание уровней на одном холсте. Самая частая ошибка. На Container-диаграмме появляются классы из одного из сервисов («ну у нас тут важная PaymentProcessor-логика»), на Component - облачные сервисы AWS («ну тут же видно, куда мы пишем в S3»). Каждый раз этому есть локальное оправдание, но результат тот же: диаграмма перестаёт принадлежать одному уровню, и аудитория, для которой этот уровень предназначен, перестаёт её понимать. Правило простое: если элемент не подходит к уровню, значит, он живёт на соседнем; нарисуйте на нём отдельную диаграмму или просто опустите.
Переусложнённый Context. Команда соблазняется показать «как у нас всё устроено внутри» уже на Context-диаграмме - и появляются микросервисы, базы, очереди. Это автоматически убивает Context как коммуникационный инструмент с нетехнической аудиторией: продукт-менеджер или CEO смотрит на диаграмму, видит «UserService → AuthService → Redis», ничего не понимает, и больше на эту диаграмму не возвращается. Context должен оставаться чёрным ящиком; всё внутреннее - на следующем уровне.
Переусложнённый Code. Зеркальная ошибка: команда героически рисует UML class diagram на 60 классов, фиксирует её в Confluence и через месяц перестаёт обновлять. Через квартал диаграмма расходится с кодом настолько, что становится дезинформацией - новый разработчик пользуется ею и принимает неверные решения. Code-диаграммы оправданы только тогда, когда они либо генерируются автоматически из кода, либо описывают редко меняющееся ядро (state machine, доменное ядро) - то есть существуют в режиме, который защищает от стихийного устаревания.
Архитектурные диаграммы вне version control. Диаграмма в Confluence или Lucidchart, не связанная с репозиторием кода, который она описывает, - почти гарантированно устареет. Никто не помнит обновить её при PR; никто не делает code review её изменений; никто не знает, какая версия актуальная. Решение - хранить диаграмму как код в том же репозитории, и ниже отдельный раздел про это.
Одна большая диаграмма вместо набора по уровням. Команда пытается уместить «всю архитектуру» на одном A3 - и получает либо нечитаемый клубок, либо упрощение, в которое не помещаются нужные детали. C4 предлагает обратное: одну диаграмму на zoom-уровень, и ссылочную связь между ними. Большая диаграмма-постер визуально эффектна, но как рабочий инструмент проигрывает набору фокусированных диаграмм почти всегда.
Наследование «архитектора-художника». Когда диаграммы рисует один человек в Visio, а остальная команда не умеет с ними работать, диаграммы умирают вместе с уходом этого человека из проекта. Дисциплина C4 окупается только тогда, когда ею владеет команда, а не один архитектор. Это связано с переходом к Diagrams as Code: текстовый исходник диаграммы доступен любому разработчику, и обновление - это PR, а не визит к автору.
Примеры из production систем
C4 как формальная нотация принят далеко не везде, но иерархическая дисциплина зума - принципиально шире, и её используют команды, которые формально про C4 не упоминают. Полезно посмотреть на несколько публичных примеров с разным контекстом.
c4model.com - example bank. Самый прямой пример - официальный сайт модели Брауна (c4model.com) и связанная коллекция в Structurizr DSL (structurizr.com/dsl). Там приведены полные комплекты диаграмм для нескольких эталонных систем (Big Bank plc, Internet Banking System), которые показывают, как все четыре уровня выглядят на одной системе и как они между собой связаны. Это образцовая референсная имплементация для команды, которая хочет понять, к чему стремиться, а не выдумывать структуру с нуля.
AWS Reference Architectures. Публичная библиотека референсных архитектур AWS (aws.amazon.com/architecture) формально не использует C4-нотацию, но дисциплина уровней в их диаграммах узнаваема: верхняя диаграмма показывает workload в окружении пользователей и managed-сервисов (структурно это Context), следующие слои показывают логические компоненты и data flow (структурно это Containers и Components), и только дальше - детализация по AZ и сетевой топологии (Deployment). Это полезный пример, потому что он показывает: иерархический подход работает не только для одной системы внутри одной компании, но и как способ публичной коммуникации между вендором и клиентом.
Atlassian. В публикациях Atlassian Engineering (atlassian.com/engineering) и в многочисленных выступлениях их архитекторов на конференциях упоминается практика хранения архитектурных решений как ADR в репозитории и фиксации структуры систем диаграммами в Confluence, организованными по уровням, близким к C4. Конкретный набор уровней может отличаться от каноничного, но принцип «одна диаграмма на zoom, явно зафиксированный уровень аудитории, ссылочная связь между уровнями» соблюдается. Это пример организации, в которой дисциплина уровней встроена в инженерный процесс, а не существует как разовый артефакт.
Monzo. Британский цифровой банк Monzo, известный микросервисной архитектурой на 1500+ сервисах поверх Kubernetes, в постах своего инженерного блога (monzo.com/blog) и в выступлениях Matt Heath и других инженеров публично описывает архитектуру в терминах, структурно близких C4: high-level взгляд на платформу как Context, разбивка по доменам и сервисам как Containers, внутреннее устройство критических сервисов как Components. Они особо подчёркивают: при таком количестве сервисов попытка показать всё на одной диаграмме физически невозможна; единственный рабочий подход - дисциплина уровней.
Spotify. Знаменитая «Squad model» Spotify (engineering.atspotify.com) принципиально про организационный дизайн, а не про диаграммы, но в инженерных публикациях Spotify сами архитектурные диаграммы тоже структурируются по уровням близко к C4: верхний уровень - бизнес-домены и их интерфейсы, средний - сервисы внутри домена, нижний - внутренняя структура отдельных сервисов. Это дополнительная иллюстрация того же тезиса: модель уровней работает на масштабе организации, а не только на масштабе одного приложения.
Стилизованный антипример. Стилизованный пример на основе типичных паттернов: команда из 30 инженеров поддерживает «архитектурный wiki», в котором лежит одна большая диаграмма «Overall Architecture» в Lucidchart, нарисованная два года назад техлидом, который с тех пор ушёл. Диаграмма показывает 40 прямоугольников (микросервисы, базы, очереди) на одном холсте; уровни не разделены. Каждый новый разработчик видит её при онбординге, ничего не понимает, идёт спрашивать у соседей. Через год команда обнаруживает, что 7 из 40 прямоугольников описывают сервисы, которых уже нет, ещё 5 - сервисы под другими именами, и обновлять диаграмму некому, потому что владелец один и он перегружен. Это типовой шаблон, который дисциплина C4 предотвращает не через инструмент, а через правило «одна диаграмма на zoom-уровень, диаграмма живёт в репо рядом с кодом».
Сравнение полезно: c4model.com показывает, как должно быть; AWS показывает, как иерархия работает в публичной коммуникации; Atlassian и Monzo - как она встраивается в процесс; Spotify - как она применяется на масштабе организации; антипример - что бывает, если ни одного из этих принципов нет. Все вместе они формируют один тезис: дело не в выборе нотации, а в наличии дисциплины уровней.
Diagrams as Code в production
Любая диаграмма, которая не лежит в version control и не редактируется через PR, обречена устареть. Это не идеологический тезис, а эмпирическое наблюдение: визуальный редактор (Visio, Lucidchart, draw.io) удобен для одноразовой иллюстрации в slide deck, но не подходит для долгоживущей документации. Причины: нет diff-а, нет review, нет автоматического обновления при изменении кода, нет owner-а, который заметит расхождение. Через квартал диаграмма расходится с реальностью настолько, что становится дезинформацией.
Diagrams as Code решает эту проблему за счёт текстового исходника, который живёт в том же репозитории, что и код:
- Версионирование в Git. Каждое изменение диаграммы фиксируется коммитом, у которого есть автор, дата и сообщение.
- Code review через PR. Диаграмма меняется тем же процессом, что и код; рецензент видит diff и может оспорить решение.
- Связь с изменением, которое её мотивировало. Если PR добавляет новый сервис, в том же PR обновляется Container-диаграмма. Расхождение становится заметно при review.
- Единый источник правды. Не возникает вопроса «какая версия актуальная» - актуальная та, что в main.
- Автоматический рендеринг в CI. Из текстового исходника собирается PNG/SVG, который публикуется в README, на сайт документации или в pages.
Я использую PlantUML с C4 extension - библиотекой макросов от Ricardo Niepel, которая добавляет в PlantUML синтаксис C4 (Person, System, Container, Component, Rel и т. д.). Пример Context-диаграммы:
@startuml
!include <C4/C4_Context>
title My Platform - System Context
Person(employee, "Employee", "Firm user")
Person(client, "Client", "End user")
System(platform, "Platform", "Main system")
System_Ext(payments, "Payment Provider", "Processes payments")
System_Ext(email, "Email Service", "Sends notifications")
Rel(employee, platform, "Manages operations")
Rel(client, platform, "Uses services")
Rel(platform, payments, "Processes payments", "HTTPS")
Rel(platform, email, "Sends emails", "SMTP")
@enduml
Какие диаграммы создавать
| Диаграмма | Рекомендация |
|---|---|
| System Context | Да - для каждой системы |
| Container | Да - для каждой системы |
| Component | По необходимости |
| Code | Редко, только для сложных частей |
| Deployment | Да - как минимум для production |
Инструменты
- Structurizr DSL - DSL и инструмент от самого Саймона Брауна, спроектированный специально под C4. Самый «канонический» вариант, поддерживает single source of truth для нескольких диаграмм одной системы.
- PlantUML + C4 macro library - библиотека Ricardo Niepel поверх PlantUML; мой выбор, отлично интегрируется с CI/CD, рендерится локально и в Docker.
- Mermaid C4 - C4 diagrams, рендерится прямо в GitHub/GitLab markdown без отдельного pipeline. Удобно для README.
- Graphviz - не C4-специфичный, но удобный для генерации диаграмм из метаданных кода.
- draw.io / Lucidchart - визуальные редакторы для команд, которые не готовы к Diagrams as Code. Подходят для разовых иллюстраций; для долгоживущей документации проигрывают text-based инструментам.
Советы
- Начинайте с Context - это фундамент понимания.
- Не смешивайте уровни - каждая диаграмма должна быть на одном уровне абстракции.
- Включайте легенду - особенно если используете нестандартные обозначения или иконки облачных провайдеров.
- Обновляйте регулярно - устаревшая диаграмма хуже, чем её отсутствие.
- Diagrams as code - версионируйте вместе с кодом, ревьюйте через PR.
- Монолит vs Микросервисы - когда какая архитектура подходит.
- Когда переходить на Kubernetes - примитивы как словарь общения с платформой; перекликается с примитивами C4 как словарём общения об архитектуре.
- Системный менеджмент - закон Конвея и связь между структурой команды и структурой системы, которая видна в C4.
Источники
Первоисточники по C4 и архитектурной коммуникации
- c4model.com - официальный сайт модели; автор Simon Brown. Каноническое описание уровней, FAQ, example bank.
- Simon Brown. Software Architecture for Developers (Leanpub, 2014, постоянно обновляется). Развёрнутое объяснение, откуда взялась модель и какие проблемы UML-эпохи она решает.
- Grady Booch. Object Solutions: Managing the Object-Oriented Project (Addison-Wesley, 1996). Levels of abstraction как фундаментальная инженерная дисциплина.
- Eric Evans. Domain-Driven Design (Addison-Wesley, 2003). Bounded context как способ зафиксировать уровень обсуждения; концептуально близко к C4 System Landscape.
- Vaughn Vernon. Implementing Domain-Driven Design (Addison-Wesley, 2013). Context maps - визуальный язык для соотношения нескольких bounded contexts.
- Mark Richards, Neal Ford. Software Architecture: The Hard Parts (O'Reilly, 2021). Архитектурные решения по уровням и цена смешивания уровней.
- Michael Nygard. Documenting Architecture Decisions (cognitect.com, 2011). Оригинальный пост про ADR; естественный спутник C4-диаграмм.
Реальные примеры и case studies
- Structurizr - DSL и платформа для C4 от автора модели; включает example bank с полными комплектами диаграмм для эталонных систем.
- AWS Reference Architectures - публичная библиотека иерархических архитектурных диаграмм; не используют C4-нотацию, но дисциплина уровней узнаваема.
- Atlassian Engineering Blog - публикации про практику ADR и архитектурную документацию.
- Monzo Engineering Blog - архитектура микросервисов на масштабе 1500+ сервисов; иерархическое описание системы в постах и выступлениях.
- Spotify Engineering - публикации про архитектуру и Squad-модель.
Инструменты Diagrams as Code
- PlantUML standard library - включает C4 macro library от Ricardo Niepel.
- C4-PlantUML на GitHub - исходники макросов и примеры использования.
- Mermaid C4 - C4-синтаксис в Mermaid; рендерится в GitHub/GitLab markdown.
- Graphviz - универсальный движок для генерации диаграмм из текстового описания.
- draw.io - визуальный редактор для команд, которые ещё не на Diagrams as Code.