Бизнес-анализ в IT
2024-08-12 13:34

UML: Activity Diagram

Бизнес-анализ
На очереди у нас — Activity Diagram (до этого мы уже рассмотрели диаграммы вариантов использования и классов).

Снова про систему обозначений:

Голубой цвет — то, что не продиктовано UML, а взято как полезный совет/правило из иных теорий и практик.

Курсив — примеры.

Activity Diagram (видал, что корректно по-нашенски оно зовётся «диаграмма деятельности», но как-то сие не прижилось: все зовут диаграммой активностей) — это процессная диаграмма (из разряда поведенческих в UML), коих в мире вагон и тележка: блок-схемы, Flowcharts, Business Process Diagram в BPMN — почти в любой нотации найдётся прямой аналог. Подобные диаграммы показывают шаги процесса, их последовательность, ветвления/циклы и условия этого, плюс порой и участников (кто что делает).
Когда применять:

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

Элементы:

Action (Действие) — ключевой элемент диаграммы: атомарный шаг в рамках процесса, который мы моделируем. Например, это шаг варианта использования, если мы рисуем сценарии варианта использования. Прямоугольник с закругленными краями.

Decision и Merge (Ветвление и объединение) — показывают то, как процесс может ветвиться на потоки в зависимости от какого-то условия. Или, соответственно, как потоки могут объединяться в один. Оба элемента показываются ромбом. Например, в ходе выполнения юз кейса система проверяет корректность введенных данных и либо выполняет нечто успешное, либо показывает сообщение об ошибке.
Нюансы:

  • Стоит понимать, что decision — это ветвление на альтернативные потоки (либо-либо), то есть после decision поток может идти только по одному из указанных выходов (которых, кстати, может быть много). Вообще для корректного восприятия потоков в рамках подобных диаграмм лучше представить себе, как по вашей диаграмме с течением времени движется точка/точки. Что-то типа такого (хоть это и не UML Activity Diagram на картинке):
  • Когда потоки сливаются в единый процесс, merge ждет какой-либо из входящих потоков (т. е. именно один из), и, как только это происходит, процесс идет дальше. См. примечание для merge в примере выше.
Есть два варианта того, как на диаграмме показать, в чем заключается ветвление. В примере выше показан вариант номер раз: написать проверочный вопрос/условие около decision, а на выходящих из него связях — ответы на данный вопрос. Такая подпись на связях, кстати, называется guard и оформляется в квадратных скобках (на что аналитики часто забивают и скобки не пишут — ничего страшного в этом нет, но стоит понимать, что это не совсем корректно с точки зрения UML). Для многих это самый наглядный вариант, но для пытливых поясню, что это не есть норма с точки зрения UML — в недрах UML для такой задачи предлагается использовать иной механизм (decision input behavior), но он не то, чтобы нагляден, а потому будем нарушать заповеди отцов и использовать это именно так.
Второй вариант (который более корректен с позиции UML) — описать полностью каждое условие с помощью guard у выходных связей без подписи decision:
Initial Node и Activity Final Node (Стартовая и конечная точки процесса). Стартовая точка — закрашенный кружок, конечная — он же, но внутри пустого круга. Аналитики часто подписывают начальные и конечные точки состояниями (исполнителя или участника процесса) на момент старта и конца процесса. Например, если вы моделируете сценарии юз кейса, сюда огненно лягут его предусловия и постусловия.
Нюансы:

  • Начальных точек может быть несколько — это означает, что процесс должен стартовать во всех начальных точках. Подобное редко применяется, поэтому это, скорее, повод блеснуть этим на собеседовании.
  • Конечная точка для процесса — это то, что заканчивает весь процесс. Конечных точек также может быть несколько – та, в которую раньше приходит процесс, заканчивает весь процесс.
Partition (Область) — это визуальная область на диаграмме, которая группирует все остальные элементы по участнику. Например, для типового юз кейса это могут быть области «Актер» и «Система», и все остальное будет находиться внутри одной из этих двух областей. Области можно показывать вертикально и горизонтально.
Fork/Join (Развилка/слияние, или как-то примерно в таких терминах) — элемент, похожий на Decision/Merge, но теперь уже для параллельных потоков. Изображается в виде прямой линии, в которую могут входить потоки (Join) и из которой они могут выходить (Fork).
Нюансы:

  • В отличие от Decision/Merge поток, входящий в Fork, делится на ряд потоков, одновременно продолжающихся после этого самого Fork.
  • Когда потоки сливаются в единый процесс, Join ждет все входящие потоки (именно все, а не один из), и, как только это происходит, процесс идет дальше.

