Если возникает вопрос об описании архитектуры системы, то есть несколько основных решений где и как это сделать. Популярные нотации для визуализации схем архитектуры:
C4,
ArchiMate,
SysML,
4+1,
AADL.
В этой статье я хочу сфокусироваться на нотации моделирования архитектуры C4. Моя цель — показать практические примеры её применения, который вы сможете использовать как ориентир в своей работе, а также инструменты для её создания.
В конце статьи я оставлю список источников, в которых можно будет посмотреть дополнительную теорию и примеры.
Статья полезна для системных аналитиков, архитекторов, разработчиков, менеджеров проектов и тех, кто участвует в создании и принятии решений по организации архитектуры проекта.
Теория по нотации C4
Нотация моделирования C4 — это метод визуализации архитектуры программного обеспечения, разработанный Саймоном Брауном. Она используется для создания диаграмм, описывающих архитектуру систем.
C4 появилась как реакция на сложность и непонятность традиционных архитектурных диаграмм. Саймон Браун предложил этот подход в начале 2010-х годов с целью упростить понимание архитектуры для всех участников команды разработки, включая разработчиков, тестировщиков, аналитиков, менеджеров и других заинтересованных сторон.
Название "C4" расшифровывается как:
Context - Контекст,
Containers - Конейнеры,
Components - Компоненты,
Code - Код.
Эти четыре "C" представляют четыре уровня абстракции (представления), которые используются в этой нотации для визуализации архитектуры.
Уровни представления архитектуры в нотации C4 в примерах
Краткое и наглядное описание для одного проета: схема C4 в Miro c примером проекта.
Для этой статьи визуализацию сделаю с помощью кода и инструмента https://www.structurizr.com/dsl.
???? Context
Показывает, как система взаимодействует с внешними сущностями (пользователями, внешними системами). Сразу видно интеграции.
Обычно используют на начальных этапах проектирования, для понимания общего контекста.
Элементы:
- системы,
- пользователи,
- взаимосвязи.
Пример проекта:
Сервис-агрегатор GetDelivery из моего канала для системных аналитиков, где я разбираю на практике задачи по проектированию систем.
Context - код для https://www.structurizr.com/dsl
workspace {
model {
user = person "Клиент" "Использует приложение GetDelivery."
admin = person "Администратор" "Управляет приложением GetDelivery."
GetDelivery = softwareSystem "GetDelivery" "Сервис доставки." {
webApp = container "Web-приложение" "Интерфейс для клиентов." "Web Application"
mobileAppiOS = container "Mobile App iOS" "iOS приложение для клиентов." "iOS"
mobileAppAndroid = container "Mobile App Android" "Android приложение для клиентов." "Android"
adminWebApp = container "Web App Admin" "Интерфейс для администраторов." "Web Application"
backend = container "Backend" "Обрабатывает бизнес-логику." "Server-side Application"
database = container "База данных" "Хранит информацию о заказах, пользователях и т.д." "Database"
userDatabase = container "База данных пользователей" "Хранит данные пользователей." "Database"
reportStorage = container "Файловое хранилище отчетов" "Хранит PDF отчеты." "File Storage"
logicService = container "Сервис основной логики" "Обрабатывает основные функции системы." "Server-side Application"
deliveryIntegrationService = container "Сервис интеграций с сервисами доставки" "Интеграция с СДЭК, Возовоз, Деловые Линии." "Server-side Application"
authService = container "Сервис авторизации и регистрации пользователей" "Управляет авторизацией и регистрацией." "Server-side Application"
reportService = container "Сервис генерации отчетов" "Генерирует PDF отчеты." "Server-side Application"
}
cdek = softwareSystem "СДЭК" "Система доставки."
vozovoz = softwareSystem "Возовоз" "Система доставки."
delovieLinii = softwareSystem "Деловые Линии" "Система доставки."
user -> webApp "Использует"
user -> mobileAppiOS "Использует"
user -> mobileAppAndroid "Использует"
admin -> adminWebApp "Использует"
webApp -> backend "Взаимодействует"
mobileAppiOS -> backend "Взаимодействует"
mobileAppAndroid -> backend "Взаимодействует"
adminWebApp -> backend "Взаимодействует"
backend -> database "Использует"
backend -> userDatabase "Использует"
backend -> logicService "Использует"
backend -> deliveryIntegrationService "Использует"
backend -> authService "Использует"
backend -> reportService "Использует"
logicService -> reportStorage "Сохраняет отчеты"
reportService -> reportStorage "Сохраняет отчеты"
deliveryIntegrationService -> cdek "Интеграция"
deliveryIntegrationService -> vozovoz "Интеграция"
deliveryIntegrationService -> delovieLinii "Интеграция"
}
views {
systemContext GetDelivery {
include *
autolayout lr
}
theme default
}
}
Пример проекта сервис-агрегатор для расчета наиболее выгодной стоимости доставки GetDelivery.
???? Container
Описывает верхнеуровневую архитектуру и технологии. Используется для понимания технологического стека и разделения зон ответственности.
Элементы:
- контейнеры (например, веб-приложения, базы данных),
- взаимосвязи,
- технологии.
Пример проекта: Сервис-агрегатор GetDelivery из моего канала для системных аналитиков, где я разбираю на практике задачи по проектированию систем.
Container - код для https://www.structurizr.com/dsl
workspace {
model {
user = person "Клиент" "Использует приложение GetDelivery."
admin = person "Администратор" "Управляет приложением GetDelivery."
GetDelivery = softwareSystem "GetDelivery" "Сервис доставки." {
webApp = container "Web-приложение" "Интерфейс для клиентов." "Web Application"
mobileAppiOS = container "Mobile App iOS" "iOS приложение для клиентов." "iOS"
mobileAppAndroid = container "Mobile App Android" "Android приложение для клиентов." "Android"
adminWebApp = container "Web App Admin" "Интерфейс для администраторов." "Web Application"
backend = container "Backend" "Обрабатывает бизнес-логику, содержит сервисы и базы данных." "Server-side Application"
}
cdek = softwareSystem "СДЭК" "Система доставки."
vozovoz = softwareSystem "Возовоз" "Система доставки."
delovieLinii = softwareSystem "Деловые Линии" "Система доставки."
user -> webApp "Использует"
user -> mobileAppiOS "Использует"
user -> mobileAppAndroid "Использует"
admin -> adminWebApp "Использует"
webApp -> backend "API"
mobileAppiOS -> backend "API"
mobileAppAndroid -> backend "API"
adminWebApp -> backend "API"
backend -> cdek "HTTPS/JSON"
backend -> vozovoz "HTTPS/JSON"
backend -> delovieLinii "HTTPS/JSON"
}
views {
container GetDelivery {
include *
autolayout lr
}
theme default
}
}
???? Component
Детализирует структуру внутри контейнера системы, т.е. описывает более детально только один контейнер из предыдущего уровня.
Используется для проектирования и документирования внутренней структуры компонентов системы.
Элементы:
- компоненты,
- взаимосвязи,
- технологии,
- зависимости.
Пример проекта: Сервис-агрегатор GetDelivery из моего канала для системных аналитиков, где я разбираю на практике задачи по проектированию систем.
Про возможности Structurizr
Дополнительно для этой диаграммы хочу взять пример из официальной документации, чтобы вы увидели, как многослойно и красиво всё может быть сделано кодом в рамках одной схемы.
Пример кода диаграммы Component и других уровней
/*
* This is a combined version of the following workspaces, with automatic layout enabled:
*
* - "Big Bank plc - System Landscape" (https://structurizr.com/share/28201/)
* - "Big Bank plc - Internet Banking System" (https://structurizr.com/share/36141/)
*/
workspace "Big Bank plc" "This is an example workspace to illustrate the key features of Structurizr, via the DSL, based around a fictional online banking system." {
model {
customer = person "Personal Banking Customer" "A customer of the bank, with personal bank accounts." "Customer"
group "Big Bank plc" {
supportStaff = person "Customer Service Staff" "Customer service staff within the bank." "Bank Staff"
backoffice = person "Back Office Staff" "Administration and support staff within the bank." "Bank Staff"
mainframe = softwaresystem "Mainframe Banking System" "Stores all of the core banking information about customers, accounts, transactions, etc." "Existing System"
email = softwaresystem "E-mail System" "The internal Microsoft Exchange e-mail system." "Existing System"
atm = softwaresystem "ATM" "Allows customers to withdraw cash." "Existing System"
internetBankingSystem = softwaresystem "Internet Banking System" "Allows customers to view information about their bank accounts, and make payments." {
singlePageApplication = container "Single-Page Application" "Provides all of the Internet banking functionality to customers via their web browser." "JavaScript and Angular" "Web Browser"
mobileApp = container "Mobile App" "Provides a limited subset of the Internet banking functionality to customers via their mobile device." "Xamarin" "Mobile App"
webApplication = container "Web Application" "Delivers the static content and the Internet banking single page application." "Java and Spring MVC"
apiApplication = container "API Application" "Provides Internet banking functionality via a JSON/HTTPS API." "Java and Spring MVC" {
signinController = component "Sign In Controller" "Allows users to sign in to the Internet Banking System." "Spring MVC Rest Controller"
accountsSummaryController = component "Accounts Summary Controller" "Provides customers with a summary of their bank accounts." "Spring MVC Rest Controller"
resetPasswordController = component "Reset Password Controller" "Allows users to reset their passwords with a single use URL." "Spring MVC Rest Controller"
securityComponent = component "Security Component" "Provides functionality related to signing in, changing passwords, etc." "Spring Bean"
mainframeBankingSystemFacade = component "Mainframe Banking System Facade" "A facade onto the mainframe banking system." "Spring Bean"
emailComponent = component "E-mail Component" "Sends e-mails to users." "Spring Bean"
}
database = container "Database" "Stores user registration information, hashed authentication credentials, access logs, etc." "Oracle Database Schema" "Database"
}
}
# relationships between people and software systems
customer -> internetBankingSystem "Views account balances, and makes payments using"
internetBankingSystem -> mainframe "Gets account information from, and makes payments using"
internetBankingSystem -> email "Sends e-mail using"
email -> customer "Sends e-mails to"
customer -> supportStaff "Asks questions to" "Telephone"
supportStaff -> mainframe "Uses"
customer -> atm "Withdraws cash using"
atm -> mainframe "Uses"
backoffice -> mainframe "Uses"
# relationships to/from containers
customer -> webApplication "Visits bigbank.com/ib using" "HTTPS"
customer -> singlePageApplication "Views account balances, and makes payments using"
customer -> mobileApp "Views account balances, and makes payments using"
webApplication -> singlePageApplication "Delivers to the customer's web browser"
# relationships to/from components
singlePageApplication -> signinController "Makes API calls to" "JSON/HTTPS"
singlePageApplication -> accountsSummaryController "Makes API calls to" "JSON/HTTPS"
singlePageApplication -> resetPasswordController "Makes API calls to" "JSON/HTTPS"
mobileApp -> signinController "Makes API calls to" "JSON/HTTPS"
mobileApp -> accountsSummaryController "Makes API calls to" "JSON/HTTPS"
mobileApp -> resetPasswordController "Makes API calls to" "JSON/HTTPS"
signinController -> securityComponent "Uses"
accountsSummaryController -> mainframeBankingSystemFacade "Uses"
resetPasswordController -> securityComponent "Uses"
resetPasswordController -> emailComponent "Uses"
securityComponent -> database "Reads from and writes to" "SQL/TCP"
mainframeBankingSystemFacade -> mainframe "Makes API calls to" "XML/HTTPS"
emailComponent -> email "Sends e-mail using"
deploymentEnvironment "Development" {
deploymentNode "Developer Laptop" "" "Microsoft Windows 10 or Apple macOS" {
deploymentNode "Web Browser" "" "Chrome, Firefox, Safari, or Edge" {
developerSinglePageApplicationInstance = containerInstance singlePageApplication
}
deploymentNode "Docker Container - Web Server" "" "Docker" {
deploymentNode "Apache Tomcat" "" "Apache Tomcat 8.x" {
developerWebApplicationInstance = containerInstance webApplication
developerApiApplicationInstance = containerInstance apiApplication
}
}
deploymentNode "Docker Container - Database Server" "" "Docker" {
deploymentNode "Database Server" "" "Oracle 12c" {
developerDatabaseInstance = containerInstance database
}
}
}
deploymentNode "Big Bank plc" "" "Big Bank plc data center" "" {
deploymentNode "bigbank-dev001" "" "" "" {
softwareSystemInstance mainframe
}
}
}
deploymentEnvironment "Live" {
deploymentNode "Customer's mobile device" "" "Apple iOS or Android" {
liveMobileAppInstance = containerInstance mobileApp
}
deploymentNode "Customer's computer" "" "Microsoft Windows or Apple macOS" {
deploymentNode "Web Browser" "" "Chrome, Firefox, Safari, or Edge" {
liveSinglePageApplicationInstance = containerInstance singlePageApplication
}
}
deploymentNode "Big Bank plc" "" "Big Bank plc data center" {
deploymentNode "bigbank-web***" "" "Ubuntu 16.04 LTS" "" 4 {
deploymentNode "Apache Tomcat" "" "Apache Tomcat 8.x" {
liveWebApplicationInstance = containerInstance webApplication
}
}
deploymentNode "bigbank-api***" "" "Ubuntu 16.04 LTS" "" 8 {
deploymentNode "Apache Tomcat" "" "Apache Tomcat 8.x" {
liveApiApplicationInstance = containerInstance apiApplication
}
}
deploymentNode "bigbank-db01" "" "Ubuntu 16.04 LTS" {
primaryDatabaseServer = deploymentNode "Oracle - Primary" "" "Oracle 12c" {
livePrimaryDatabaseInstance = containerInstance database
}
}
deploymentNode "bigbank-db02" "" "Ubuntu 16.04 LTS" "Failover" {
secondaryDatabaseServer = deploymentNode "Oracle - Secondary" "" "Oracle 12c" "Failover" {
liveSecondaryDatabaseInstance = containerInstance database "Failover"
}
}
deploymentNode "bigbank-prod001" "" "" "" {
softwareSystemInstance mainframe
}
}
primaryDatabaseServer -> secondaryDatabaseServer "Replicates data to"
}
}
views {
systemlandscape "SystemLandscape" {
include *
autoLayout
}
systemcontext internetBankingSystem "SystemContext" {
include *
animation {
internetBankingSystem
customer
mainframe
email
}
autoLayout
description "The system context diagram for the Internet Banking System."
properties {
structurizr.groups false
}
}
container internetBankingSystem "Containers" {
include *
animation {
customer mainframe email
webApplication
singlePageApplication
mobileApp
apiApplication
database
}
autoLayout
description "The container diagram for the Internet Banking System."
}
component apiApplication "Components" {
include *
animation {
singlePageApplication mobileApp database email mainframe
signinController securityComponent
accountsSummaryController mainframeBankingSystemFacade
resetPasswordController emailComponent
}
autoLayout
description "The component diagram for the API Application."
}
image mainframeBankingSystemFacade "MainframeBankingSystemFacade" {
image https://raw.githubusercontent.com/structurizr/examples/main/dsl/big-bank-plc/internet-banking-system/mainframe-banking-system-facade.png
title "[Code] Mainframe Banking System Facade"
}
dynamic apiApplication "SignIn" "Summarises how the sign in feature works in the single-page application." {
singlePageApplication -> signinController "Submits credentials to"
signinController -> securityComponent "Validates credentials using"
securityComponent -> database "select * from users where username = ?"
database -> securityComponent "Returns user data to"
securityComponent -> signinController "Returns true if the hashed password matches"
signinController -> singlePageApplication "Sends back an authentication token to"
autoLayout
description "Summarises how the sign in feature works in the single-page application."
}
deployment internetBankingSystem "Development" "DevelopmentDeployment" {
include *
animation {
developerSinglePageApplicationInstance
developerWebApplicationInstance developerApiApplicationInstance
developerDatabaseInstance
}
autoLayout
description "An example development deployment scenario for the Internet Banking System."
}
deployment internetBankingSystem "Live" "LiveDeployment" {
include *
animation {
liveSinglePageApplicationInstance
liveMobileAppInstance
liveWebApplicationInstance liveApiApplicationInstance
livePrimaryDatabaseInstance
liveSecondaryDatabaseInstance
}
autoLayout
description "An example live deployment scenario for the Internet Banking System."
}
styles {
element "Person" {
color #ffffff
fontSize 22
shape Person
}
element "Customer" {
background #08427b
}
element "Bank Staff" {
background #999999
}
element "Software System" {
background #1168bd
color #ffffff
}
element "Existing System" {
background #999999
color #ffffff
}
element "Container" {
background #438dd5
color #ffffff
}
element "Web Browser" {
shape WebBrowser
}
element "Mobile App" {
shape MobileDeviceLandscape
}
element "Database" {
shape Cylinder
}
element "Component" {
background #85bbf0
color #000000
}
element "Failover" {
opacity 25
}
}
}
}
Источник: https://github.com/structurizr/examples/tree/main/dsl (big-bank-pic)
Если скопируете код и вставите в https://www.structurizr.com/dsl, то увидете следующее:
Дополнительный пример уровня Component из Miro для проекта Зоомагазина:
???? Code
Показывает детали реализации отдельных компонентов.
Используется для документирования структуры кода. На практике не используется, т.к. разработчикам это не надо. Это как диаграмма классов UML: вроде полезно понимать, а по факту не нужна.
Элементы:
- классы,
- интерфейсы,
- отношения между ними.
Пример можно посмотреть на сайте автора нотации - Саймона Брауна по банковскому проекту.
Где создавать схемы C4 - инструменты
Для создания схем в нотации C4 можно использовать:
графические инструменты,
инструменты визуализации через код (+ ChatGPT).
Использование инструментов, которые позволяют описывать C4 через код, позволяют ускорить процесс за счет использования искусственного интеллекта - ChatGPT или аналог.
1. Draw.io — графический инструмент
Draw.io (diagrams.net) — это бесплатный онлайн-инструмент, который подходит для создания различных видов диаграмм, включая C4. Он предоставляет широкий набор элементов дизайна, что делает его удобным для быстрого создания диаграмм.
Есть минусы в редактировании, когда на диаграмме много элементов: бывает, что перемещаешь не то что хотел, или не так, как хотел.
Плюсы:
+ Бесплатный;
+ Есть все виды диаграмм;
+ Есть интеграция с Confluence, Google Drive и другими постоянно используемыми программами.
Минусы:
- Большие схемы приводят к страданиями при редактировании. Это проблема всех графических редакторов.
Заключение:
Если у меня стоит задача отрисовать схему архитектуры в нотации C4 через графический инструмент, то я буду это делать в Draw.io. В GetAnalyst используем этот инструмент как основной.
Как включить C4 в Draw.io
2. Miro — графический инструмент
Miro — это онлайн-платформа для визуального создания и обсуждения проектов на электронных досках, которая также может быть использована для создания C4 диаграмм.
Для использования Miro в качестве средства визуализации схемы архитектуры, я рекомендую вам взять мой шаблон Miro с элементами C4 и копировать элементы из него.
Плюсы:
+ Есть интеграция с Confluence, Google Drive и другими постоянно используемыми программами.
+ Приятный и удобный интерфейс, более современно выглядит, чем Draw.io.
Минусы:
- Ограничение на количество бесплатных досок, поэтому условно платный.
- Большие схемы приводят к страданиями при редактировании.
- Элементы C4 не стандартные для Miro, что может приводить к проблемам при редактировании.
Заключение:
При сравнении опыта работы с Miro и Draw.io, я остаюсь сторонником более простого и удобного Draw.io, так как для Miro возможность отрисовки C4 скорее неожиданная опция, чем удобная фича.
3. Microsoft Visio — графический инструмент
Microsoft Visio от Microsoft — это профессиональное решение для создания сложных диаграмм. Аналогичен по функциональности Draw.io, и скорее всего шаблоны элементов C4 придётся сначала создать, как в Miro.
Плюсы:
+ Распространен в IT-компаниях.
Минусы:
- Платный.
- Работа в оффлайн, хотя для кого-то это может быть и плюсом.
- Не предназначен для C4.
Заключение:
Я выберу draw.io, так как несколько лет не открывала Visio и у меня уже больше года не Windows.
4. Structurizr — инструмент визуализации через код
Structurizr — это один из самых специализированных инструментов для создания диаграмм C4. Structurizr позволяет определять их через код, что обеспечивает высокую гибкость и точность в описании архитектуры.
Чтобы использовать Structurizr для описания архитектуры в нотации C4:
Используйте онлайн-интерфейс с редактором DSL: https://www.structurizr.com/dsl.
Напишите или вставьте приведенный ниже код в редактор Structurizr.
Нажмите "Render" справа сверху, над панелью с кодом, чтобы увидеть вашу диаграмму.
Плюсы:
+ Бесплатный.
+ Удобный в использовании.
+ Понятный язык разметки, которым "рисовать".
+ Поддерживает генерацию кода через искусственный интеллект (ChatGPT).
+ Визуально простой и понятный.
+ Чистый интерфейс - нет мусорной рекламы.
+ Можно даже писать на Java код для визуализации.
+ Потрясающая база знаний с примерами на английском языке.
Минусы:
- Могут быть сложности с визуализацией больших диаграмм.
Заключение:
Брать и использовать.
Примеры кода для Structurizr - Context
Код для диаграммы на уровне Context:
workspace {
model {
user = person "Пользователь" "Описание пользователя."
bankingSystem = softwareSystem "Банковская Система" "Описание банковской системы."
user -> bankingSystem "Использует" "HTTPS"
}
views {
systemContext bankingSystem {
include *
autoLayout lr
}
theme default
}
}
Этот код создает диаграмму контекста с двумя элементами:
"Пользователь" (отображается как
Person
в PlantUML), который взаимодействует с системой."Банковская Система" (отображается как
System
), которая представляет собой внешнюю систему, с которой взаимодействует пользователь.
Между этими элементами устанавливается связь с описанием "Использует" и протоколом "HTTPS".
Примеры кода для Structurizr - Container
Код для уровня Container:
workspace {
model {
user = person "Пользователь" "Описание пользователя."
bankingSystem = softwareSystem "Банковская Система" {
webApp = container "Веб-приложение" "Предоставляет банковские услуги онлайн." "Java"
db = container "База Данных" "Хранит данные о счетах и транзакциях." "MySQL"
api = container "API" "Предоставляет API для доступа к данным." "RESTful"
}
user -> webApp "Использует" "HTTPS"
webApp -> db "Читает/записывает" "JDBC"
api -> db "Запрашивает" "JDBC"
}
views {
container bankingSystem {
include *
autoLayout lr
}
theme default
}
}
Этот код создаёт диаграмму контейнеров внутри системы "Банковская Система". Здесь мы видим:
Пользователь, который взаимодействует с веб-приложением.
-
В Банковской Системе теперь определены три контейнера:
Веб-приложение: Представляет собой пользовательский интерфейс, написанный на Java.
База Данных: MySQL база данных, хранящая информацию.
API: RESTful API для доступа к данным базы.
Примеры кода для Structurizr - Component
Детализирует контейнер "Веб-приложение" из предыдущего примера.
В этом примере мы фокусируемся на компонентах внутри "Веб-приложения":
Также показаны связи между этими компонентами, а также их взаимодействие с внешними контейнерами, такими как "API" и физическая "База Данных".
Код для уровня Component:
workspace {
model {
user = person "Пользователь" "Описание пользователя."
bankingSystem = softwareSystem "Банковская Система" {
webApp = container "Веб-приложение" {
ui = component "Пользовательский Интерфейс" "Angular, Предоставляет веб-интерфейс для пользователей."
server = component "Серверная Логика" "Spring Boot, Обрабатывает запросы от пользовательского интерфейса."
databaseComponent = component "Компонент Базы Данных" "JPA/Hibernate, Обеспечивает доступ к данным."
}
api = container "API" "RESTful, Предоставляет API для доступа к данным."
db = container "База Данных" "MySQL, Хранит данные о счетах и транзакциях."
user -> ui "Использует" "HTTPS"
ui -> server "Вызывает" "JSON/HTTP"
server -> databaseComponent "Использует" "JDBC"
server -> api "Делает запросы" "JSON/HTTP"
databaseComponent -> db "Читает/Записывает" "JDBC"
}
}
views {
component webApp {
include *
autoLayout lr
}
theme default
}
}
5. PlantUML — инструмент визуализации через код
PlantUML — это инструмент, который позволяет создавать UML-диаграммы из текстового описания. Он поддерживает синтаксис для создания диаграмм C4, но работает с перебоями - периодически не поддерживает загрузку визуализатора по ссылке и выдаёт ошибку. Поэтому рекомендую использовать только от большой любви к PlantUML.
Плюсы:
+ Можно аккуратно визуализировать диаграммы через код.
Минусы:
- Работает нестабильно.
Заключение:
Structurizr лучше подходит для создания C4-диаграмм через код.
Чтобы использовать PlantUML для описания архитектуры в нотации C4:
Используйте онлайн-интерфейс PlantUML, такой как PlantText или онлайн-редактор PlantUML на сайте plantuml.com.
Напишите или вставьте приведенный ниже код в редактор PlantUML.
Диаграмма будет автоматически сгенерирована на основе этого текстового описания. Либо нажмите "Submit".
*В случае проблем с отображением из-за недоступности URL https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml внутри PlantUML смените браузер или переключитесь несколько раз между дневным и ночным режимами (переключатель справа от кнопки "Submit").
Примеры кода для PlantUML
Context
Пример кода на PlantUML для диаграммы на уровне Context:
@startuml C4_Example
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml
LAYOUT_WITH_LEGEND()
Person(user, "Пользователь", "Описание пользователя.")
System(bankingSystem, "Банковская Система", "Описание банковской системы.")
Rel(user, bankingSystem, "Использует", "HTTPS")
@enduml
*Если не увидете диаграмму сразу, переключитесь в темную/светлую тему или смените браузер. Бывают проблемы с установкой соединения.
Container
Код для уровня Container:
@startuml C4_Containers
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml
LAYOUT_WITH_LEGEND()
Person(user, "Пользователь", "Описание пользователя.")
System_Boundary(bankingSys, "Банковская Система") {
Container(webApp, "Веб-приложение", "Java", "Предоставляет банковские услуги онлайн.")
Container(db, "База Данных", "MySQL", "Хранит данные о счетах и транзакциях.")
Container(api, "API", "RESTful", "Предоставляет API для доступа к данным.")
}
Rel(user, webApp, "Использует", "HTTPS")
Rel(webApp, db, "Читает/записывает", "JDBC")
Rel(api, db, "Запрашивает", "JDBC")
@enduml
Component
Детализируем "Веб-приложение" из предыдущего примера. Код для уровня Component:
@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml
LAYOUT_WITH_LEGEND()
Container_Boundary(webApp, "Веб-приложение") {
Component(ui, "Пользовательский Интерфейс", "Angular", "Предоставляет веб-интерфейс для пользователей.")
Component(server, "Серверная Логика", "Spring Boot", "Обрабатывает запросы от пользовательского интерфейса.")
Component(database, "База Данных", "JPA/Hibernate", "Обеспечивает доступ к данным.")
}
Container(api, "API", "RESTful", "Предоставляет API для доступа к данным.")
Container(db, "База Данных", "MySQL", "Хранит данные о счетах и транзакциях.")
Person(user, "Пользователь", "Описание пользователя.")
Rel(user, ui, "Использует", "HTTPS")
Rel(ui, server, "Вызывает", "JSON/HTTP")
Rel(server, database, "Использует", "JDBC")
Rel(server, api, "Делает запросы", "JSON/HTTP")
Rel(database, db, "Читает/Записывает", "JDBC")
@enduml
Выводы
Выбор инструмента зависит от личных предпочтений, требований проекта и уровня комфорта в работе с конкретными инструментами. Некоторые предпочитают инструменты с графическим интерфейсом для более интуитивного процесса, в то время как другие могут выбрать кодовые инструменты для большей автоматизации и точности.
Я рекомендую для создания диаграммы C4 инструменты Draw.io и Structurizr.
Заключение
Я считаю C4 наиболее понятной и доступной нотацией моделирования архитектуры, которая помогает команде разработки. Диаграммы легко читаются всеми участниками за счет того, что содержат ограниченный набор обозначений.
Сама в практике, как системный аналитик, я также часто использую упрощенные модели, базирующиеся на C4, когда нужно показать что-то большое. На больших схемах прямоугольники C4 занимают много пространства и становится затруднительно знакомиться со схемой на маленьком мониторе, да и на большом тоже.
Наиболее полезные уровни:
Context — общее представление, полезен для понимания внешних взаимодействий с системой - интеграций.
Container — устройство системы внутри, подходит для понимания какие есть веб-, мобильные, серверные, и другие виды приложений.
Component — идеально подходит для документирования архитектуры Backend, основной уровень описания архитектуры, который требует внимания на проекте.
Уровень кода Code считаю ненужной тратой времени. В роли системного аналитика проектирования структуры кода я не касаюсь, а документирование кода разработчиками в C4 или в диаграмме классов UML скорее вызовет у меня ощущение бюрократического шока, чем восхищение. Лучше комментарии нормальные оставить.
Дополнительно примеры схем архитектуры в можно посмотреть в моем канале в этом посте, и сверху-снизу от него.
Если вы хотите ввести стандарт документирования архитектуры в своей компании, то нотация C4 идеальна, чтобы начать с неё (а затем адаптировать под что-то своё, при необходимости).
Нотация C4 — мощный инструмент, обеспечивающий ясность и структурированность в процессе проектирования архитектуры систем. Эта нотация не только помогает архитекторам и разработчикам в создании целостного представления системы, но и способствует улучшению коммуникаций разработчиков и архитекторов с менеджерами проектов, аналитиками и другими заинтересованными сторонами.
Дополнительная информация
Теория и примеры
The C4 model for visualising software architecture
The C4 model and this website were created by Simon Brown
Первоисточник с теорией по нотации, где можно искать ответы на вопросы "как правильно...".-
Примеры архитектуры для интеграционных проектов:
Еще одна хорошая статья на Habr с аккуратным примером и теорией.
Как описать большую систему в нотации С4.
Инструменты
Пример схемы архитектуры проекта в Miro - интернет-зоомагазин
Екатерина Ананьева
Пример схемы архитектуры в нотации С4, на основе которого можно изучать нотацию и из которого можно переносить шаблоны элементов в свой собственный Miro.C4 Model with PlantUML (англ)
Huseyin Kutluca
Статья про возможность использования PlantUML для создания диаграмм в нотации C4. В ней можно взять дополнительные примеры для изучения и лучше понять подход к написанию кода.https://github.com/structurizr/examples/tree/main/dsl
База данных с примерами для инструмента structurizr, с помощью которого можно описывать диаграммы C4 через код.
Комментарии (4)
notffirk
08.12.2023 03:01+1Самое интересное начинается дальше, когда начинает появляется необходимость контроля версий, деление на слои, модули и их внутренние связи и согласованность
Тогда на помощь приходят системы для управления корпоративной архитектуры, такие как iserver и leanix и другие
Dmitriys88
08.12.2023 03:01Описание диаграмм кодом это пока очень грустно, так как autolayout пока что умеет работать с 4-5 квадратами и 8-10 стрелками. Когда их становится больше, а их всегда больше в реальных диаграммах реальных систем, то ты сначала вынужден тратить кучу времени на написание кода (это всегда дольше, чем в графическом редакторе из готового набора элементов drag'n'drop'ом вытянуть квадратик или стрелочку), а потом еще в 10 раз больше времени на то, чтобы потом все расставить так, чтобы это было хоть сколько-нибудь читаемо.
Также в вашем примере с GetDelivery на С2 и С3 все перемешалось в кучу. Поизучайте, что есть Container и что есть Component и как эти абстракции вкладываются друг в друга на диаграммах. Половина ваших компонент на уровне С3 это на самом деле контейнеры с уровня С2 (если не все вообще). Просто попробуйте запихнуть это в тот же structurizr, поймете о чем я????
Foxcool
Недавно открыл для себя mermaid как доступный способ кодом "рисовать" диаграммы. Поддерживаются различные виды, в том числе в бете поддреживаются С4 диаграммы. Автоматически рендерится в схемы на гитлабе, обсидиане. В вскод тоже работает, как минимум с установкой расширения (точно не помню). Т.е. можно без каких-либо отдельных инструментов вести ту же документацию сразу в гит-репозиториях в маркдауне и при этом не надо тащить картинками схемы - все изменения будут фиксироваться, как и изменения другого текста.