有限状态机通常被认为是 OOP 中的糟糕设计吗?
我经常听到。而且,在我不得不使用它来处理一个非常古老的、未记录的 C++ 片段之后,我倾向于同意。调试很痛苦。
可读性/可维护性问题呢?
有限状态机通常被认为是 OOP 中的糟糕设计吗?
我经常听到。而且,在我不得不使用它来处理一个非常古老的、未记录的 C++ 片段之后,我倾向于同意。调试很痛苦。
可读性/可维护性问题呢?
FSM永远不应该被认为是坏的。它们太有用了,但不习惯它们的人通常会认为它们很累赘。
有很多方法可以用 OOP 来实现。有些比其他的更丑。您的低级人员将使用 switch 语句、跳转表甚至“goto”。
如果您正在寻找一种更简洁的方法,我建议您使用Boost 的状态图库,它专为在 C++ 中实现 UML 状态图而构建。它利用现代模板技术,使内容更具可读性。它的表现也非常好。
有限状态机是实现某种目的的工具。作为任何工具,它们也可能被滥用。
它们不是最优雅的工具,但它们擅长的工作几乎不可能通过其他方式实现(通常任何其他方法都注定会比机器糟糕一千倍)。
该作业在禁止经典等待状态的条件下运行。
我必须阅读触摸屏。要读取位置,我必须通过 SPI 交换大约 15 个命令。我需要每秒 100 个读数。我必须在每个命令之后等待大约 1 微秒,以便相应的忙标志消失,然后我才能继续。还有许多其他操作必须在同一界面上实现,例如设置对比度、更改模式、打开或关闭背光、读取温度。如果我while(BUSY_BIT);
每次等待都执行,我会在短时间内耗尽所有 CPU。如果我这样做sched_yield()
或usleep(1)
,我将永远无法达到我想要的读数数量。唯一的方法是有限状态机。
但是也有一些方法可以让有限状态机发挥得更好。将机器隐藏在幕后,并为开发人员提供可以使用的功能。
到目前为止,我的工作经验主要是基于 3 个不同的有限状态机的 2 个系统。
如果按结构或顺序编写,代码将简单两倍,清晰三倍。除非它不起作用,或者会以糟糕的性能工作。
不能告诉你他们说什么。
但是 OO 和 FSM 可以攻击不同的问题域。在对象交互的领域中——这需要面向对象的方法。在世界处于一种或另一种状态的领域中——这需要 FSM 设计。
实际上,您可以将这些设计与/在不同的抽象级别混合,这将比仅使用其中一种更清晰。
我想说有限状态机比解决相同问题的其他方法(例如匹配常规语言的问题)更容易调试。FSM 的优点就在名称中……您可能有一个具有 15 个状态的状态机,因此您可以在一张纸上绘制一个图表来显示所有转换。您可以使用该图来确定系统的有用属性,例如它接受哪些字符串以及它如何进入错误状态。对于更复杂的系统,绘制图表通常很困难或不可能。
甚至那些说“goto 是邪恶的”的人也认为他们是实现状态机的正确方法。(当然,有些人认为 gotos 总是邪恶的......但你不能取悦所有人)。
如果代码结构正确,FSM 就很容易理解和维护。我在之前的工作中实现了 FSM,这是一个骨架模板:
我认为如果代码有据可查,那么使用 OOP 方法实现它是没有问题的。大多数 C/C++ 使用 switch 语句来实现 FSM,如果机器很大,这有时会损害可读性。
最近需要解析一个Regular Language,用OOP的方式实现了一个FSM,代码可读性和可维护性都不错。我的意思是,比使用大型 switch 语句要好得多。
提示,首先,我已经实现了 FSM 包含状态和包含转换的状态。然而,在我的例子中,它被证明是一种更好的方法,让一个类来表示包含一个状态集合和另一个转换的 FSM。我更容易克隆机器(这是我的要求)并具有更小的转换功能。
我希望它有所帮助,卡洛斯。
状态机可用于表示任何类的行为。如果传入事件的顺序与类行为(组合类)无关,则使用状态模型不会带来任何特殊好处。
但是,如果一个类的行为取决于传入事件的顺序(顺序类),则状态机代表了行为分析和实现的最佳选择。
如果您关心可读性/可维护性,请使用图形表示。属于不同工程领域的类的行为示例在http://www.StateSoft.org -> State Machine Gallery 以图形和可执行的形式呈现。
-雅努斯