Связи:

Основная связь одна — Control Flow (поток управления). Это те самые стрелочки с открытыми концами, которые соединяют элементы на диаграмме. Как мы уже знаем, такая связь может быть подписана с помощью guard (текст в квадратных скобках) — guard определяет условие, при котором поток пойдет по этой связи. В частности, это применимо для оформления Decision.

Продвинутые аспекты:

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

Есть элемент Object (объект). Это прямоугольник, и используется он для акцента на объекте данных, который передается в рамках процесса из одного элемента в другой.
Что интересно (ужасно интересно, понимаю), связь в/из объекта, хоть и визуально остается прежней, формально называется уже не Control Flow, а Object Flow — опять-таки, подобным можно отжечь на собеседованиях.
Второй вариант показать то же самое: через Pins — квадратики, прилепленные к действиям.
Еще одна полезная штука — Connector (Коннектор). Это полый кружок с названием внутри. Коннекторы полезно использовать тогда, когда неохота рисовать загромождающие диаграмму связи.
Activity (Деятельность, кажись) — это процесс. Т. е. везде выше, где было использовано слово "процесс", его можно заменить на Activity. Мы и рисуем как раз Activity Diagram — вся наша диаграмма посвящена какой-то Activity (= какому-то процессу). Не удивляйтесь, если увидите нечто похожее на пример ниже — так иногда показывают границы моделируемого процесса (Activity, как и Action — это прямоугольник с закругленными концами):
Встраивание одного процесса в другой делается через Action особого типа — Call activity action. Если увидите на диаграмме action, который помечен трезубцем, знайте, что этот action — это отсылка на другую Activity, которая, вероятно, детализирована на отдельной диаграмме.
Interruptible Edge полезная (но нагружающая диаграмму) вещь, с помощью которой можно показать, что в какой-то области (целой области в отличие от отдельного action) может что-то пойти не так. В частности, с помощью такой штуки можно показать, что в нескольких шагах (т. е. на любом из них) юзер может отменить весь процесс. Изображается целым набором элементов: областью со штриховой связью (Region), прерывающим событием (Event) и Interrupt Flow — связью-молнией.

Типовые ошибки:

Как и раньше, вот они все на одном рисунке, а дальше уже детализируем:
Отсутствие decision, merge, fork или join при ветвлении/слиянии потоков
Есть простое неформальное правило: делаем только один выход из/вход в action — не более. Если их больше — нам нужны альтернативные или параллельные потоки, оформленные с помощью ромбиков или палочек.
Отсутствие actions — подмена их связями
Связи (Control Flow, Object Flow, Interrupting Flow) — это только лишь переходы от одного элемента к другому. Связь не может заменять собой действие, объект или что-либо еще значимое. Не забываем явно оформлять все действия в виде actions.
Зависшие подпроцессы, отсутствующие варианты ветвлений, зависшие циклы и прочие ошибки в алгоритме
Если из какого-то action ничего не выходит, это сигнал к тому, что у вас что-то не так — процесс завис. Он не дошел ни до одного из пунктов выхода. Не забываем представлять в уме точки, бегущие по диаграмме — они все должны дойти до конца процесса.
Если из decision/fork выходит или в merge/join входит только одна связь — вы что-то делаете не так. Суть этих элементов в том, чтобы ветвить/объединять потоки.
Отсутствующие guards для выходов из decision
Капитан подсказывает, что если guards на выходах нет, неясно, в каком случае куда поток пойдет. Просто не забываем их подписывать.
Путаница между событиями и действиями
Действие (Action) — это в активной форме "кто-то что-то делает", а не событие (Event), где что-то "происходит" или "наступило". В UML есть способ показать события, и частный вариант этого мы разобрали (прерывающее событие). Такое нечасто требуется, плюс далеко не все умеют читать этот элемент, поэтому события в целом мы в заметке не рассматривали. В целом, не стоит смешивать эти два понятия.