智睿思维Logo智睿思维

MBSE建模学习之四:活动(Activity)及活动图

活动(Activity)

活动(Activity)是一种行为(Behavior)元素,它是行为元素的子类。首先活动是一个“类”(class)。SysML中,它也是一个模块(block),所以它有“类”的特征,可以有属性、方法,还可以有下层的“行为”元素,形成一个多层嵌套的行为模型。其次,活动是一个“行为”元素,有输入参数和输出参数。活动元素的特殊之处在于它可以包含各种可以说明一个行为过程的元素,包括“动作”(Action)、控制流(ControlFlow)和对象流(ObjectFlow),以及其它说明控制逻辑的节点。

活动可以用来说明系统的功能,活动以及它包含的子活动元素、活动中的动作元素,可以形成一个系统的功能结构树。在进行系统的功能分析的时候,它是重要的说明元素。

作为一个行为元素,活动可以作为一个模块(Block)的拥有行为,用于说明一个模块的功能。此外,活动也可以作为其它行为元素的更具体的说明。如,对一个用例(UseCase)进行更详细的说明,可以把活动元素作为用例的拥有行为(用例也是一种行为类BehavioredClassifier,可以拥有行为)进行说明;活动也可以作为状态机中的状态(State)的内部行为,或系统处于某个状态时进行的工作;活动也可以作为状态转移(Transition)的影响(effect),说明状态转移时发生的行为。

在“智睿思维基于模型的软件”(MBSES)中,你可以为一个模块增加拥有行为的时候,增加一个活动元素。也可以直接在一个包中增加一个活动元素。

UML\SysML是面向对象的语言,活动是一个说明具体行为过程的元素。可以说活动和它的活动图是用UML\SysML语言写的一段系统运行过程的“程序”。这段“程序”要有运行的语境(Context),也就是活动的过程可以读写的变量的范围。这个语境就是活动所属的模块。如果活动没有所属模块,那它自己就是自己的语境。在活动的过程中,可以读写它的语境中的属性(Property)、可以调用所属语境的其它行为(通过一个调用行为动作)。当然也可以调用(通过一个“调用操作动作”)另外一个模块的操作(Operation)、接收(Reception),但必须通过当前模块的一个部件(part)属性或引用(reference)属性。这是面向对象语言的“封装”性原则所规定的,这个原则使我们定义的系统模型中功能调用关系是清晰的、范围可控的。

活动图示例

下面以一个具体的人造卫星做霍曼转移、变轨过程的活动图来说明活动图中元素及其作用和意义。

人造卫星从一个较低运行轨道转移到一个较高的运行轨道,需要两次发动机点火、加速的过程。如右图所示,人造卫星从低轨道“1”送往较高轨道“3”,先在低轨道“1”上瞬间加速,进入一个椭圆形的转移轨道“2”。卫星由此椭圆轨道的近地点开始,抵达远地点后再瞬间加速,进入另一个圆轨道(3),此即为目标轨道。

首先定义这个过程的活动元素为“执行霍曼转移”,有一个类型为“转移命令”的输入参数(命令中包含执行时间点、目标转移轨道高度),以及一个类型为“命令响应”的返回参数(返回命令是否合法的响应,这是一个“流”类型的返回参数)。定义的语法如下:

“执行霍曼转移(当前命令: 转移命令) :命令响应{流}”

对应的活动图如下(来源于《SysML精粹》图6.1,进行中文翻译。此图使用“智睿思维基于模型的系统工程软件--MBSES”制作)

活动图中有以下几类节点,说明如下。

动作(Action)

动作是活动中的基本功能执行单元,动作是最底层的功能单元,不能(或当前建模要求下不需要)再分解。每个动作也可以有输入(输入栓)和输出(输出栓),作为这个动作处理的数据和结果。

在活动图中,通过控制流(ControlFlow)或对象流(ObjectFow)将动作串联起来,表示动作执行的过程顺序。

