Диаграмма последовательности
Дисклеймер
Если ты опытный айтишник, смело переходи к главе Интересные возможности, ради которой ты, скорее всего, и зашел на эту страницу.
Что это?
Диаграмма последовательности используется для визуализации взаимодействия между объектами в системе. Она показывает порядок сообщений, которыми объекты обмениваются друг с другом во времени и их жизненный цикл. На мой взгляд, это самый простой и удобный инструмент для демонстрации всех интеграций и взаимодействий в рамках проектируемого бизнес-процесса.
Из чего состоит?
Основные элементы, из которых состоит sequence-диаграмма: объекты (зеленое), линии жизни (красное), сообщения (синее).
Пример sequence-диаграммы
Объекты — это сущности, которые взаимодействуют друг с другом. Например, пользователь, топик или очередь, микросервис. Помимо названия, объекты могут еще отличаться своим типом:
Типы объектов
Линии жизни(lifelines) отображают течение времени, а также активность или исполнение определенных функций объекта. Представляют из себя вертикальную линию с блоком активности.
Сообщения(messages) показывают обмен информацией между объектами. Например, клик пользователя на кнопку, но чаще это запрос или ответ, вызов хранимой процедуры или отправка сообщения. Сообщения отображаются в виде стрелок, направленных от одной линии жизни к другой, и бывают нескольких типов:
Типы стрелок
Где и как пользоваться?
Есть много вариантов, где можно рисовать UML-диаграммы. Самые популярные:
Графический редактор draw.io
Песочница от plantUML
С помощью плагина в инструментах JetBrains или VSCode
Графический редактор draw.io
Самое простое решение, которое не требует изучение синтаксиса UML — графический редактор draw.io, он же diagrams.net. Для создания диаграммы с помощью draw.io нужно только немного разобраться в интерфейсе программы, найти в поиске фигуры для создания sequence диаграмм и начать перетаскивать их на холст:
Создание диаграммы в draw.io
Все довольно просто, но проблемы начинаются, когда необходимо сделать диаграмму с большим количеством взаимодействий объектов. Будет много редактирований и нарисовать такую диаграмму займет гораздо больше времени. Поэтому лучше все-таки разобраться с синтаксисом UML и освоить 2 других варианта »рисования» диаграмм.
Разберемся с синтаксисом
К сожалению, просто взять и начать использовать UML диаграмму не получится. Нужно хотя бы поверхностно изучить синтаксис UML. Он очень простой, поэтому базовых примеров будет достаточно, чтобы начать прорабатывать диаграммы.
Сначала нужно еще раз осознать, что есть вышеописанные сущности: объекты, линии жизни и сообщения. Чтобы появились линии жизни необходимо четко определить в начале документа объекты:
actor "Пользователь" as u
participant "Фронт" as f
participant "Бэк" as b
Или можно этого не делать (чего я не рекомендую, поскольку читаемость, на мой взгляд, сильно ухудшится), так как они автоматически появятся при описании второй сущности — сообщений. Для описания сообщений используются стрелки »→». Нужно только указывать из какого объекта идет сообщение и в какой — «client → server»:
actor "Пользователь" as u
participant "Фронт" as f
participant "Бэк" as b
u -> f
f -> b
b -->> f
f -->> u
На основе своего опыта сразу подсвечу, обычно никто не пользуется сразу всеми типами объектов и стрелок. Среди типов объектов самые распространенные:
• actor — пользователь или «клиент»;
• participant — сервер, компонент системы;
• database — база данных;
• queue — топик или очередь.
Среди часто используемых стрелок:
a ->> b: Асинхронный вызов
a -> b: Синхронный вызов
a -->> b: Ответ
a -x b: Запрос, который будет удален
'или от которого решили отказаться/устаревший
Часто используемые стрелки
Синхронный/Асинхронный вызов это –
Синхронный вызов — взаимодействие, в котором один объект отправляет запрос и обязательно получает что-то в ответ от другого объекта. Как пример, взаимодействие браузера с сервером.
Асинхронный вызов — взаимодействие, при котором один объект шлет запрос другому, но ответ не получает. Как пример, работа очередей или топиков: один объект положил данные в топик, а второй объект забрал эти данные, но никакой отбивки первому объекту при этом не пришло.
Группировка
Теперь, когда мы разобрались с самыми распространенными типами стрелок и объектов, предлагаю разобраться с еще одним важным понятием — группировка сообщений. Здесь я опять же разберу самые популярные и те, которые в моей практике реально встречаются. Группировка нужна для того, чтобы как-то осмысленно скомпоновать сообщения, а также для того, чтобы наложить определенные правила для отдельно взятых сообщений. Например, можно объединить несколько сообщений по смыслу и как-то их обозвать, а можно объединить их в группу »par» тем самым подсветив, что сообщения в этой группе выполняются параллельно.
Alt — группировка, которая накладывает определенные правила. Используется для того, чтобы показать альтернативные кейсы для взаимодействия, используется с оператором else. Например, объект может отправить запрос, а второй объект, в зависимости от полученных данных, выполнит разные действия:
Синтаксис и пример
alt case 1
a -> b
else case 2
a -> c
end
Пример для alt
Opt — используется для того, чтобы выделить сообщение в опциональный кейс. Например, объект может отправить запрос, а второй объект, в зависимости от полученных данных, может выполнить дополнительное действие:
Синтаксис и пример
opt
a -> c
end
Пример для opt
Par — используется для того, чтобы выделить сообщения, которые выполняются параллельно. Используется с оператором else. Например, объект может отправить запрос, а второй объект параллельно выполнит внутренние вычисления и вернет ответ первому объекту:
Синтаксис и пример
par
a -> b
else
a -> c
end
Пример для par
Loop — используется для того, чтобы выделить сообщения, которые выполняются несколько раз. Например, объект может отправить запрос, а второй объект выполнит внутренние действия несколько раз в зависимости от отправленных данных:
Синтаксис и пример
loop
a -> c
end
Пример для loop
Group — используется для того, чтобы скомпоновать сообщения по смыслу. Например, на диаграмме может быть много взаимодействий и для того, чтобы было меньше путаницы можно подписать группы сообщений:
Синтаксис и пример
group
a -> c
end
Пример для group
Еще сгруппировать можно сами объекты. Это может быть полезно для описания взаимодействия нескольких систем с микросервисами:
Синтаксис и пример
box Название
participant "Название 1"
participant "Название 2"
box end
Пример группировки объектов
Подробное описание всех возможностей sequence-диаграмм можно прочитать здесь, включая все типы объектов, стрелок и группировок, которые я решил не описывать в этой статье.
Песочница от plantUML и плагины
После того, как мы разобрались с синтаксисом UML уже можно «рисовать» более сложные диаграммы, например, в песочнице от plantUML. Выглядит это так:
Пример работы в plantUML
Исходный код
@startuml
actor "Браузер" as b
box "Работа с пользователем"
participant "Модуль клиентов" as c
participant "Модуль обработки данных" as d
box end
box "Хранение данных"
participant "Модуль хранения данных" as s
database "База данных" as db
box end
b -> c: Запрос данных
activate c
opt В запросе параметр обработки = true
c -> d: Запрос на обработку данных
activate d
d -->> c: Ответ
deactivate d
end
c -> s: Сохранение данных
activate s
s -> db: Запрос в БД
activate db
db -> db: Сохранение
db -->> s
deactivate db
s -->> c
deactivate s
c -> c: Формирование ответа
c -->> b: Ответ
deactivate c
@enduml
Но самый удобный инструмент для работы с sequence-диаграммами — ваша любимая ide. Например, вы можете установить плагин прямо в WebStorm от JetBrains.
Подробнее:
Установка плагина для работы с UML
Создание файла формата .puml
Создавать диаграммы через любимые ide самый удобный способ, вдобавок файлы хранятся непосредственно на вашем устройстве. Формат UML для описания диаграмм последовательности очень хорошо работает с системами версионирования, поэтому можно смело вести свои проекты с использованиям git’а.
Интересные возможности
Цвета
Изменение цвета стрелки
-[#blue]>
-[#ff00ff]>
Изменение цвета стрелки
Такая возможность пригодится в тех случаях, когда необходимо что-то подсветить.
Я сталкивался с тем, что в отдельных компаниях был конкретный регламент на цвета стрелок. Например, необходимо было существующие потоки красить в синий цвет, существующие, которые дорабатываются — в оранжевый, а новые — в красный.
Еще помимо стрелок можно красить и сам текст. Как это использовать — додумаете сами.
Изменение цвета текста
A -> B: Запрос
B -->> A: Ответ
Изменение текста сообщения
Также можно настраивать цвета для «линии жизни» и самого объекта. Кстати, в Интернете можно найти огромное количество настроек для кастомизации базовых стилей, включая шрифты, толщину линий, отступы и многое другое. Такие настройки, как правило, начинаются с оператора «skinparam».
Изменение стилей
Пример кастомизации
Да-да, я знаю, выглядит всрато так себе.
Блок активности
Недавно открыл для себя, что необязательно каждый раз писать «activate» и «deactivate», досаточно »++» и »--».
Пример:
#было:
Alice -> Bob: Authentication Request
activate Bob
Bob -> Sanya: Another authentication Request
activate Sanya
Sanya --> Bob: Authentication Response
deactivate Sanya
Alice <-- Bob: another authentication Response
deactivate Bob
#------------
#стало:
Alice -> Bob++: Authentication Request
Bob -> Sanya++: Another authentication Request
Sanya --> Bob--: Authentication Response
Alice <-- Bob--: another authentication Response
Согласитесь, uml-кода стало сильно меньше и даже читаемость улучшилась. А вот так это выглядит:
Пример активации
Autonumber
Многие знают, что это за оператор и как он работает, но далеко не многие знают, что его функционал куда шире, чем просто инкрементирование номера сообщения.
Номер можно еще стилизовать, переопределять, добавлять в него подпункты, использовать как переменную и многое другое (подробнее здесь).
Изменение autonumber
autonumber 10 5 "(##)"
Alice -> Bob
Alice <-- Bob
Alice -> Bob
|||
autonumber 1 "Message 0 "
Alice -> Bob
autonumber "[000]"
Alice <-- Bob
|||
autonumber 2.1
Alice -> Bob
Alice <-- Bob
Alice -> Bob
Примеры кастомизации autonumber
Я лично частенько использую подпункты.
Подсказка
Очень редко на своей практике встречал диаграммы, на которых кто-то пользовался этой крутой фишкой. С помощью нее можно подробнее описать какие-то нюансы взаимодействия или просто указать адрес (host: port).
Подсказка
note right
REST: **some.adress.com:433/new**
end note
Пример с подсказкой
Разделительная черта
Не смотря на всю крутость подсказок, их я использую редко, а вот разделительную черту я использую довольно часто. Бывают случаи когда интеграция имеет, например, 2 сценария. Чтобы не захламлять страницу с аналитикой и не дублировать кучу uml-кода, можно нарисовать одну диаграмму, но разбить ее на 2.
Разделительная черта
#Синтаксис
== Сохранение данных ==
Разделительная черта
Заключение
В заключение хочу сказать, что диаграмма последовательности очень крутой и мощный инструмент для описания взаимодействий и интеграций, а научиться им пользоваться довольно легко, особенно когда есть под рукой материал с описанием синтаксиса.
Еще у меня есть Telegram-канал Айтишник обыкновенный, где я делюсь опытом и знаниями IT-индустрии. Лучшая поддержка — подписка на мой канал ❤️
P.S. Возможно, про какие-то особенности я забыл написать или даже не знал. Поделитесь в комментариях, если кто-то пользуется чем-то еще, чего я не осветил в этой статье. Если будет что-то дельное, я обязательно добавлю эту фишку/особенность, а также вас как автора.
Всем добра!