39
0
0
Скопировать ссылку
Telegram
WhatsApp
Vkontakte
Одноклассники
Назад

Как создавать sequence-диаграммы с помощью PlantUML и почему базовый скил аналитиков может пригодиться не только им

Время чтения 25 минут
Нет времени читать?
Скопировать ссылку
Telegram
WhatsApp
Vkontakte
Одноклассники
39
0
0
Нет времени читать?
Скопировать ссылку
Telegram
WhatsApp
Vkontakte
Одноклассники

Давайте поговорим о таком важном (и, как вы убедитесь, прочитав статью до конца, несложном) инструменте, как sequence-диаграммы, или диаграммы последовательности. Это базовый скил аналитиков, но если вы разработчик, архитектор и в целом работаете в IT-сфере, умение не только понимать, но и создавать такие диаграммы очень полезный навык.

Меня зовут Екатерина Петрова, я автор медиа «вАЙТИ» и аналитик. В этой статье расскажу, что такое сиквенсы и как их нарисовать.

Как создавать sequence-диаграммы с помощью PlantUML и почему базовый скил аналитиков может пригодиться не только им

Что за зверь такой — диаграммы последовательности

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

Кому это может понадобиться:

  • Аналитикам. Понятно описать сценарии работы системы и передать их разработчикам.
  • Разработчикам. Понять, что вообще происходит в проекте и как всё работает. При этом важно уметь не только читать такие схемы, но и самому набрасывать их.

Какие инструменты использовать для создания

Вариант 1: если вы хотите пострадать, выберите draw.io. Почему страдать? Потому что всё придется делать руками: двигать квадратики, стрелочки, тексты. Попробуйте потом поправить что-то в середине схемы — готовьтесь потратить пачку нервных клеток, возвращая съехавшие элементы на свои места.

Из плюсов: освоить можно интуитивно. Но инструмент крайне непрактичный, особенно если в процессе потребуется вносить множество исправлений. А еще это ад для перфекциониста. 

Вариант 2: с помощью инструмента PlantUML. Перейдите на на plantuml.com/ru → Online Server. Почти магический инструмент, который работает через код. И пусть вас не пугает слово «код» — потратьте немного времени, чтобы разобраться. Это не rocket science, пишется логично, а нотация достаточно простая. 

Вот еще плюсы PlantUML:

  • Есть возможность сохранить исходный файл. 
  • Всё автоматически получается аккуратным (стрелочки, шрифты, никакого судорожного подравнивания — лайк от перфекционистов).
  • Можно легко встроить диаграмму в документацию, например в Confluence или Wiki.

Нотация действительно интуитивно понятна. Смотрите, даже без знания документации UML вы легко прочитаете следующую диаграмму:


@startuml
participant "Client" as client
participant "Server" as server
 
client -> server: HTTP GET /users
server -> server: Process request
server --> client: 200 OKn[{"id":1,"name":"Alice"}]
 
client -> server: POST /usersn{"name":"Bob"}
server -> server: Create user
server --> client: 201 Createdn{"id":2,"name":"Bob"}
@enduml

Это пример простой схемы — на диаграмме показан обычный пример клиент-серверного взаимодействия. 

Как это читается:

  1. Client отправляет HTTP-запрос к серверу, чтобы получить список пользователей.
  2. Server обрабатывает запрос и отвечает 200 OK с данными.
  3. Затем Client добавляет нового пользователя, отправляя запрос POST.
  4. Сервер записывает данные в database и отвечает подтверждением о создании.

Не так уж и запутанно, правда? Теперь давайте по порядку разбирать ключевые элементы и заодно пошагово создавать сиквенс в PlantUML.

Из чего состоят диаграммы

Минимум, который нужно знать:

Участники (participants) — обозначаем всех, кто участвует. Это могут быть пользователи, серверы, базы данных и так далее — например, `participant "Client" as client`.

Сообщения показывают, как участники общаются: `client -> server: HTTP GET /users`.

Пример возьмем из жизни: допустим, у нас есть умный дом. Пользователь регулирует температуру и освещение через систему управления, а та отправляет команды устройствам.