在控制流或对象流中传递的数据称为“令牌”(Token)。这些令牌可以是一次一个数据的方式传递,也可能是按“流”的方式连续的传递(针对对象流)。

一个动作能够执行的条件是:

(1)动作所在的活动在执行;

(2)动作中所有连进来的控制流上都有控制令牌到达。

(3)所有输入对象流上都有足够数量的对象令牌到达,以满足相应输入栓的最低多重性要求(值栓除外,值栓不需要对象流)。

如果一个动作没有任何输入的控制流及对象流,则当所在活动开始执行的时候,这个动作就开始执行。

活动图中的具体动作节点类型有40多种,每一类动作节点有具体的用途。常用的动作类型如下:

(1)不透明动作(OpaqueAction)

不透明动作是用某种语言(包括自然语言,或某种编程语言)描述的一个功能。不透明动作一般用一个动词短语描述一个功能。如图中的“生成’合法命令’状态响应”节点用自然语言说明一个系统将执行的一个功能;“:{C}当前轨道半径=当前高度+地球.半径”节点用C语言的赋值语句说明了这个节点将执行的数据处理功能。

(2)调用行为动作(CallBehaviorAction)、调用操作动作(CallOperationAction)

“调用行为动作”表示对另外一个行为元素(可能是另外一个具体的活动、交互或状态机)的调用。调用操作动作表示对一个模块的实例的操作的调用。这两个“调用动作”在节点中一般会显示显示一个叉的符号。如图中的“vc: 验证命令”和“ma: 测量高度”动作就是两个调用行为动作。

活动的分解,就是通过在一个活动的活动图中定义“调用行为动作”调用下层的活动来实现的。在节点中,它的文本表示语法是:

“动作名称:被调用的行为名称”

在MBSES软件中,通过节点的右键菜单“设置行为元素”来设置调用的对应的行为。在进行活动图的仿真时,遇到调用行为节点将会打开对应行为元素代表的图,并继续执行。

“调用操作动作”有一个“目标”输入栓,这个“目标”栓的实例,就是将被调用的操作所在的实例。

这两个调用动作节点,要求其它输入栓和输出栓应该和被调用的行为或操作的参数对应。

(3)发送信号动作(SendSignalAction)

发送信号动作表示动作将生成一个某种类型的信号,并发送到指定的“目标”输入栓对象。信号的类型是在模型中某个地方定义的信号(Signal)元素。向一个对象发送信号,相当于调用了对象中和信号类型对应的“接收”(Reception)。“接收”和操作类似,只不过接收的名称和接收的信号类型相同,参数和接收类型的属性对应。对“接收”的调用都是“异步”的,意味着发送信号动作不会等待被调用“接收”对应的行为执行完,而是立即执行下一个动作。

发送信号的其它输入栓应该和信号类型的属性对应,从而作为生成信号属性的数据。

如果没有定义“目标”栓,则发送信号动作将把信号发送到当前图中对应的“接收信号动作”(接收事件动作,而且事件类型是一个信号,见下一节)。上面示例图中,“轨道半径更新”发送信号动作没有规定“目标”栓,则信号发送到当前图中的“轨道半径更新”接收事件动作。

(4)接收事件动作(AcceptEventAction)

接收事件动作的触发,除了上述动作执行的条件之外,还有一个条件就是接收事件动作的触发器事件发生。一个接收事件动作可以有多个触发器(Trigger),每个触发器有一个触发事件。触发器的事件类型有“调用事件”(当前语境对象的某个操作被调用时发生)、“信号事件”(当语境对象接收到某个类型的信号时发生)、“变动事件”(当这个事件定义的表达式的值从“false”变为“true”的时候发生)、“时间事件”(见下节说明)、“任何接收事件”(当接收到一个包含任何除信号之外的其它“对象”的消息的时候发生。通常由一个SendObjectAction –“发送对象动作”引发)。

