Диаграммы деятельности
Диаграммы деятельности - это технология, позволяющая описывать логику процедур, бизнес-процессы и потоки работ. Во многих случаях они напоминают блок-схемы, но принципиальная разница между диаграммами деятельности и нотацией блок-схем заключается в том, что первые поддерживают параллельное процессы.
Диаграммы деятельности подвергались самым большим изменениям при смене версий языка UML, поэтому неудивительно, что они были снова изменены и существенно расширены в UML 2. В UML 1 диаграммы деятельности рассматривались как особый случай диаграмм состояний. Это вызвало немало трудностей у специалистов, моделирующих потоки работ, для которых хорошо подходят диаграммы деятельности. В UML 2 это ограничение было ликвидировано.
На рис. 11.1 показан пример простой диаграммы деятельности. Мы стартуем с начального узла (initial node), а затем выполняем операцию Receive Order (Принять заказ). Затем идет ветвление (fork), которое имеет один входной поток и несколько выходных параллельных потоков.
Из рис. 11.1 видно, что операции Fill Order (Заполнить заявку), Send Invoice (Послать счет) и следующие за ними выполняются параллельно. По существу, в данном случае это означает, что последовательность операций не имеет значения. Я могу заполнить заявку, послать счет, доставить товар (Delivery), а затем получить оплату (Receive Payment); или я могу послать счет, получить оплату, заполнить заявку, а затем доставить товар. Посмотрите на рисунок.
Я могу также выполнять операции поочередно. Я беру со склада первую позицию заказа, печатаю счет, беру вторую позицию заказа, кладу счет в конверт и т. д. Или я могу что-то делать одновременно: печатать счет одной рукой, а другой рукой брать что-нибудь со склада. Согласно диаграмме, любая из этих последовательностей действий допустима.
Диаграмма деятельности позволяет любому, кто выполняет данный процесс, выбирать порядок действий. Другими словами, диаграмма
только устанавливает правила обязательной последовательности действий, которым я должен следовать. Это важно для моделирования бизнес-процессов, поскольку эти процессы часто выполняются параллельно. Такие диаграммы также полезны при разработке параллельных алгоритмов, в которых независимые потоки могут выполнять работу параллельно.
При наличии параллелизма необходима синхронизация. Мы не закрываем заказ, пока он не оплачен и не доставлен. Это показывается с помощью объединения (join) перед операцией Close Order (Закрыть заказ). Исходящий из объединения поток выполняется только в том слу-
чае, когда все входящие потоки достигли объединения. Поэтому вы можете закрыть заказ, только когда принята оплата и заказ доставлен.
В UML 1 действовали определенные правила для балансировки ветвлений и объединений, так как диаграммы деятельности представляли особый случай диаграмм состояний. В UML 2 в такой балансировке уже нет необходимости.
Заметьте, что узлы на диаграмме деятельности называются операциями (actions), а не активностями (activities). Строго говоря, деятельность относится к последовательности действий, поэтому диаграмма представляет деятельность, состоящую из операций.
Условное поведение схематически обозначается с помощью решений (decisions) и слияний (merges). Решение, которое в UML 1 называлось ветвью, имеет один входящий поток и несколько защищенных выходных потоков. Каждый выходной поток имеет защиту - условное выражение, помещенное в квадратные скобки. Каждый раз при достижении решения выбирается только один из выходных потоков, поэтому защиты должны быть взаимно исключающими. Применение [else] в качестве защиты означает, что поток [else] используется в том случае, когда другие защиты данного решения принимают ложное значение.
На рис. 11.1 решение располагается после операции заполнения заявки. Если у вас срочный заказ, то он выполняется в течение суток (Overnight Delivery); в противном случае производится обычная доставка (Regular Delivery).
Слияние (merge) имеет несколько входных потоков и один выходной. Слияние обозначает завершение условного поведения, которое было начато решением.
На моей диаграмме каждая операция имеет один входящий в нее поток и один выходящий. В UML 1 подразумевалось, что несколько входящих потоков имеют слияние. Другими словами, операция выполнялась, если запускался любой поток. В UML 2 это было изменено, так что вместо слияния предполагается объединение; таким образом, операция выполняется, только если все потоки пройдены. Поэтому я рекомендую применять операции с единственным входным потоком и единственным выходным, а также явно показывать все объединения и слияния; это избавит вас от путаницы.