Sequence диаграммы как код

23 марта 2024

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

В русской википедии они именуются как диаграммы последовательности.

Зачем вообще нужны Sequence диаграммы?

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

Почему удобнее их писать как код?

Поначалу я рисовал такие диаграммы в draw.io. Это было в целом достаточно утомительно.

sso_diagram.drawio

Потом для меня открыли существование PlantUML. Написать первую диаграмму, используя текст, было тоже весьма утомительно, как и рисовать в draw.io. Но вот когда дело дошло до внесения изменений и когда потребовалось делать другие подобные диаграммы, тут-то в полной мере и раскрылись преимущства диаграмм в виде кода, а не рисунков.

Ясность и точность
Использование PlantUML для написания Sequence диаграмм в виде кода обеспечивает высокую ясность и точность в описании взаимодействия между компонентами. Код на PlantUML является формализованным и строгим, что исключает возможные неоднозначности или недопонимания при интерпретации диаграмм.
Интеграция с документацией
Sequence диаграммы, созданные на PlantUML, легко встраиваются в документацию проекта, такую как Confluence. Это обеспечивает удобный доступ к визуальным представлениям архитектуры и взаимодействия компонентов системы для всех участников проекта.
Версионность изменений
PlantUML дает возможность отслеживать изменения в диаграммах и контролировать их версионность. Это полезно при работе с Confluence, так как позволяет сохранять историю изменений и быстро восстанавливать предыдущие версии диаграмм при необходимости.
Легкость внесения правок и создание последующих диаграмм
Благодаря тому, что Sequence диаграммы на PlantUML представлены в виде кода, внесение правок становится простым и быстрым процессом. Кроме того, на основе существующего кода легко создавать последующие диаграммы, что способствует экономии времени и повышает эффективность работы команды.

К минусам кодирования диаграмм я отнёс бы разве что недостаточную гибкость в стилях отображении.

PlantUML

Диаграмму можно начать кодировать/рисовать в браузере:

https://www.plantuml.com/plantuml/uml/SyfFKj...

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

https://hub.docker.com/r/plantuml/plantuml-server

Нумерация запросов

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

Для обоих сценариев сильно помогает нумерация запросов на диаграме. Если запросы пронумерованы, то в коммуникации часто используется «запрос 11 отправлет такие-то данные сервису вашей команды, а в ответе 12 приходят в ответ неожиданные данные». Это позволяет избегать запутанных и длинных конструкций «когда сервис той команды шлёт запрос к сервису вашей команды».

Пример диаграммы для Single Sign-On

@startuml

<style>
group {
    LineThickness 1
    LineColor #4d4d4d
    LineStyle 1
  }

  groupHeader {
    LineThickness 1
    LineStyle 1
  }
</style>

skinparam sequence {
ArrowColor #000000
ActorBorderColor #000000
LifeLineBorderColor #000000
LifeLineBackgroundColor #FFFFFF
ParticipantBorderColor #000000
ParticipantBackgroundColor #FFFFFF
ParticipantFontColor #000000
BoxBorderColor #000000
BoxBackgroundColor #FFFFFF
BoxFontColor #000000 }

participant Customer order 10
participant Browser order 20 #fff2cc
participant App1 order 30 #dcebf7
participant App2 order 40 #e2efda
participant App3 order 50 #d9d2e9
participant App4 order 60 #F5F5F5
participant App5 order 70  #FCE4D6  

group App1 Group Authentication
 
Customer -> Browser : A1. Go to App1
activate Browser
Browser -> App1 : A2. GET index
activate App1
App1 -> Browser : A3. index
deactivate App1

Customer -> Browser : A4. Click Login
Browser -> App2 : A5. GET authorization.oauth2, CustID: App1
activate App2

App2 -> Browser : A6. Login form

Customer -> Browser : A7. Login information

Browser -> App2 : A8. POST Login information
App2 --> Browser : A9. 302 Redirect + auth code

Browser -> App1 : A10. GET redirect uri_endpoint + auth hash
activate App1

App1 -> App2 : A11. Request access token by auth hash

App2 -> App1 : A12. Access Token + User_Info

App1 -> Browser : A13. Logged in content
deactivate App1

Browser -> Customer : A14. Logged in content

end

group  App1 User Authentication
 
Customer -> Browser : B1. Click User Login
Browser -> App1 : B2. GET
activate App1

App1 -> Browser : B3. Login form

Customer -> Browser : B4. User Login information

Browser -> App1 : B5. POST User Login information
App1 -> Browser : B6. User Logged in content + Cookie with User Id
deactivate App1

Browser -> Customer : B7. User Logged in content

end

Customer -> Browser : C1. Go to App

Browser -> App3 : C2. GET initial URI (with ID, pass and language parameters)
activate App3
App3 --> Browser : C3. 302 Redirect to App2, set state parameter to 'initial URI'

Browser -> App2 : C4. GET authorization.oauth2, CustID: App1

App2 --> Browser : C5. 302 Redirect + auth hash

Browser -> App3 : C6. GET redirect uri_endpoint + auth hash

App3 -> App2 : C7. Request tokens by auth hash

App2 -> App3 : C8. Access, Refresh, Id Tokens

App3 --> Browser : C9. 302 Redirect to certain Data Center depending on User from Id Token, GET initial URI
deactivate App3

Browser -> App4 : C10. GET initial URI
activate App4

App4 --> Browser : C11. 302 Redirect to App2, set state parameter to 'initial URI'
Browser -> App2 : C12. GET authorization.oauth2, ClientID: App1

App2 --> Browser : C13. 302 Redirect + auth hash

Browser -> App4 : C14. GET redirect uri_endpoint + auth hash


App4 -> App2 : C15. Request tokens by auth hash

App2 -> App4 : C16. Access, Refresh, Id Tokens
deactivate App2

App4 -> App5 : C17. Socket: Id Token + User
activate App5
rnote over App5
App5 gets Id token,
extracts user information,
creates internal context
for this user
+ Login to User, if defined
endrnote
App5 -> App4 : 18. Success status
deactivate App5

App4 -> Browser : C19. App4 Logged in content, depending on parameters from App2 'state' about 'initial URI'
deactivate App4
Browser -> Customer : C20. App4 Logged in content


deactivate Browser

@enduml

Ссылка на эту же диаграмму на PlantUml сервере: http://www.plantuml.com/plantuml/uml/fLLjRz....