根据接收事件的类型不同,接收事件动作显示的语法不一样。当接收事件是一个“调用事件”的时候,显示操作的定义;当接收事件是一个“信号接收事件”的时候,显示信号类型的名称(如示例图中的“轨道半径更新”接收事件动作);当接收事件是“变动事件”时,显示“when 表达式”;当前信号类型是“时间事件”的时候,显示“at 时间点”,或“after 时间点”;当接收事件类型是“任何接收事件”时,显示“all”。

(5)等待时间动作(Action)

当一个接收事件动作只有一个类型是时间事件的触发器时,这个动作非正式的称为“等待时间动作”,它的节点用一个沙漏的形状来表示。

等待时间动作的时间事件,有两种时间表示方法。一种是绝对时间,用“at 具体时间”来表示;另外一种是相对时间,用“after 多少时间”表示。等待时间动作只能有一个输出的结果栓。当时间事件发生时,发生时间值被放到这个结果输出栓上。如示例图中的“at 当前命令.执行时间”,表示时间到达命令中的执行时间点的时候,时间事件触发器触发,才会执行下一步的“进入转移轨道:点火推进器”动作。

(6)控制操作(ControlOperator)

控制操作是一个构造型,它用于一个行为(一个具体活动、交互或状态机),表示这个行为具有一个复杂的逻辑,能够接收或返回一个“控制值类型”(ControlValueKind)的参数。“«控制操作»”会用于一个“调用行为动作”,表示调用的行为是对控制值类型数据的处理。“控制值类型”是一种特殊性数据,可以取值“使能”(enable)或“使不能”(disable)。一般情况下,当一个动作接收到“控制值类型”的参数的时候,根据值参数值动作进入可以执行状态或不能执行(停止执行)状态。但是一个具有“«控制操作»”构造型的调用行为动作收到“控制值类型”参数,不是停止这个调用行为动作执行,而是它会处理这个参数,而且可能根据具体逻辑返回一个“控制值类型”参数,然后传递给其它动作来控制其它动作的执行。

除了以上常用的动作类型,UML标准中还定义了其它30多种动作,这些动作主要是某些特殊类型对象的创建、读取、删除、销毁等操作。

控制流(ControlFlow)和对象流(ObjectFlow)

控制流和对象流把动作和控制节点连接起来,表示动作发生的顺序和条件。在UML标准中,控制流和对象流都是“活动边”(ActivityEdge)的子类型;换句话说,它们都是控制边,控制边有的特征,它们都有。

控制流表示控制令牌数据的传递。在MBSES软件中,控制流用虚线表示。控制流直接把动作、控制节点连接起来。当一个动作连入的控制流有控制令牌到达的时候,这个动作才“可以”执行。控制流中的令牌可以理解为对“动作”的一次调用命令。一个动作所有的连入控制流是“与”的关系,也就是如果一个动作有多个连入的控制流,要所有控制流都有令牌到达动作才能够执行。所以,当我们表示一个循环执行的动作的时候,不能把这个动作输出的控制流又连回到这个动作,而应该在连入自己之前,和别的连入控制流(首次执行连入的控制流)用一个“合并”节点合并为一个连入的控制流。如上述活动图中“轨道半径更新”接收信号事件动作前后的合并节点和决定节点。

对象流中传输的是数据或其它定义的类型(如水流、电流等任何定义的“模块”类型或值类型)的实例对象,或者活动参数代表的对象。对象流中的“对象”令牌是动作执行中处理的内容,类似是“动作”的输入、输出参数。在MBSES软件中对象流用实线表示。

对象流必须通过“栓”(Pin)连到动作上,除非对象流中间用一个“对象节点”的方式简化两端的栓表示法。

控制流或对象流的“守卫条件”指这个边能执行的条件;例如上述活动图中验证命令之后的“决定节点”的两个输出边,“[命令是否合法=是]”和“[命令是否合法=否]”表示两个输出对象流路径的执行条件。

活动边“概率”属性表示这条边能够走过的概率;“权重”表示当这个边上需要的最小令牌数量条件,当这条活动边上通过的令牌数量满足这个权重条件的时候才会通过。当对象流上流过的对象是“流”的时候,可以定义活动边上对象通过的“比率”值,这个值应该是一个单位时间内通过的对象数量。如“0.2kg/s”。当通过的每个对象之间的时间间隔为0,则是“连续”;否则是“离散”。

