如何在UML中表示通信协议?

4
在我的UML模型中,我有一个系统和它的子组件彼此交流。例如,我有一台计算机和一辆RC机器人,它们通过蓝牙通信。目前,在图表中的流程大致如下:
“计算机”触发“RC汽车”的“setVelocity()”函数。
此时,我想通过以下方式细化通信:
计算机发送“Movement”消息 速度字段设置为100,方向字段设置为0 RC汽车通过发送ACK消息确认 带有消息ID“Movement”和序列号X。
我该怎么做?
编辑:澄清
通常情况下,这就是我的图表,没有协议细节:

Current Model

但是当我尝试添加消息时,至少存在两个问题:

  • 似乎计算机首先按顺序触发了setVelocity()函数,然后是sendBluetoothMessage(),这些并不是顺序的。 setVelocity()后面的内容实际上是在该函数内部发生的。
  • sendBluetoothMessage()实际上是计算机的一个函数。但是在这里它属于RC汽车。(或者我错了?)ACK也是同样的情况。

What I tried

感谢回复。你很棒!

如果您在问题中包含一张图表,那将会非常有帮助。至少向我们展示您所讨论的现有图表的相关部分(我们甚至不知道这是什么类型的图表)。更好的做法是尝试创建一个回答您自己问题的图表并发布它,这样我们就可以指出其中存在的问题。 - www.admiraalit.nl
1
@www.admiraalit.nl 我在手机上写了这个问题,很抱歉没有提供足够的细节,但现在我已经添加了图表。 - bomberman
3个回答

1

通信协议概述

在两个设备之间表示发送运动消息的主要方法有两种:

  1. 在目标设备上执行 movement() 操作,其中包含速度和方向参数。您通常会在序列图中显示交换,其显示为从发送方到接收方的调用箭头。返回消息可以简单地标记为 ACK。

  2. «signal» Movement信号 对应于事件消息。在类图中,它们像类一样表示,但使用 «signal» 关键字:velocitydirection 将是该信号的属性。 ACK 将是另一个信号。能够接收信号的类将其显示为 接收(看起来像操作,但再次使用了 «signal» 关键字)。

在这两种情况下,您都需要展示您的通信协议与几乎相同的序列图进行交互。但是,信号用于异步通信,更好地反映了通信的本质。它的语义更适合您的需求。
如果您更喜欢通信图而不是交互图,则信号方法会更清晰,因为通信图不显示返回消息。
为什么信号是您需要的(您的编辑)
通过这些图表,您编辑后的问题变得更加清晰。我对使用信号的立场没有改变:信号将对应于计算机和汽车之间交换的信息。因此,在类图中,您可以将“Movement”标记为具有属性“id”,“velocity”和“direction”的信号。

Class diagrams showing a hierarchy of signals

在你的顺序图中,你将发送一个带有Movement (X,100,0)的箭头。信号允许展示协议交换的高层视图,而不会迷失于实际实现细节中。

enter image description here

实现细节可以在单独的图表中显示。计算机一侧涉及几个类(一个图表,最终动作是某种发送),汽车一侧也涉及几个类(另一个图表:如何接收和调度消息,并解码其内容)。我没有提供示例,因为它看起来非常像您当前的图表,但发送功能可能由通信控制器实现。
如果您尝试将协议及其实现放在同一图表中,就像第二个图表中那样,由于关注点缺乏分离,会变得混乱:您在这里说计算机正在调用汽车上的发送函数,这完全不是您想要的。然后,读者难以看出协议所需的真正内容以及实现细节。例如,根据您的图表,我仍然不知道setVelocity是否应直接向汽车发送某些内容,还是它是使用速度发送移动消息的准备步骤。
最后但并非最不重要的是,请记住,序列图仅表示特定场景。如果您想在UML中正式定义协议,则还需要创建协议状态机,以告知有效的消息连续性。使用信号时,您可以直接使用其名称作为状态转换触发器/事件。

@qwerty_so 是的,那是一个相关的评论,但这不会只是转移问题吗?OP问如何描述协议(“我想通过说...来改进通信”)。告诉他类实现了协议并不能让我们更接近协议的建模,对吧? - Christophe
@Christophe,我认为第一种选项仍然缺乏协议的细节。对于第二个选项,在互联网上我找不到太多资料,但在这里[链接]https://www.ibm.com/docs/en/rational-soft-arch/9.7.0?topic=diagrams-signals中,它说他们在默认情况下定义了一个发送函数。所以我应该从计算机画一个箭头到<<signal>> Movement,等等? - bomberman
@qwerty_so,您是在说“已知遥控车和计算机可以实现静态模型中定义的协议,开发人员应该推断出应该使用运动消息”,对吗? - bomberman
1
@ozercik 个人认为这个链接并不是很清晰,我对默认发送也有一些疑问。这似乎不是一个很受欢迎的话题,至少在互联网上不是。到目前为止,我找到的最好的解释是在《UML用户指南第二版》中。它是由UML的发明者Booch、Jacobson和Rumbaugh编写的,所以我认为他们最了解它真正的意义;-) 他们用简单的英语定义为“消息是由一个对象异步发送然后被另一个对象接收的命名对象。信号是消息的分类器;它是一种消息类型”。... - Christophe
他们应该从需求中推断出来。协议只是一个“选项”,但在某些情况下可能被设置为强制性的。无论如何,静态声明是在连接SD之前的一些设计。 - qwerty_so
显示剩余2条评论

0
如果您真的想在序列图中显示这种详细级别,它会像这样:

enter image description here

注意事项:

  1. 对于异步调用,请使用开放式箭头。
  2. 使用堆叠条形图来表示调用堆栈。
  3. 在操作的参数列表中,写入“argumentName=argumentValue”或仅写入“argumentValue”。
  4. 对于那些确切的操作名称未知或不相关的消息,我只使用没有参数列表的描述。

但是要小心选择要显示的详细级别。如果您显示调用堆栈中的每个操作,则序列图往往会变得过于复杂。


-1

我遇到了同样的问题。我在网上搜索,但找不到我喜欢的东西。因此,我想出了这个解决方案。 我在顺序图中展示了通信端口,并在端口线之间绘制了通信相关步骤。 以下是您问题的截图:我的版本。

注意:我以前没有使用过蓝牙,所以我不确定确认步骤是否属于这个过程。如果这是硬件自动完成的操作(例如在CAN总线中),我就不会像这样绘制它。我可能不会显示它,或者我不会添加函数acknowledge(); ,只需在蓝牙端口的生命线之间画线。

enter image description here


你的图表很有趣,但是存在一些问题形式上的错误。你能从UML语法的角度进行更正吗?我想借此机会表达我的观点:在协议层面上,通信中有趣的部分是发生在你的“蓝牙”生命线之间的内容。在我的建议中,图表将仅限于这部分,重点放在设备之间的消息上。计算机或汽车端发生的事情是设备内部的内容,并且将在不同的图表中显示,以避免所需协议和实现细节之间的混淆。 - Christophe
1
我不确定setVelocity是否指向计算机,但喜欢通过蓝牙端口和这些端口之间的交互来实现。 - bomberman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接