提问人:Dirk Fraanje 提问时间:10/24/2023 更新时间:10/28/2023 访问量:79
当离开转换的两个保护条件都为假时,状态机将何去何从?
Where does a State machine go when both guard conditions on leaving transitions are false?
问:
我正在为下周一的 UML 考试练习,问题是下图的结果是什么,我认为该图无效,因为 x 的值第一次正好是 9。守卫是:大于 9 和 10 或更大。所以两个守卫都不是真的,因为守卫(+1)之后的效果是在评估守卫之后运行的。是我遗漏了什么,还是这确实不严谨:
我认为该图无效,因为两个防护装置都是错误的。
答:
编辑 - 最终(但很长)的答案
这个边缘案例中的关键问题
通常,操作会在离开状态之前清理情况。因此,在现实生活中,执行可能影响转换的清理操作并不常见。exit
假设 x 是任何其他并发状态机都无法访问的属性,我们可以按照图看到机器进入第一个状态,x 依次为 0、2、4、6,直到它以 x=8 进入具有两个传出转换的状态。
极端情况是该动作可能会对防护装置的状况产生影响。关键问题是,防护装置是在退出行为之前还是之后进行评估:exit
- 如果在退出状态之前评估了守卫,则 x 为 8,并且为 true,并且过渡点火。
[x<9]
- 如果在退出状态后评估守卫,则 x 为 9,并且两个守卫都是假的,这意味着该状态不会退出,因此 X 将停留在 8,游戏永远结束。
非权威答案
不幸的是,UML 规范在这方面并不是非常清楚。我本来希望有一个关于何时评估警卫的明确声明,但这些信息被稀释了几个段落,并受到不同的解释(参见与qwerty_so交换的评论)。
因此,我最终看了《UML用户指南》,这本书并不具有权威性,也不再与最新的UML规范保持一致,但它的优点是,在OMG将其变得非常抽象之前,UML的发明者写得非常清楚。
他们传达的信息很明确:当收到与转换匹配的 trigerring 事件时,将对过渡防护进行评估。这意味着在行为之前对其进行评估,符合qwerty_so公开的逻辑。exit
当没有指定触发事件时,问题仍然存在,尽管我们可以理解它与状态准备退出有关。
规格怎么说
UML 2.5.1 规范的寻呼机 315 我们读到:
过渡可能具有关联的保护约束。具有计算结果为 false 的防护的转换将被禁用。
但是,什么是启用的过渡?UML 规范在有关运行完成的部分中要求几个条件,特别是:
(...)至少存在一条从源状态配置到目标状态配置或 (...) 的完整路径,其中所有保护条件均为 true
从源到目标的完整路径需要离开状态。UML 2.5.1 规范的 P 311/312 对此进行了解释:
无论 State 如何退出,只有在 State 的退出行为(如果已定义)完成执行后,StateMachine 才会被视为“离开”了该状态。
因此,这意味着没有启用的路径,因为退出意味着 x 为 9,并且两个防护的计算结果都为 false。这是我最初回答的结论。但是与用户指南的矛盾让我睡不着觉。
读了又读,终于找到了另外两个相关的段落。第一个部分解释了在未指定触发事件时无保护的简单转换的情况(P.314):
一种特殊的过渡是完成过渡,它有一个隐式触发器。启用此触发器的事件称为完成事件,它表示与完成转换的源状态关联的所有行为都已完成执行。对于简单状态,当关联的条目和 doActivity 行为完成执行时,将生成完成事件。
上面这一段的关键是,在完成状态时没有提到。这允许我与 UML 用户指南建立链接:触发转换的事件是当 和 完成时,与 无关。exit
entry
do
exit
关于守卫的另一段提到了复合过渡。我最初认为“复合跃迁”指的是一种具有子状态机或复合状态的特殊情况,这与我们的情况无关:
在启用包含防护的复合转换之前,将对防护进行评估,除非它们位于源自选择伪态的转换上。在后一种情况下,当到达选择点时评估防护装置。
然而,“复合转换”似乎对应于机器在两个稳定配置之间的遍历。还解释了复合过渡的情况之一是完成过渡:
如果我们将两者放在一起,这意味着在退出行为之前评估防护。这很复杂,但很明确,并且覆盖了我之前基于“完整路径”的互操作。
结论
你的机器会用守卫 x<9 触发过渡,然后再做另一个循环,然后用 >=10 触发过渡,最后到达终点。
在这件事上,规格非常难以阅读。诚然,它们涵盖了广泛的案例,但已经有一个注释(表明它不够清楚)。本说明应予修改:
过渡防护装置
过渡可能具有关联的保护约束。具有计算结果为 false 的防护的转换将被禁用。在启用包含防护的复合转换之前,将对防护进行评估,除非它们位于源自选择伪态的转换上。在后一种情况下,当到达选择点时评估防护装置。没有关联防护的过渡将被视为具有始终为 true 的防护。
注意。完成转换也可能具有保护,在这种情况下,独立于退出行为评估保护。
评论
x
这是对克里斯托夫回答的修正(因为太长了,无法发表评论)。
事实上,UML 规范对保护/退出行为并不明确。但是,只有当状态可以退出时,才能执行退出行为。这意味着守卫已被证明是正确的(如果只有守卫出口)。因此,当双出口状态为 x==8 时,保护 x<9 将应用并且状态离开,从而递增 x 2 倍。当它下次以 x==16 进入时,防护 x>=10 适用。
评论
x=x+1
x=x+1