Исторически сложилось начинать с обрамляющего код синтаксиса @startuml/@enduml, хотя это необязательно, код всё равно отработает — можете проверить. 

Далее определяем основных участников, они в PlantUML обозначаются как participant. У вас отобразятся прямоугольники, однако для большей наглядности можно менять форму их отображения. Самые популярные:

  • actor — человечек (действующее лицо, например пользователь);
  • database — форма цилиндра, обозначающего базу данных;
  • queue — скругленный прямоугольник, который используется для обозначения очереди (например, в брокерах сообщений).

Далее именуем наших участников. Если слов в названии больше чем два, оборачиваем в кавычки. Используем псевдоним через as для упрощения обозначения.

Участники на диаграмме появляются в том порядке, в каком вы их укажете в коде. Если нужно задать другой порядок, можно использовать команду `order` с любыми числами — главное, чтобы они шли по возрастанию или убыванию (например, первый участник — `order 50`, второй — `order 9`). Честно говоря, я редко использую `order` и просто прописываю участников сразу в нужной последовательности.

Итак, давайте добавим участников процесса для нашего примера умного дома. 


```
actor Пользователь as user
    participant "Датчик температуры" as temp
    participant "Датчик освещенности" as light
    participant "Датчик движения" as mot
    control "Система управления" as manager
    database "База данных" as bd
    participant Кондиционер as cond
    participant Освещение as illum
    participant Жалюзи as blind
```

Начнем показывать взаимодействие между участниками с помощью стрелок сообщений. 

Синтаксис стрелки-запроса от одного участника к другому выглядит так:

```Participant_1 -> Participant_2```

Используется для отображения синхронного взаимодействия (классический REST-запрос). 

Стрелка с половинкой наконечника используется для демонстрации асинхронного взаимодействия — например, работы брокера сообщений.

Синтаксис выглядит так:

```Participant_1 -\ Participant_2```

Ответ (response) показывается пунктирной стрелкой.


```
Participant_1 -> Participant_2
Participant_2 --> Participant_1
Participant_1 -> Participant_2
Participant_1 <-- Participant_2
```

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

В спецификации PlantUML приводятся и другие виды стрелок: 


@startuml
Bob ->x Alice
Bob -> Alice
Bob ->> Alice
Bob - Alice
Bob \- Alice
Bob //-- Alice
Bob ->o Alice
Bob o\-- Alice
Bob <-> Alice
Bob <->o Alice
@enduml

Они пригодятся разве что для специфичных случаев и вряд ли понадобятся вам. Если нужно показать процесс, лучше использовать привычные стрелки -> или –>. Так будет проще и понятнее, чтобы никто не запутался.

Итак, покажем на диаграмме процесс того, как пользователь вносит в программу умного дома желаемые настройки для температуры и освещенности.


```user->manager: Ручная настройка параметров
        manager->db: Сохранение настроек
        db-->manager: Подтверждение сохранения
```

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

В коде для работы с линиями жизни используются следующие элементы:

  • `activate` активирует участника, что визуально обозначается началом прямоугольника вдоль линии;
  • `deactivate` завершает активность участника (прямоугольник закрывается);
  • `destroy` показывает конец линии существования участника. На диаграмме это обозначается крестиком.

Например:


```
participant A
participant B
 
A -> B: Запрос
activate B
B -> A: Ответ
deactivate B
A -> B: Другая операция
destroy B
```

Конструкция activate/deactivate после каждого сообщения может сильно загромоздить код. 

Совет: для упрощения можно использовать сокращения с помощью знаков `++` и `–`. Эти символы добавляются к участнику, чтобы показать активацию (`++`) или деактивацию (`–`).

Примеры:

1. Активация участника:

    ```   
    A -> B++: Отправить запрос
    ```

2. Деактивация участника:

    ```
    B-->A--: Отправить ответ
    ```

Здесь `B` отправляет ответ участнику `A` и деактивируется.

Также можно комбинировать активацию и деактивацию в одной строке, например:


```
A -> B++: Отправить запрос (активировали B)
B-->C--++: Отправить другой запрос (деактивировали B и активировали C)
C-->A--: Вернуть ответ (деактивировали C)
```

