Привет! Меня зовут Михаил Пискунов, я более 15 лет занимаюсь разработкой, архитектурой и системной аналитикой.

В данной статье я хочу поделиться опытом и рассказать о том, как системным аналитикам улучшить Sequence-диаграммы (диаграммы последовательностей) с помощью лучших практик.

Многие системные аналитики не имеют опыта программирования и не знакомы с принципами Clean Code. В результате их диаграммы иногда получаются трудночитаемыми или неоптимальными.

Я покажу, как некоторые подходы из мира программирования (те самые best practices и идеи из Clean Code) помогают рисовать sequence-диаграммы чище и понятнее. 

Статья основана на личном опыте, не претендую на универсальность.?
Будем использовать понятные примеры на PlantUML, только практичные советы и наглядные примеры диаграмм.


Зачем уделять внимание качеству sequence-диаграмм?

Sequence-диаграммы - один из ключевых артефактов (документов) в проектной документации. Они показывают, как системы и компоненты взаимодействуют друг с другом во времени в рамках какого-то процесса. В микросервисной архитектуре такие диаграммы становятся особенно крайне важными. Их обычно много, и они описывают базовые интеграции между сервисами, фронтендом и внешними API. 

Хорошая sequence-диаграмма позволяет понять сценарий работы системы без чтения кода. Как я упоминал в статье "Что такое правильная документация проекта" на Хабре, такие диаграммы отображают последовательность запросов между сервисами и входят в минимальный набор документации по проекту.

Однако создание понятных диаграмм является не тривиальной задачей. В реальности системных аналитиков не учат тонкостям программирования. В вакансиях от аналитиков обычно не требуют знаний ООП и паттернов, и в целом аналитиков не обучают тому, что знают разработчики.

В США, как я выяснил и описал на Хабре в статье "Кто выполняет функции системного аналитика в США?", часто роль системного аналитика частично выполняют бизнес-аналитики, которым "по долгу службы" приходится рисовать UML-диаграммы (Use Case, Activity, Sequence). То есть, далеко не у всех, кто делает sequence-диаграммы, есть бэкграунд в разработке. Отсюда и появляются диаграммы с непонятными решениями, чрезмерно вложенными условными блоками, перегрузкой деталей, запутанными переходами.

Давайте разберём, как этого избежать. С начала проведу аналогии с кодом (Clean Code, Best Practices), потому что диаграммы и код должны говорить об одном и том же, просто разными языками. А потом ниже напишу практические рекомендации по оформлению диаграмм последовательностей, которые сделали мою документацию лучше.


"В моменте не отвечу... ПОЧИТАЙ ДОКУМЕНТАЦИЮ" (цитирую коллегу Диму ?)
"В моменте не отвечу... ПОЧИТАЙ ДОКУМЕНТАЦИЮ" (цитирую коллегу Диму ?)

Принципы Clean Code в мире системного анализа и sequence-диаграмм

Всё, что делает программист с именами функций или структурой классов, аналитик делает тоже самое с названиями участников, стрелками сообщений и логикой взаимодействий.

