UML 状态图中的转换:使用触发器或守卫更好?

Transitions in UML state charts: better to use triggers or guards?

在 UML 状态图的设计中,我似乎可以选择使用 triggersguard 逻辑来实现状态之间的转换.

那么哪个更好用呢?给定相同的转换逻辑,触发器的行为是否与守卫有任何不同?一个比另一个的 benefits/drawbacks 是多少?

是否可能因特定工具而异,或者 UML 标准是否严格定义了两种转换方法的行为?

我目前正在使用 Simulink Stateflow 设计状态机。

这两个是不同的概念。

Trigger 是一个 event 事件,它会启用转换, 而 guard 是一个 condition,必须评估为 true 才能继续进行转换。

所以你不能互换使用它们——它们有不同的作用。

另请注意,默认守卫(如果指定了 none)是 [true],因此触发器通常足以从一种状态移动到另一种状态。

更新:

总结:

  • 触发器(事件)是对象接收到的一些新数据(任何数据类型)。
  • Guard 是对象中已经存在的某些数据的布尔表达式。

触发器(事件)是其他一些参与者触发的外部事件 - 用户按下按钮,浏览器请求页面加载等。所以在上图中,每次用户按下数字锁上的数字时触发 "pressed digit" 事件。

如果引脚(数字序列)有效,则将启用到 unlocked 状态的转换。

另一种看待它的方式:

如果您按下键盘键,系统会触发一个 keypress event,这将是一个触发器,其值为按下的键。然后你可以做一个守卫[pressedKey = enter](守卫总是一个布尔表达式)。

但是这里只有守卫是不够的,因为没有什么可比较的。

严格来说,没有触发器就不能使用守卫。

UML 2.5.1 specification (Section 14.2.4.8, page 331) defines State Machine's transitions by the following BNF expression:

[<trigger> [‘,’ <trigger>]* [‘[‘ <guard>’]’] [‘/’ <behavior-expression>]]

虽然 UML 2.0 将它们定义为:

<transition> ::= <trigger> [‘,’ <trigger>]* [‘[‘ <guard-constraint>’]’] [‘/’ <activity-expression>]

触发器定义为:

<trigger> ::= <call-event> | <signal-event> | <any-receive-event> | <time-event> | <change-event>

因此,在这两种情况下,没有任何触发器的守卫都无法进行转换。

根据 UML 2.5.1,唯一的例外是 内部转换,它们由以下内容指定:

{<trigger>}* ['[' <guard>']'] [/<behavior-expression>]