Альтернативные и опциональные сценарии

Давайте посмотрим еще один вариант популярного использования РlantUML — отразим на диаграмме альтернативные (alt) и опциональные, то есть необязательные (opt), сценарии. 

Каждый такой блок начинается с ключевого слова (alt или opt) и обязательно заканчивается словом end.

Лайфхак: чтобы избежать бесконечных ругательств валидатора PlantUML, сразу прописывайте всю структуру.

  • Для альтернативного сценария — `alt ... else ... end`.
  • Для опционального — `opt ... end`.

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

Вернемся к нашему умному дому. Какой процесс происходит:

  1. Пользователь задает температуру 22 °C.
  2. Система проверяет текущую температуру через датчик.
  3. Если температура выше 25 °C, система включает кондиционер на охлаждение.

Давайте добавим условия: если температура воздуха поднимается выше 25 градусов, система управления домом подаст сигнал для включения кондиционера на режим охлаждения. Если температура опустится ниже 15 градусов — включится режим обогрева.

Код будет выглядеть так: 


   ```
        alt Температура > 25 °C
            manager->cond: Включить охлаждение
            cond-->СистемаУправления: Подтверждение включения
        else Температура < 15 °C
            manager->cond: Включить обогрев
            cond-->СистемаУправления: Подтверждение включения
        end
   ```

Добавим опциональное условие (кстати, блоки можно между собой комбинировать).


    ``` opt День (6:00–22:00)
            alt Освещенность < 50%
                manager->illum: Увеличить яркость
                illum-->: Подтверждение включения осветителей
            end
            
            alt Солнце активно
                manager->>blind: Прикрыть окна
                Жалюзи-->>manager: Подтверждение раскрытия шторок
            end
        end
   ```

Зацикливание

Давайте смоделируем задачу: необходимо рассчитать среднюю температуру за неделю. Для этого датчики будут каждые пять минут передавать данные в систему управления домом, которая, в свою очередь, сохранит их в базе данных.

Для отображения периодического повторения сколько-то раз или в течение определенного периода в plantUML есть специальный блок loop — зацикливание.

Синтаксис нам уже знаком: loop ... end.


  ```
actor Пользователь as user
    participant "Датчик температуры" as temp
    participant "Датчик освещенности" as light
    participant "Датчик движения" as mot
    control "СистемаУправления" as manager
    database "База данных" as db
 
loop Каждые пять минут
        temp->>manager: Отправка температуры
        light->>manager: Отправка уровня света
        mot->>manager: Статус движения
    manager->>db: Запись истории изменений
        db-->>manager: Подтверждение записи
    end
  ```

На практике блок `loop` часто используется для реализации сценариев отслеживания статусов. Например, при создании заявки ей присваивается статус «Создана», который сохраняется в базу данных. Затем шедулер запускается каждую минуту и проверяет, изменился ли статус.


  ```
@startuml
actor "Client" as client
participant "Server" as server
database "Database" as db
 
== Создание заявки ==
client -> server: Создать заявку
server -> db: Сохранить заявку со статусом «Создана»
db --> server: Успешно сохранено
server --> client: Заявка создана (статус: «Создана»)
 
== Цикл проверки статуса ==
loop Каждую минуту
    server -> db: Проверить статус заявки
    db --> server: Текущий статус: «Создана»
    server -> server: Логика проверки обновления статуса
    alt Статус не изменился
        server -> server: Ожидание следующей проверки
    else Статус обновлен
        server -> db: Обновить статус
        db --> server: Статус обновлен
        server --> client: Уведомление: статус заявки обновлен
    end
end
@enduml
  ```

В PlantUML можно создавать блоки, где фрагменты выполняются параллельно, используя ключевое слово `par` (parallel). Это удобно для отображения процессов, происходящих одновременно.

Для более наглядной структуризации доступна конструкция `group`. Она представляет собой своего рода рамку, внутри которой можно размещать связанные по смыслу элементы или обозначать логические группы. Синтаксис предельно простой: `group (название группы) ... end`.