Давайте попробую объяснить каждый принцип Clean Code, но через призму системного аналитика, то есть на примерах sequence-диаграмм, а не кода.

  1. Первый принцип — понятные имена. На диаграмме это означает, что участники должны называться так, чтобы любому человеку было очевидно, что они делают. Если lifeline подписан как «Order Service», «Payment Provider» или «Email Notification», то даже без пояснений понятно, какую роль он играет.

  2. Следующий принцип — малые функции. В терминах диаграмм это означает, что каждая стрелка должна отражать ровно одно осмысленное действие. Если мы рисуем одно сообщение, которое одновременно валидирует заказ, проверяет запас и отправляет подтверждение, это эквиваленто большому методу в коде, который делает всё сразу. Намного лучше выразить такие шаги отдельными сообщениями (стрелками), чтобы диаграмма раскрывала бизнес‑логику последовательно, без скрытых действий внутри одной стрелки.

  3. Принцип минимизации дублирования тоже напрямую переносится в системный анализ. Бывает, что один и тот же набор взаимодействий повторяется в нескольких сценариях. Например, авторизация пользователя или проверка подписки. Если каждый раз перерисовывать этот фрагмент, то документация быстро становится несогласованной, а потом любое изменение приходится вносить в десяток мест на диаграмме. Перенос этого фрагмента в отдельную диаграмму, на которую можно сослаться, устраняет дублирование и делает систему описания чище.

  4. Простота структуры в диаграммах означает, что она не должна превращаться в объект, похожий на паутину из десятков участников и линий. Хорошая диаграмма показывает только те сущности, которые действительно участвуют в конкретном сценарии.
    Всё остальное (инфраструктурные сервисы, логирование, технические адаптеры) лучше вынести из неё, чтобы не размывать смысл. Если сценарий получается слишком большим, его корректно разбить на несколько диаграмм. Например, одну для основного успешного пути и отдельные для альтернативных веток или ошибок.

  5. Принцип выражающих намерение конструкций касается правильного использования элементов нотации. Если в сценарии есть ветвление, нужно явно показывать его через фрагмент alt, а не пытаться описать условие словесно. Если действие необязательно, то это opt. Если повторяется, то используем loop. Если происходит параллельно, то применяем par. Когда нотационные конструкции используются по назначению, диаграмма становится не набором стрелок, а чётким описанием поведения системы, где смысл читается без расшифровки.

  6. Комментировать в диаграммах стоит только то, что невозможно понять из самих сообщений и структуры. Если требуется указать важное бизнес‑правило, нормативное ограничение или специфическую договорённость с внешней системой, небольшая заметка действительно помогает. Но когда комментарии поясняют то, что можно было выразить самими именами сообщений или участниками, это признак того, что диаграмму стоит переработать, а не перегружать текстом.

  7. Последний принцип — «Код важнее комментариев». Он означает, что sequence‑диаграмма должна быть понятна без длинных пояснений сбоку. Если смысл взаимодействия читается из названий участников и сообщений, если каждый шаг выражает реальное действие, если структура диаграммы логична и чиста, то комментарии становятся редким исключением. Хорошая диаграмма может стоять сама по себе и быть понятной так же, как хороший чистый код.


Best Practices - это гораздо более широкое понятие
Best Practices - это гораздо более широкое понятие

Best Practices - это не просто набор правил

Когда говорят о Best Practices, сразу возникает ощущение чего‑то технического, связанного с кодом. Но на самом деле Best Practices — это гораздо более широкое понятие, поскольку это совокупность методов, подходов и стандартов, которые отрасль IT за десятилетия признала наиболее эффективными.