对象节点(ObjectNode)

对象节点对动作之间传输的对象进行定义。对象节点的类型可以是“模块”(Block)或其它数据类型。它可以代表一种数据,也可以代表我们的模型中定义的任何物质。

对象节点一般是作为一个动作(Action)的“输入栓”(InputPin)或“输出栓”(OutputPin)。“输入栓”(InputPin)或“输出栓”类似动作的输入、输出参数。

“值栓”(ValuePin)是一种特殊的输入栓,它不需要对象流传入,它的值是用定义的表达式计算的。当动作符合执行条件的时候(其它输入控制流都有控制令牌到达、其它输入栓都有对象流到达或满足最小令牌数条件),动作就从这个“值栓”的表达式中计算一个值作为输入。

对象节点本身不代表传输的对象,它是对传输对象的形态进行定义。传输的对象是对象节点类型的实例,每个实例称为一个“令牌”。在活动执行过程中,有很多个“令牌”通过连接对象节点的对象流。但并不是一有“令牌”对象到达,动作就一定执行。例如处理视频播放功能的一个动作,要等到视频数据“缓冲”到一定量才执行。对象节点的“下限”属性就是定义动作执行一次需要的最小数据量。如果对象节点不能“缓冲”,则应用“非缓存”(«nobuffer»)构造型。

“接收令牌数上限”是指当到达的令牌数量超过这个值之后,不再接收令牌。因为动作一次执行不一定把到达的令牌全部拿走(消费),消费不完令牌会积累,积累到一定量的时候,就拒绝上一环节的动作发送新的令牌。例如当调用一个http协议的服务的时候,如果post的数据量超过这个http服务接收的“最大令牌数量”时,这个服务将拒绝新的post请求,以防服务崩溃。

“覆盖”(«overwrite»)表示新到达的令牌超出对象节点规定的上限时,覆盖已有令牌而不是拒绝接收。

“可选”(«optional»)表示对象数据对于动作的执行时可选的,也就是“下限”是0。

应用了“控制”(«control»)构造型,说明传输的数据类型是“控制值”类型(见控制操作一节说明)。

如果用了“流”(«stream»)构造型,说明对象是一种“流”类型。此时,可以进一步定义“流”的参数:比率(rate)、离散或连续的。

“排序”是对象节点中的令牌是按什么顺序被动作节点消费或传送到下一个节点的。有四种顺序可选:“无序”、“有序”、“先进先出”(FIFO)和“先进后出”(LIFO)。

“包含状态”是指令牌对象的取值范围,只能在“包含状态”定义的几种状态中取值。这几种状态应该是对象节点类型的状态机中定义的状态。

除了动作上的栓,还有以下类型的对象节点:

“活动参数节点”(ActivityParameterNode):对应活动的一个输入或输出参数。在示例图中,“当前命令:转移命令”是活动参数节点(一般放在活动图左边);“:命令响应”是输出的活动参数节点(一般放在活动图下边缘,或右边缘);

“中心缓存节点”(CentralBufferNode):作为缓存作用的对象节点。

“数据存储节点”(DataStoreNode):数据存储节点中的令牌对象被输出活动边拿走后,仍然会保留一份值相等的令牌对象,永远拿不完。而“中心缓存节点”中的令牌对象被取走后就没有了。但是“数据存储节点”中存储的对象按ID保存,相同ID的对象仅存储一份。

控制节点(ControlNode)

控制节点的类型主要有以下几种:

“决定节点”(DecisionNode):最少一个、最多两个输入的活动边,最少一个输出的活动边。如果有两个输入的活动边,则其中一个必须是对象流,这个输入对象流的数据用于决定节点输出的对象流活动边守卫条件的判断。在示例图中有两个“决定节点”。