Если требуется сгруппировать участников или выделить работу какой-либо системы, например работу брокера, можно воспользоваться блоком `box ... end box`. Этот инструмент помогает визуально разграничить элементы для удобства восприятия.

Еще лайфхаки: прокачайте свой сиквенс

В PlantUML есть инструменты-бантики, которыми можно украсить диаграмму, то есть сделать ее еще более читабельной и понятной.

Можно использовать следующие записи, чтобы задать цвет: 

  • участнику — `actor Bob #red`
  • стрелке — `Bob -[#red]-> Alice : hello`
  • блоку — `box "Internal Service" #LightBlue`
  • линиям жизни между участниками — `alice -> bob --++ #gold`.

Можно сделать автоматическую нумерацию сообщений с помощью ключевого слова `autonumber`

Для добавления заголовка диаграммы применяется ключевое слово `title`.

Заметки к сообщениям можно размещать с помощью команды `note`. Их расположение задается следующим образом:

  • `note left` — заметка будет отображена слева;
  • `note right` — заметка расположится справа;
  • `note over` — заметка добавляется сверху.

При необходимости можно задать привязку к элементу, используя `note left of`, `note right of` или `note over`.

Заметки разных форм:

  • `hnote` — в виде шестиугольника;
  • `rnote` — в виде прямоугольника.

Чтобы сделать диаграмму более компактной и удобной для восприятия, используйте перенос текста на несколько строк. Для этого вставьте символ `n` в местах, где требуется разрыв строки.

А вот так будет выглядеть итоговая диаграмма: 


```
@startuml
title: Процесс работы умного дома
autonumber
 
    actor Пользователь as user #LightYellow
    participant "Датчикnтемпературы" as temp
    participant "Датчикnосвещенности" as light
    participant "Датчикnдвижения" as mot
    control "Системаnуправления" as manager
    database "Базаnданных" as db
    participant Кондиционер as cond
    participant Освещение as illum
    participant Жалюзи as blind
 
Note over user, manager: Пользователь задает параметры вручную
 
user->>manager: Ручная настройка параметров
manager++
manager->db: Сохранение настроек
db++
db-->>manager: Подтверждение сохранения
db--
manager--
 
loop Каждые пять минут
    Note over temp, mot: Система собирает информацию<br>с датчиков через регулярные интервалы
    temp->>manager: Отправка текущей температуры
    manager++
    light->>manager: Отправка уровня освещенности
    mot->>manager: Сообщение о движении
    manager->>db: Запись данных в историю
    db++
    db-->>manager: Подтверждение записи
    db--
    manager--
end
 
alt Температура > 25 °C
    Note over manager, cond: Охлаждение активируется
    manager->>cond: Включить охлаждение<br>для температурного баланса
    cond++
    cond-->>manager: Подтверждение: кондиционер включен
    cond--
else Температура < 15 °C
    Note over manager, cond: Обогрев активируется
    manager->>cond: Включить обогрев<br>для поддержания тепла
    cond++
    cond-->>manager: Подтверждение: обогрев включен
    cond--
end
 
opt Дневное управление освещением (6:00–22:00)
    alt Освещенность < 50%
        Note over manager, illum: Освещение повышается<br>при низком уровне света
        manager->>illum: Включить освещение
        illum++
        illum-->>manager: Подтверждение включения света
        illum--
    else Достаточное освещение
        Note over manager: Освещение не требуется
    end
end
 
alt Уровень солнечного света (дневное управление)
    manager->>blind: Закрыть жалюзи<br>от ярких солнечных лучей
    blind++
    blind-->>manager: Подтверждение: жалюзи закрыты
    blind--
else Менее яркий солнечный свет
    Note over manager, blind: Жалюзи остаются открытыми
end
@enduml
 
```

Как вы видите, создание sequence-диаграмм с помощью кода — это несложный и крайне полезный инструмент, который пригодится не только аналитикам, но и всем, кто связан с IT. Умение визуализировать процессы и обмен данными позволяет не только лучше понимать систему, но и эффективно доносить свои идеи до команды.

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

Комментарии0
Тоже интересно
Комментировать
Поделиться
Скопировать ссылку
Telegram
WhatsApp
Vkontakte
Одноклассники