Они касаются не только того, как писать код, но и того, как команда проектирует систему, планирует работу, документирует сценарии, ведёт репозиторий, управляет качеством и развёртывает продукт. И системный аналитик тоже находится внутри этих процессов. Ведь диаграммы, требования, спецификации и архитектурные решения - это тоже часть общих практик в команде.

  1. С чего начнём? Например, код‑ревью — это не только про программистов. В системной аналитике тоже существует док‑ревью. Когда другой аналитик или архитектор смотрит вашу sequence‑диаграмму, проверяет, действительно ли события расположены логически, нет ли противоречий, корректно ли учтены альтернативы, и согласованы ли ваши диаграммы с соседними модулями. Док‑ревью помогает избежать ошибок, которые иначе вскрылись бы на поздних этапах, когда исправлять всё намного дороже.

  2. Единый стиль кодирования в мире разработки означает, что весь код выглядит одинаково. Для аналитиков это аналогично стандартизации и единообразию в документации. Это когда все диаграммы строятся в одной нотации UML, названия участников следуют единому шаблону, структура требований одинакова от одного документа к другому. Такие правила позволяют всей команде понимать документы друг друга, не тратя лишнее время на расшифровку.

  3. Принцип KISS (Keep It Simple, Stupid — «делай проще») в аналитической работе означает, что не стоит придумывать чрезмерно сложные схемы и сценарии. Если бизнес‑процесс можно описать пятью шагами, не нужно пытаться сделать из него «архитектурный шедевр» с множеством абстракций. Хорошая sequence‑диаграмма должна быть понятна менеджеру, тестировщику и программисту. Если вы чувствуете, что она стала сложнее, чем сам бизнес‑процесс, скорее всего нужно упростить модель.

  4. Принцип DRY (Don«t Repeat Yourself — „не повторяйся“) в документации означает избегание дублирования требований. Если несколько модулей проверяют авторизацию одинаково, логичнее вынести этот процесс в отдельный документ или общую диаграмму и ссылаться на неё. Иначе возникает риск, что где‑то требования изменятся, а где‑то останутся прежними — и появятся неявные расхождения.»

  5. Принципы SOLID чаще ассоциируется с объектно‑ориентированным программированием, но у системного аналитика есть свой эквивалент — разумное разбиение логики на независимые блоки, которые можно переиспользовать. Например, вы пишете спецификацию, где один сервис отвечает за валидацию данных, другой — за расчёт, третий — за доступы. Это позволяет команде понимать ответственность каждого компонента и уменьшает связанность.

  6. Юнит‑тесты в аналитике превращаются в «ясные критерии приёмки». Если требования сформулированы так, что их можно проверять автоматически, или хотя бы тестировщик может буквально галочками пройтись по всем условиям, — это хороший показатель качества. Неочевидные, расплывчатые требования — это эквивалент отсутствия тестов.

  7. Использование CI/CD для аналитика будет незаметным, но влияет на его работу прямо. Чем стабильнее pipeline выкатки (особенно, если Middle‑документация лежит в GIT), тем меньше необходимости переписывать требования «в спешке». А если документации достаточно, продуктовые и инфраструктурные изменения проходят гладко. Аналитик должен понимать, какие данные и процессы критичны и как они поведут себя на проде — это тоже часть best practice.

  8. Хранение секретов в.env‑файлах, Vault и защита конфиденциальной информации — это зона ответственности не только программиста. Аналитик должен убедиться, что в требованиях нет прямых значений токенов, паролей, ключей — иногда встречается, что кто‑то вставляет их как «пример». Это нарушение безопасности в документации, и что хуже — может попасть в корпоративный Confluence или Jira.

  9. Логирование и мониторинг тоже важная практика для аналитика, потому что он описывает, какие события система должна фиксировать, какие метрики показывают работоспособность процесса и какие ошибки должны быть видимы пользователю. Хорошие требования о логах позволяют не только тестировать систему эффективнее, но и сделать её прозрачной для эксплуатации, показывая здоровье сервиса в виде конкретных метрик.

  10. Наконец, линтеры и форматтеры — это аналог автоматической проверки качества. Для аналитических артефактов такую роль играют инструменты вроде автоматических проверок UML, валидации схем API, проверок корректности JSON‑запросов, генрация сниппетов. Четко описанные модели, которые проходят валидацию, — это гарантия, что разработчики получат корректную спецификацию.

Поэтому Best Practices не просто набор правил для программиста. Это единое поле стандартов, в котором живёт вся команда, включая аналитиков.

Clean Code относится только к качеству написания программы, а Best Practices охватывают всё: от архитектуры и документации до процессов и безопасности. Clean Code - это лишь маленький остров внутри огромной территории, которую аналитик тоже помогает поддерживать в порядке.


А теперь давайте перейдём поближе к практике и примерам на самих диаграммах…

Легенда и цвета диаграмм

Большая sequence-диаграмма с десятком участников может выглядеть как "стена серых прямоугольников". Глазам сложно сразу понять, где база данных, а где внешняя система, какие системы в одном кластере, а какие в другом. Поэтому я стараюсь использовать цветовую кодировку для разных типов участников и групп участников. Это маленький трюк, который здорово повышает читаемость.

 Согласитесь, так ведь понятнее? А теперь представьте, что боксов и выделений фоном не было бы… Скажем так, было бы гораздо менее информативно
Согласитесь, так ведь понятнее? А теперь представьте, что боксов и выделений фоном не было бы… Скажем так, было бы гораздо менее информативно

