6 活动图
活动图侧重于将程序处理建模为系统。它规定了实现活动所需的各个步骤--操作--之间的控制流和数据流。
在UML2中,活动图使用面向流程的语言概念,这些概念起源于定义业务流程的语言。
活动图也基于用于描述并发通信过程的既定概念,如Petri网的标记概念。活动图的特点是既支持面向对象系统建模,也支持非面向对象系统建模。活动图允许您独立于对象、面向对象和非面向对象系统建模来定义活动,这意味着您可以对功能库、业务流程和现实世界的组织进行建模。
UML标准没有规定任何特定的活动符号形式。除了活动图中基于流程的符号元素,该标准还允许其他形式的符号,如结构图甚至伪代码。除了自定义符号元素外,还出现了一些重复出现的控制流和数据流模式。这些模式特别用于业务流程建模,并被证明对复杂流程非常有用。这些结构被称为"工作流模式"。
在本章中,善于观察的读者会注意到,并非所有示例都对完整的流程进行了建模--有些模式仅限于流程的摘录。因此,举例来说,有些图并不包含初始和最终节点。但实际上,一个完整的活动图必须有明确定义的起点和终点。
6.1 Activities
活动图允许您以活动的形式指定用户定义的行为。活动本身可以描述一个用例的活动实现。在非常详细的层次上,它还可以以单个指令的形式定义操作行为,或者在不太详细的层次上,对业务流程的功能进行建模。业务流程定义了业务伙伴如何相互影响以实现其目标。它还可以描述公司的内部流程。因此,可以在不同的粒度水平上定义行为。一项活动可以分配给一个类的操作,但也可以是独立的。
与Petri网一样,活动的内容也是有向图。其节点代表活动的组件,如操作、数据存储和控制元素,其边代表控制流或对象流,即活动的可能执行路径。
活动被描绘成带圆角的矩形,与操作一样,活动也可以有参数。这些参数显示为在活动边界重叠排列的矩形。为使图表更易于阅读,应将输入参数置于活动的左侧或上边界,将输出参数置于右侧或下边界。这样就可以从左到右和/或从上到下读取活动。通过输入参数传送到活动中的值,可以提供给那些通过有向边与输入参数相连的操作(见 下一节)。同样,输出参数通过有向边从活动中的操作接收其值。下图中的示例显示了执行活动 "参加考试"的必要步骤。输入参数是学生的预科编号和学习计划ID。
6.2 操作(Actions)
操作是活动的基本元素。与活动一样,操作也是一个圆角矩形,操作名称位于圆角矩形的中心位置。您可以使用操作指定任何用户定义的行为。动作描述没有特定的语言要求。因此,您可以使用自然语言或任何编程语言来定义操作。例如,如果执行操作后,变量i的值要增加 1,可以使用 i++ 或简单地写成 Increase i by one。
操作处理输入值以产生输出值,这意味着它们能够执行计算。它们还可以从内存中加载数据,并改变系统的当前状态。上图的示例中,"注册"、"写入考试 "和 "更正 "都是操作。
在活动上下文中,操作总是原子性的,也就是说,在建模上下文中,操作的原子性无法被进一步分解。但是动作可以指代另一个本身由动作组成的活动。尽管行动可能由多个单独步骤组成,但它们仍被视为原子性的。例如,注册考试通常需要多个步骤,如登录系统、选择合适的课程和考试日期。尽管如此,我们还是有意将 "注册"建模为操作而不是活动。这是因为在本模型中,注册的执行被视为单一的步骤;然而,我们对这一步骤的内部细节并不感兴趣,因此我们没有将其进一步细分。
我们要区分控制流边和对象流边:控制流边只定义操作之间的顺序,而对象流边也可用于交换数据或对象。
在UML中,有许多预定义的、非特定语言的预定义动作,由于它们的详细程度,您可以在任何目标语言中轻松建模。
UML中的预定义动作可根据其功能和复杂程度分为不同类别。下面我们将讨论其中最重要的两类。
6.2.1 基于事件的动作
基于事件的动作可以将对象和信号传递给接收对象。它们允许您区分不同类型的事件。您可以使用接受事件操作来模拟或等待特定事件发生的操作。接受事件操作的符号元素是 "凹五边形"--尖端从左侧向内的矩形。如果事件是基于时间的事件,则可以使用接受时间事件操作,在这种情况下,符号是沙漏。
接受(时间)事件操作不一定有输入边缘。如果没有输入边,则会在相应事件发生时启动。它们保持激活状态,也就是说,它们可以接收信号,直到包含它们的活动结束。下图显示了三个接受(时间)事件操作的示例:每当触发火警警报时,必须疏散阶梯教室;学期结束时,颁发证书;学生参加考试后,等待成绩并在收到成绩时检查试卷。
要发送信号,可以使用发送信号操作。发送信号操作用"凸五边形"表示,即一个尖端向右突出的矩形。下图(b) 中的操作"发送等级"就是发送信号操作的一个示例。
6.2.2 调用行为操作
操作可以调用活动本身。这些操作被称为调用行为操作A调用行为操作,并标有一个倒叉符号。分叉符号表示层次结构。它表示该操作的执行会启动另一个活动,从而将系统划分为不同的部分。上图(a) 显示了调用行为操作的一个示例。在该图中,"组织考试 "活动中的 "签发证书 "操作指的是详细说明 "签发证书 "的活动。在 "组织考试 "活动的上下文中,导致签发证书的内部步骤并不相关。因此,尽管签发证书涉及一个包含多个操作的过程,但它在这里被视为一个原子单元。
参考资料
- 软件测试精品书籍文档下载持续更新 https://github.com/china-testing/python-testing-examples 请点赞,谢谢!
- 本文涉及的python测试开发库 谢谢点赞! https://github.com/china-testing/python_cn_resouce
- python精品书籍下载 https://github.com/china-testing/python_cn_resouce/blob/main/python_good_books.md
- Linux精品书籍下载 https://www.cnblogs.com/testing-/p/17438558.html
6.3 控制流
活动由其他活动和操作组成,这些活动和操作通过边与描述流程的令牌相连。如果我们观察一个活动的图,静态结构并不能清楚地显示执行是如何进行的。为了将动态行为整合到图中,我们需要执行语义,也就是说,我们必须明确说明活动图是如何执行的。
Petri引入的令牌概念是活动图执行语义的基础。令牌是一种虚拟协调机制,能准确描述执行过程。在这里,虚拟意味着令牌不是图的物理组件。它们是授予行动执行权限的机制。如果一个动作收到令牌,则该动作处于激活状态,可以执行。一旦动作结束,它就会通过边将标记传递给后续节点,从而触发该动作的执行。一旦该操作结束,它就会将标记传递给外向边或保留标记,直到满足特定条件为止。
标记的传递可以通过guard 来阻止。下图的示例中,只有当学生报名参加考试时才会举行考试。
只有当所有输入边上都有标记时,才能执行操作。如果一个操作有多条出站边,则会向这些边上的所有目标节点提供令牌,从而将其分割成多个独立的执行路径。特殊节点也可作为这种并发建模的替代方案。
当一个动作被执行时,通常会消耗其每条传入边上的一个标记。另外,也可以在边上加权。边的权重用关键字 weight 在大括号中指定。它总是一个大于或等于零的整数。如果权重为零,这意味着所有存在的标记都会被消耗。也可以用all或∗代替0。如果没有指定权重,则默认值为1。下图给出了一个使用权重的例子。如果Register信号接收到30次,即至少有30名学生注册,并因此向后续操作提供了30个代币,那么后续操作将被执行,消耗30个代币,并创建一个新组。
如果要通过边连接的两个操作在图中相距较远,可以使用连接器使图更清晰。在这种情况下,您不必将边画成一条从一个操作到另一个操作的连续线段。连接器以包含连接器名称的小圆圈表示。每个连接器必须在活动中出现两次:一次是输入边,一次是输出边。下图模拟了两个操作之间的关系。
活动图提供了用于控制控制流的特殊节点。这些节点称为控制节点。初始节点表示活动开始执行的位置。
初始节点没有任何输入边,但至少有一条输出边,以黑色实心圆圈表示。最终节点,表示活动的结束,该节点由一个黑色实心圆圈标注在另一个圆圈内。
每个活动还允许有多个初始节点。这样就可以表达并发性,即多个执行路径可以同时活动。如果调用了具有多个初始节点的活动,所有初始节点的出站边都会同时获得标记。
决定(决策)节点来模拟备选分支。这些节点是标记的切换点,相当于传统编程语言中的if语句。决策节点被描绘成一个菱形,有一条输入边和多条输出边。出边有保护(也称为条件)。与其他UML图表一样,守护符是括在方括号内的布尔表达式。这些条件不能重叠,也就是说,系统必须能清楚地决定一个标记在特定情况下应该走哪条出站边。例如,不允许有一条出站边的条件是 [x > 1],另一条出站边的条件是 [x < 3],因为在 x = 2 的情况下,标记不可能选择唯一的出站边。如果在决策节点上有一个标记,系统必须能够根据当前的上下文(例如,取决于变量的值)清楚地决定该标记应走哪条路径才能离开决策节点。
您可以为决策节点指定决策行为,这些行为是评估保护所必需的。这样可以避免在不同的保护程序中多次执行相同的计算,因为计算结果可以在每个保护程序中访问。但是,这种行为不得产生任何副作用,也就是说,在执行决策节点中定义的行为时,不得改变对象和变量的值。决策行为作为标有"decisionInput"的注释附加到决策节点上。考试成绩一经公布,中央部门就会决定是否为学生提供查阅改卷的机会。如果决定是肯定的,则允许学生检查他们的试卷。随后颁发证书。如果决定是否定的,则立即发放证书。
如果要将备选子路径重新组合在一起,可以使用合并节点 ...可以使用合并节点来实现。该节点也是菱形节点,但有多条入边,只有一条出边。特别是,一个标记最多只能出现在一条入边上。
可以使用多个初始节点来模拟活动开始时的并发性。如果一条执行路径后来分裂成多条同时激活的执行路径,可以使用并行化节点来实现。
您可以将多个活动最终节点合并为一个具有多条输入边的活动最终节点。只要有一个标记通过输入边到达活动最终节点,整个活动就会结束。
如果只想结束一条执行路径,而其他同时活动的执行路径不受影响,则必须使用流程最终节点Flow final 节点。该节点只删除直接流入该节点的标记,从而只结束相应的路径。活动的所有其他标记不受影响,可以继续存在。流程最终节点由一个包含 X 的小圆圈表示,只有输入边。
成功参与作业和同时参加相关讲座以及参加考试是两条独立的执行路径,每条路径都以一个流最终节点结束。但是,作业不及格会终止整个活动,也就是说,如果学生的作业成绩为负数,那么该学生就不能再参加期末考试。
综合实例:
6.4 对象流
到此为止,我们主要研究了控制流,重点是动作的逻辑顺序。所描述的令牌概念只使用控制令牌。为简化起见,到目前为止,我们只将其称为标记。不过,行动使用数据令牌交换数据的情况也可能发生,甚至很有可能发生。就像控制标记一样,这些标记从未在图中绘制过,而且也仅用于描述活动图的执行语义。数据标记隐含地也是控制标记,因为这些标记的交换会影响活动的流程。数据可以是操作的结果,也可以作为后续操作的输入。不过,数据也可以通过活动的输入参数接收,并传递给输出参数。
输入参数通常只在活动开始时读取一次,而输出参数则在活动结束时写入一次。如果希望在活动执行过程中不断读写参数,可以用关键字 {stream} 标记输入或输出参数。下图显示了活动或操作的输入和输出参数流的示例(操作参数将在下文中介绍)。操作的流参数可以用填充矩形表示。
当活动结束时,任何没有标记的输出参数都会被分配一个空标记。在活动中,可以使用对象节点来明确表示数据交换。对象节点有多种显示方式。它们既可以像对象图(参见第 49 页)中那样显示为一个单独的节点,也可以作为输入或输出引脚直接连接到操作。下图给出了一个对象节点作为独立节点的示例。它以矩形的形式添加在传送数据的操作和操作之间。
动作的引脚符号与活动的参数引脚符号相对应。它同样用于表示作为操作输入和输出的对象。在相应动作边界的边缘开头或结尾处指定一个小矩形。我们可以用与显式表示矩形对象节点时相同的信息来注释该引脚。
活动图提供了用于保存和传递数据标记的特殊对象节点:中央缓冲区和数据存储区。中央中央缓冲区 "centralBuffer
中央缓冲区是一个特殊的对象节点,用于管理多个数据源和多个接收器之间的数据流。它接受来自对象节点的传入数据令牌,并将这些令牌传递给其他对象节点。与插针和活动参数不同,中央缓冲区不与操作或活动绑定。从中央缓冲区读取数据令牌后,该数据令牌就会在中央缓冲区被删除,不能再被使用。下图显示了使用中央缓冲区的一个示例。要执行 "授予访问权限 "操作,必须从密钥柜中取出密钥。然后,密钥就不在密钥柜中了,直到在撤回访问授权的操作中返回密钥。
在数据存储区中,流入数据存储区的所有数据令牌都会被永久保存。
DS永久保存,这意味着它们在离开数据存储之前会被复制。您可以在数据存储的输出边缘定义有关数据存储内容的查询。这些查询使用注释符号附加到出站边。因此,数据存储可以模拟数据库的功能。
课程学员的成绩在数据存储ExamData中进行管理。这些数据包括计算总成绩所需的作业任务评估和考试成绩。
中央缓冲区代表瞬时存储器,而数据存储区代表永久存储器。对于前者,信息只能使用一次,也就是说,一旦从中央缓冲区读取并转发,信息就会丢失。而对于数据存储,只要信息在数据存储中保存过一次,就可以根据需要随时使用。
6.5 分区
分区可以根据A分区B分区的共同属性对活动的节点和边进行分组。例如,如果我们考虑一个业务流程,我们可以用分区来分组特定实体负责执行的所有操作。UML 对可以使用的分组标准没有严格的规定。一般来说,分区反映了负责执行分区内操作的组织单位或角色。您可以指定不同详细程度的分区,直至单个类的级别。分区可以以任何方式重叠和嵌套。分区不会改变活动图的执行语义,活动图的执行语义是由标记定义的。这意味着分区不会影响标记流,而只是代表了其组成部分的逻辑视图。分区使图表更加清晰,使您能够快速查看责任区域,从而在模型中引入更多详细信息。
分区可以用图形或文本形式表示。以图形形式描述时,分区会以 "开放"矩形的形式放在活动图的顶部。位于"开放"矩形内的所有元素都属于一个共同组。分区的名称指定在矩形的一端。由于其外观,分区也被称为泳道。
参与方包括一名学生、一名助教和一名教授。使用分区可以为每个参与者分配他们必须执行的操作。
一个分区本身可以细分为多个子分区。分区也可以是多维的。
您也可以将一个操作指定给一个分区,或者在多维分区中指定给一组文本形式的分区。
6.6 异常处理
如果在执行操作过程中出现错误,执行将被终止。在这种情况下,无法保证操作会提供预期的输出。如果一个操作有一个针对特定错误情况的异常处理程序,那么当异常发生时,该异常处理程序将被激活。使用异常处理程序,可以定义系统在特定错误情况下的反应方式。您可以为特定类型的错误指定一个异常处理程序,也就是说,您可以为不同的错误使用不同的异常处理程序。如果发生错误,相关操作中的所有标记都会被立即删除。如果有匹配的异常处理程序,则会替换相关操作的内容,取而代之的是执行异常处理程序的内容。然后,序列继续按照活动的常规路径运行,就像有缺陷的操作正常结束一样。
由于异常处理程序是一个活动节点,因此用圆角矩形来表示。异常处理程序所保护的操作用一个闪电箭头指向异常处理程序。箭头的顶端标有错误类型。图 7.25 显示了两个处理异常的示例。如果打印过程中出现卡纸,一旦卡纸被清除,打印就可以继续。如果打印机中没有纸张,则必须插入纸张才能继续打印,直到打印出足够的考试说明副本为止。
它对变量和值的访问权限与它所保护的节点相同。执行异常处理程序内容所产生的标记将成为受保护节点的结果标记。
因此,异常处理程序和受保护节点必须有相同数量的返回值。这样就能确保在发生错误时,受保护节点的每条出站边都能收到所需的标记。
可中断活动区域是处理例外情况的另一种方法。利用这一概念,您可以定义一组操作,如果发生特定事件,这些操作的执行将立即终止。可中断活动区域用一个带圆角的虚线矩形来表示,它包围了相关的操作。这些事件的执行会受到监控,以防发生特定事件,例如错误。
如果事件在执行过程中发生,则会执行特定的操作。在可中断活动区域内,您可以对代表特殊事件的接受事件操作进行建模,并以闪电形式从边 缘引出到可中断活动区域外的活动。如果建模事件发生,可中断活动区域中的所有控制标记都会被删除,接受事件操作指向的操作也会被激活。下图显示了一个可中断活动区域的示例。如果学生在上课期间退学,则会执行 "学生退学 "操作。
但是,只有在学生已经注册,且 "参加考试 "操作尚未结束的情况下,才有可能退学。在所有其他情况下,都会颁发证书。