“合并节点”(MergeNode):合并节点只能有一条输出活动边、多条输入的活动边。当任何一条输入活动边有令牌到达,则转发到输出的活动边。在示例图中有两个“合并节点”。

“分支节点”(ForkNode):分支节点只有一个输入的活动边、多条输出的活动边。分支节点的输出活动边是“并行”的,相当于把一条输入活动边的令牌数据分发到全部输出活动边。分支节点可用于并行流程的建模。在示例图中,开始节点下面是一个“分支节点”,分出来的两个控制流并行发生,说明验证命令、点火推进器的那个分支,和测量高度、计算轨道半径的那个分支是并行的。

“集合节点”(JoinNode):集合节点有多个输入活动边、仅仅一个输出活动边。只有所有输入活动边有令牌到达的时候,输出活动边才有令牌输出。这个和“合并节点”是不同的,合并节点输入边是“或”的关系,集合节点是“与”的关系。集合节点一般和分支节点联合使用,将分支节点分出去的多个并行流程汇聚到一个流程。

“初始节点”(InitialNode)、“活动终止”(FinalNode)、“流终止”(FlowFinalNode)节点:表示一个活动图的开始和结束节点,以及仅仅一个流的终止。

结构化活动节点(StructuredActivityNode)

结构化活动节点是表示一类复杂过程的节点。结构化活动节点中包含一系列动作节点,“循环节点”、“条件节点”类似编程语言里面的“循环语句”、“条件语句”。

“循环节点”中的“设置”(setupPart)中的动作相等于循环语句中初始化循环变量的作用,“测试”(test)中的动作起判断循环条件的作用,“循环体”(bodyPart)中动作在每次循环中执行。

“条件节点”中有多组“子句”(clause)。只有当一个子句的“测试”(test)中的动作返回“true”值时,子句的“主体”(body)中的动作才能执行。

“序列节点”中包含多个动作子节点,这些动作之间不必画出节点之间的控制流,每个动作将会按序列依次执行。

这三类结构化活动节点示例如下(此图使用“智睿思维基于模型的系统工程软件--MBSES”制作):

活动分区(ActivityPartition)

活动分区是具有相同特征的活动节点和活动边的一个分组。活动分区的边框用虚线表示。活动分区和结构化活动节点是完全不同的概念(虽然都是用虚线边框)。结构化活动节点本身是一个“动作”(Action),它可以有自己的输出、输出栓。但是活动分区只是一个分组或关系(如分配活动分区)。

活动分区可以代表一个模块(更通用的说可以是一个具有行为的类目,Classifier)、一个实例(InstanceSpecification)或一个属性(Property)。分区中的动作是这个模块、或者实例的类、属性的类的活动行为被调用的动作。也可以说是一个局部的活动图,这个局部的活动图的“语境”是大活动图语境(大活动图所属的模块)的部件。

不过活动分区具体代表什么元素,UML标准中并没有明确定义,也可以是其它元素。用户可以根据需要定义。在SysML标准中,定义专用的活动分区“分配活动分区”,可以为这个分区指定指定任意的元素(一般还是一个结构元素,如“部件”),表示分区中的活动元素分配到这个指定的元素。这一般应用到将代表功能的“动作”分配到结构元素“部件”。

多个活动分区水平或垂直并列的使用,用水平线或垂直线分隔,这种表示法通俗的称为“泳道”(swimlane),这样的图称为“泳道图”(可以给图增加构造型«泳道图»)。

“可中断活动分区”是一类特殊的活动分区,分区中增加了一个表示动作流程中断的“中断控制流”,这个控制流一般是某个事件引发(例如下面示例图中,用户关闭车钥匙,发送了一个“关闭钥匙”信号,引发“关闭钥匙”接收事件,然后触发中断,结束整个活动)。

如下图是一个“SUV提供动力”的活动图图(具有«泳道图»构造型)(来源于SysML1.6标准附录D图D.38,此图使用“智睿思维基于模型的系统工程软件--MBSES”制作),图中通过表示分配关系的分配活动分区“泳道”,将相应动作功能分配给SUV相应的部件。