Совет: используйте переносы строк \n (как я на диаграмме выше) в длинных именах объектов и подписях. Диаграмма получится более компактной и не "разъедется" по горизонтали. Особенно это актуально, если названия систем или условия ветвлений длинные.

Цвета помогают с первого взгляда понять, какую роль играет каждый участник. Где база данных? А, вот зеленый прямоугольник. Где внешняя система? Вон бежевый на диаграмме. Группируя элементы по цветам, вы упрощаете восприятие диаграммы.

Отображение ошибок и исключений (alt vs break)

Перейдем к логике диаграмм. Частая проблема - отображение ошибок и исключений.

Как показать на диаграмме, что пошло что-то не так? Многие по привычке начинают рисовать это через условный блок alt (альтернатива): мол, если случилась ошибка, то делаем то-то, иначе - продолжаем процесс. Формально так можно, но получается довольно неуклюже.

Активное использование alt ведёт к тем же проблемам, что и множественные вложенные друг в друга if/else в виде "лесенки", в которой легко запутаться. Такой код даже прозвали "условный оператор из ада", это когда уровни вложенности образуют стрелку, уходящую вправо, и нормальный поток выполнения теряется из виду. То же самое происходит и с диаграммой, когда вы начинаете вкладывать один alt в другой. Читать такую диаграмму затруднительно, а основная логика тонет в ветвлениях.

Посмотрите пример, как делать не надо:

 Понять такую диаграмму не представляется возможным. Вроде бы логика есть, но из-за множества конструкций if/else читать такую sequence-диаграмму очень сложно
Понять такую диаграмму не представляется возможным. Вроде бы логика есть, но из-за множества конструкций if/else читать такую sequence-диаграмму очень сложно

В чистом коде давно выработан подход "ранний выход" (вернее "Guard Clauses"), позволяющий избавиться от множества if/else. Суть его в том, чтобы проверять особые случаи (ошибки, невалидные данные) как можно раньше и сразу прерывать выполнение программы, если условие не выполнено. Тогда основной поток алгоритма не обрамляется со всех сторон вложенными else, а идёт "плоско", без лишних отступов. Это повышает читаемость и облегчает понимание намерения кода программы.

Применительно к sequence-диаграммам используется блок break для досрочного завершения сценария при возникновении ошибки или исключения. Фрагмент break обозначает условие, при котором текущий поток прерывается (не продолжается ниже на диаграмме).

Рассмотрим тот же процесс, но уже правильно описанный на диаграмме:

 Читабельность такой диаграммы значительно выше. Более того, сразу понятно, что программа не будет пытаться выполнять лишние действия и при любом негативном сценарии сразу прервёт свою работу
Читабельность такой диаграммы значительно выше. Более того, сразу понятно, что программа не будет пытаться выполнять лишние действия и при любом негативном сценарии сразу прервёт свою работу

Циклы и работа с большими данными

Фрагменты loop на Sequence-диаграмме применяются для отображения повторяющихся действий. Они полезны, когда нужно показать, что некое действие выполняется для каждого элемента из набора или до достижения условия. Но здесь тоже есть важные нюансы и best practices, особенно когда дело касается большого объема данных.

Менее опытные коллеги иногда рисуют взаимодействие с базой данных без учёта технических особенностей. Например, считывают сразу все записи, потом перебирают их и что-то делают.

В коде же подобная реализация чревата проблемами. Если данных десятки тысяч, приложение может исчерпать всю доступную оперативную память и упасть с ошибкой OutOfMemory.

Реальные случаи этому подтверждение. Например, однажды в системе накопилось >6 миллионов записей и попытка выбрать их одним запросом привела к ошибке «Недостаточно памяти для получения результата запроса».

Поэтому лучшей практикой считается обрабатывать данные порционно (батчами). То есть, выбрать из базы ограниченное количество записей, обработать, затем при необходимости выбрать следующую порцию и т.д. Системы проектируются так, чтобы могли "прожёвывать" хоть миллион записей, но не за раз, а небольшими частями.

