我在上一部分讨论的所有特性都是结构特性。然而,在大多数建模项目中,仅指定模块的组成部分、引用、约束、值属性和端口是不够的。它们确实很重要,但只传递了设计一个方面的信息。同样重要的方面是模块能够执行的一系列 行为 。通过为模块添加行为特性,你可以传递设计的这方面信息。
SysML提供了两种类型的行为特性:操作(operation)和接收(reception)。我之前在3.4.1节讨论接口的时候对其进行了简要的说明。然而,它们不仅限于接口使用。你还可以为模块添加操作和接收。决定直接把行为特性添加在模块上还是添加到(模块提供或者需要的)接口上取决于你选择的建模方法以及设计原则。SysML不会指定任何一种,而且在两种情况下显示操作和接受信息的格式也是一样的。
现在让我们详细看一下这两种行为特性。
操作 代表客户端调用模块的时候它所执行的行为。正式的说法是,操作是由 调用事件 触发的。
注意 当在第6章、第7章和第8章中的行为部分详细讨论事件的时候,调用事件这个术语的意义会更丰富。我现在介绍这个术语,是为了确立它与操作这个概念之间的联系。在你逐渐学习SysML的过程中,要记住图只是底层模型的视图;你在BDD上看到的会与你在其他类型图——包括活动图、序列图和状态机图——上看到的内容相关。
最常见的情况下,操作代表的是一种 同步 行为。这意味着调用者会一直等待行为结束,然后再继续自身的执行。然而,SysML不需要这样;你可以把任何行为表示为操作——即便调用者没有等待它完成。
你会在BDD中把操作表示为模块操作分隔框中的字符串(如图3.14所示)。那个字符串的格式会是下面这样:
操作名称是由建模者定义的。参数列表是由逗号分隔,拥有零个或多个参数的列表。(每种参数的格式都会简短显示。)返回值(如果有)必须是你在系统模型中某处创建的值类型或者模块的名称。多重性会约束操作完成时能够给调用方返回类型的实例的数量。
参数列表中的参数代表操作的输入和输出。列表中的每个参数都会以下面的格式显示:
方向可以是in、out或inout。参数名称是由建模者定义的。类型必须是在你的模型某处存在的值类型或者模块的名称。多重性会约束参数能够代表的类型实例的数量。当操作被调用时,如果没有指定一个值作为参数,则赋予参数默认值。
图3.14显示电子电力子系统模块和通信及数据处理子系统模块都拥有多种操作——它们代表的是,如果在系统操作中被调用,这些模块的实例能够执行的行为。操作的一个例子是processCommand。这个模型表示客户端可以调用通信和数据处理子系统来执行这种操作。当调用的时候,客户端可以传递给操作一个或多个命令作为输入,当操作完成时,它会给调用方返回状态值。
图3.14 带有操作的模块
给你一些建议:使用动词短语(像processCommand)为操作命名是很好的;毕竟操作代表的是行为。另外,不要让参数列表过多;只是向模块添加操作(不指定参数)通常就足够保证模型的准确性了。如果你的团队需要在系统模型中为操作指定参数,那么一定要准确判断选择哪些显示在特定的BDD上;就算只是显示了几个参数,操作的完整字符串也会在BDD上占用大量空间。
接收 代表一种行为,当客户端发送信号来触发的时候,模块就会执行这种行为。正式的说法是,接收是由 信号事件 触发的。
接收和操作之间的关键区别在于,接收总是代表一种异步的行为。这意味着客户端发送信号——会触发接收操作来接收它——然后立刻继续自身的执行,它不会等待接收完成(甚至都不会等待它开始)。
另一个关键点是, 信号 本身也是一种模型元素。你可以使用信号来代表任意类型的事件、能量和数据,它们都是系统的一部分传递给另一部分的——一般的目的是要触发接收端的行为。和模块一样,信号可以有属性。大多数情况下,那些属性代表信号从客户端到目的地所传递的数据。当信号到达目的地并触发接收动作的时候,信号的属性就会成为接收动作的输入。
图3.15显示了名为AnalogTempDataSampled的信号。这个信号有两种属性:temp(类型是摄氏度)和time(类型是TimeStamp)。当客户端在系统操作过程中生成这个信号的实例时,就可以为这两个属性提供值。客户端可以把信号实例发送给接受它的目的地(例如,图3.16中所显示的通信和数据处理子系统模块)。
图3.15 信号
图3.16 带有接收的模块
如果信号的目的地拥有和信号名称相同的接收,那么这种结构就是无效的。此外,接收必须拥有和信号的每个属性类型兼容的参数。通信和数据处理子系统模块符合这些标准。当操作系统中这个模块的一个实例接收了AnalogTempDataSampled信号的实例,那么就会触发接收行为,信号的两个属性中持有的值就会成为那种行为的输入。
当你在模块的接收分隔框中显示接收的时候,会显示下面这种格式的字符串:
关键字<<signal>>必须总是作为接收名称的前缀。正如之前提到的,接收名称必须与模型中触发它的信号名称匹配。只要有必要,你在参数列表中可以显示任意多个参数。列表中的每个参数都会以下面的这样格式显示:
参数名称是由建模者定义的。类型必须是在你的模型某处存在的值类型或者模块的名称。多重性会约束参数可以代表的类型实例的数量。如果在信号相关属性中没有提供任何值,那么默认值就是赋予参数的值。
和操作不同,接收无法拥有返回值。接收是异步的;发送信号的客户端不会等待回复。因为同样的原因,接收的参数只能是输入而不可能是输出。