Как отразить подобный подход на диаграмме? Очень просто. В этом помогут вложенные циклыloop. Внешний loop будет обозначать чтение порциями, а внутренний обработку каждого элемента внутри порции. Покажу шаблон, который использую в таких случаях:

 Значения каждой порции мы получаем в первом loop, а во вложенном loop затем их обрабатываем. Первый цикл выполняется до тех пор, пока не закончатся порции.
Значения каждой порции мы получаем в первом loop, а во вложенном loop затем их обрабатываем. Первый цикл выполняется до тех пор, пока не закончатся порции.

На данной диаграмме Scheduler запускается на периодическую обработку (может быть крон-задача или планировщик). Он дергает API, который в цикле запрашивает порции данных, скажем, по 10 записей. База данных возвращает к API список объектов. Далее внутри этого списка API проходит в цикле по каждому объекту (вложенный loop, отмечен другим цветом). После того, как внутренний цикл закончился для 10 объектов, внешний loop повторяется и API снова спрашивает следующую десятку и т.д. Таким образом, вся обработка разбивается на небольшие итерации.

Операторы alt и opt для логики, а не для ошибок

Вернёмся к условным операторам на диаграммах - alt (альтернатива) и opt (опция).

Мы уже решили, что для ошибок лучше использовать break. Но и про alt/opt стоит сказать пару слов. alt соответствует условию if/else в коде (ветвление с альтернативами), а opt - условие без альтернативы (что-то вроде if (условие) { ... } без else). Эти конструкции нужны, чтобы показать разные варианты бизнес-логики.

Хорошее правило: alt/opt следует использовать для вариативной логики, а не для обработки исключений. Другими словами, если у процесса два или несколько нормальных исхода, которые взаимно исключают друг друга - это alt. Если у процесса есть необязательный шаг - это opt. Например:

alt/opt используют для ветвления логики исполнения программы, а не для обработки ошибок
alt/opt используют для ветвления логики исполнения программы, а не для обработки ошибок

Здесь показано две альтернативы в бизнес-логике: пользователь согласился - система сохраняет его данные; пользователь отказался - система, наоборот, удаляет ранее собранные данные. Оба варианта - штатные исходы процесса "обработка согласия". Мы раскрасили позитивный сценарий зеленым, негативный (отказ) - светло-розовым. Ни один из них не является "исключением" (ошибкой) - это ожидаемые пути (оба исхода нормальные с точки зрения бизнеса). Значит, всё ок и alt подходит идеально.

Встречал аналитиков, которые вообще не знали про opt и пихали в alt одиночные опциональные действия с пустой веткой else. Например, "если пользователь VIP, добавить бонус" рисовали как alt с else, где else просто пустой. Для таких случаев есть opt: он компактнее и явно означает "опциональный шаг".

Важно: условие в alt/opt можно записывать не только как простое выражение, но и как комбинацию через AND/OR. UML 2.x спецификация это допускает (да и PlantUML просто трактует весь текст после оператора как подпись условия). Так что не нужно бояться писать сложные условия в заголовке фрагмента.

Если ветка выполняется при нескольких одновременных условиях, то смело пишите их через AND / И. Если хотите указать альтернативные триггеры, то используйте OR / ИЛИ. Это лучше, чем пытаться изобразить два вложенных alt-а ради сочетания условий.

Пример: предположим, система сначала пытается получить некое значение1 из Источника1. Если не получилось, тогда обращается к резервному Источнику2, который может вернуть два значения сразу (значение1 и значение2). Далее, если оба значения в итоге отсутствуют - процесс прерывается как бессмысленный. А если хотя бы одно найдено - продолжаем работу. Такой сценарий можно изобразить так:

AND и OR позволяют объединять различные условия ветвления логики (см. OR в условии alt и AND в условии break)
AND и OR позволяют объединять различные условия ветвления логики (см. OR в условии alt и AND в условии break)

Форматирование и мелочи, которые делают Sequence-диаграмму лучше

Наконец, несколько небольших советов по оформлению sequence-диаграмм, которые существенно улучшают их читаемость - своего рода "clean code" для UML:

  • Переносы строк в длинных текстах
    Как уже говорил, используйте \n внутри длинных названий и надписей. Это касается имен участников (participant/actor/database), подписей условий (alt/opt/break), комментариев (note), и даже сообщений между объектами.

  • Используйте note для пояснений
    Заметки на диаграмме являются отличным способом добавить контекст, не перегружая сами стрелки пояснениями. Например, можно пометить note over SomeService: здесь происходит расчёт тарифа или note right of DB: новая запись. Это аналог комментариев в коде - если кусок диаграммы сложный, лучше добавить поясняющую сноску.

  • Логическое группирование lifeline-ов
    Располагайте участников на диаграмме в осмысленном порядке. Связанные компоненты - рядом. Например, сначала все внутренние сервисы, потом базы данных, затем внешние системы. Если фронтенд участвует - обычно ставят его слева, дальше backend-сервисы, правее - внешние. Последовательность слева направо должна отражать уровень близости к пользователю или к ядру системы. Тогда последовательность взаимодействий читается естественно, слева - инициатор, справа - исполнители.

  • DRY для диаграмм
    Принцип Don’t Repeat Yourself применим и здесь. Если один и тот же сценарий повторяется на диаграмме несколько раз или один фрагмент взаимодействия уже нарисован где-то, нет нужды копировать его вручную всюду. Можно вынести деталь во внешнюю диаграмму и на основной схеме использовать фрагмент ref (reference). В PlantUML синтаксис ref позволяет ссылаться на другой диаграммный кусок. Хотя признаться, я лично чаще просто делю диаграммы на логические части, чем пользуюсь ref. Главное - это не рисовать один и тот же большой обмен сообщений в десяти диаграммах подряд; лучше нарисовать отдельно и дать ссылку, либо описать словами. Переусердствовать с детализацией тоже плохо (нарушение KISS - Keep It Simple, Stupid!).

  • Обновляйте диаграммы вместе с кодом
    Это уже про практику документации. Sequence-диаграмма, какой бы красивой ни была, обесценится, если не будет актуальной. В отличие от кода, диаграммы не проверяются компилятором, они требуют нашей дисциплины как системных аналитиков.
    Хороший тон - при изменении логики интеграции или бизнес-процесса обновлять и диаграмму. В идеале хранить диаграммы в текстовом виде (PlantUML как раз для этого удобен) рядом с кодом. Тогда при ревью можно сразу править и документацию. Чистый код - это еще и актуальный код, а чистая документация - актуальная документация.


Мы рассмотрели лишь часть приемов, которые делают Sequence-диаграммы лучше. Тем не менее, даже этих шагов уже достаточно, чтобы повысить качество документации.

Цветовое кодирование, правильное использование alt/opt/break, ограничение циклов и порций данных, аккуратное форматирование текста - всё это превращает диаграмму из потенциальной "шарады" в понятный и полезный инструмент.

Хорошая диаграмма экономит время команды и снижает количество вопросов. Как и чистый код, она передает задумку автора максимально прямо, без "шума". Кстати, в другой моей статье на Хабре я писал, что системный архитектор просто обязан уметь наглядно доносить архитектуру до команды. Sequence-диаграммы - один из таких наглядных способов. Сделайте их понятными, и команда скажет вам спасибо. ?

Пишите диаграммы, также как код - чисто и продуманно. Если заметили, мы не использовали ни одной концепции, незнакомой разработчику. Системный анализ - не программирование, да, но он может многому поучиться у разработчиков. Перенимайте хорошие практики и в визуальном моделировании процессов!


Благодарю за внимание. Если вам понравился материал, заглядывайте в мой блог "Системный архитектор". ?

Я стараюсь писать просто и доступно, делясь личным опытом в системной архитектуре. Я не претендую на академичность. Всё, о чем рассказываю, родилось из практики - мои разработки, проектирование, исследования, аудит реальных проектов.

Люблю стартапы (финтех, проптех, агрегаторы) и постоянно экспериментирую, о чем и пишу для друзей и коллег. Если вам интересны такие темы, то welcome в мой блог "Системный архитектор" по ссылке чуть выше. Буду рад поделиться идеями и пообщаться!

Комментарии (0)