有限状态机:设计不好?
在 OOP 中,有限状态机通常被认为是糟糕的设计吗?
我经常听到这样的说法。而且,在我不得不使用它来开发一个非常古老的、未记录的 C++ 片段之后,我倾向于同意。调试起来很痛苦。
可读性/可维护性问题又如何?
Are Finite State Machines generally considered as bad design in OOP ?
I hear that a lot. And, after I had to work on a really old, undocumented piece of C++ making use of it, I tend to agree. It was a pain to debug.
what about readability/maintainability concerns?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
FSM 永远不应该被认为是不好的。它们太有用了,但不习惯它们的人常常会认为它们是负担。
使用 OOP 实现一种方法有很多种。有些比其他更丑。您的低级人员将使用 switch 语句、跳转表甚至“goto”。
如果您正在寻找一种更简洁的方法,我建议 Boost 的状态图库,它是专门为用 C++ 实现 UML 状态图而构建的。它利用现代模板技术,使内容更具可读性。它的性能也非常好。
FSMs should never be considered bad. They are far too useful, but people whom aren't accustomed to them will often consider them burdensome.
There are numerous ways to implement one with OOP. Some are uglier than others. Your low-level guys will use switch statements, jump tables or even "goto."
If you're looking for a cleaner way to do it, I'd recommend Boost's State Chart library, which is built just for implementing UML state diagrams in C++. It makes use of modern template techniques, to make things more readable. It also performs very well.
有限状态机是实现特定目标的工具。与任何工具一样,它们也可能被滥用。
它们不是最仁慈的工具,但它们擅长的工作几乎不可能通过其他方式实现(通常任何其他方法都注定会比机器糟糕数千倍)。
该作业在禁止经典等待状态的条件下运行。
我必须阅读触摸屏。为了读取位置,我必须通过 SPI 交换大约 15 个命令。我需要每秒 100 个读数。在每个命令之后,我必须等待大约 1 微秒,以便相应的忙碌标志消失,然后才能继续。还有许多其他操作必须通过同一界面实现,例如设置对比度、更改模式、打开或关闭背光、读取温度。如果我在每次等待时执行
while(BUSY_BIT);
,那么我很快就会耗尽所有 CPU。如果我执行sched_yield()
或usleep(1)
,我将永远无法获得我想要的读数数量。唯一的方法是有限状态机。但也有一些方法可以让有限状态机发挥良好作用。将机器隐藏在幕后,并为开发人员提供可使用的功能。
到目前为止,我的工作经验主要是基于 3 种不同有限状态机的 2 个系统。
如果按结构或顺序编写,代码将简单两倍、清晰三倍。除非它不起作用,或者性能很差。
Finite state machines are a tool to achieve certain end. As any tool, they can be abused too.
They are not the most gracious of tools, but the work they are good at is about impossible to achieve by other means (and usually any other approach is then doomed to be a horrible mess thousand times worse than the machine).
The job is operating in conditions where classic wait states are forbidden.
I have to read touchscreen. To read the position, I have to exchange about 15 commands over SPI. I need good 100 readouts a second. I have to wait about 1 microsecond after each command, for respective busy flag to vanish before I can continue. There is also a number of other operations that must be attainable over the same interface, like setting contrast, changing modes, turning backlight on or off, reading temperature. If I performed
while(BUSY_BIT);
for each wait, I would eat up all the CPU in matter of moments. If I didsched_yield()
orusleep(1)
, I would never attain the number of readouts I want. The only way is a finite state machine.But there are ways to make the finite state machine play nice too. Hide the machine behind the scenes and give the developers functions to work with.
My job experience so far was dominated by 2 systems based on 3 different finite state machines.
The code would be twice as simple and three times clearer if written structurally or sequentially. Except it would't work, or would work with abysmal performance.
无法告诉你他们说什么。
但是 OO 和 FSM 攻击的是不同的问题领域。在对象交互的领域中——这就需要面向对象的方法。在世界处于一种或另一种状态的领域中,这需要 FSM 设计。
实际上,您可以将这些设计与不同的抽象级别混合使用,这将比仅使用其中一种设计更清晰。
Couldn't tell you what They say.
But OO and FSM sorta attack different problem domains. In a domain where objects are interacting -- that calls for an object-oriented approach. In a domain where the world is in one state or another -- that calls for a FSM design.
Realistically, you can mix these designs with/at different levels of abstraction, which will come out cleaner than using only one or the other.
我想说,有限状态机比解决相同问题的其他方法(例如匹配常规语言的问题)更容易调试。 FSM 的优点都体现在名称中……您可能有一个具有 15 个状态的状态机,因此您可以在一张纸上绘制一个图表来显示所有转换。您可以使用该图来找出系统的有用属性,例如它接受哪些字符串以及它如何进入错误状态。对于更复杂的系统,绘制图表通常很困难或不可能。
即使那些说“goto 是邪恶的”的人也认为它们是实现状态机的正确方法。 (当然,有些人认为 goto 总是邪恶的......但你不能取悦所有人)。
I would say that finite state machines are much easier to debug than other ways of solving the same problems (problems such as matching regular languages). What's nice about FSMs is all in the name... you might have a state machine with 15 states, so you can draw a diagram on a piece of paper showing all the transitions. You can use the diagram to figure out useful properties of the system, such as which strings it accepts and how it gets into error states. With more complicated systems, diagramming is often difficult or impossible.
Even the people who say "gotos are evil" think they're the right way to implement state machines. (Of course, some people think gotos are always evil... but you can't please everybody).
如果代码的结构正确,FSM 就很容易理解和维护。我在之前的工作中实现了 FSM,这里是一个框架模板:
FSM
FSM's can be easy to understand and maintain if the code is structured the right way. I've implemented an FSM in prior jobs, here is a skeleton template:
FSM
我认为如果代码有很好的文档记录,那么使用 OOP 方法实现它是没有问题的。大多数 C/C++ 使用 switch 语句来实现 FSM,如果机器很大,有时会损害可读性。
最近需要解析一个正则语言,并使用OOP的方式实现了一个FSM,代码可读性和可维护性都很好。我的意思是,这比使用大型 switch 语句要好得多。
提示,首先,我已经实现了包含状态的 FSM 和包含转换的状态。然而,就我而言,事实证明,使用一个类来表示包含一个状态集合和另一个转换集合的 FSM 是一种更好的方法。它让我更容易克隆机器(这对我来说是一个要求)并且具有更小的转换函数。
我希望它有帮助,
卡洛斯.
I think if the code is well documented there is no problem to implement it using a OOP approach. Most of the C/C++ use to implemente FSM using switch statements which sometimes can compromise the readability if the machine is large.
Recently I needed to parse a Regular Language, and implemented an FSM using the OOP approach, the code readability and maintainability were good. I mean, much better than using large switch statements.
A tip, at a first moment, I've implemented the FSM containg states and the states containing the transitions. However, in my case it proved to be a better approach to have a class to represent the FSM containing one collection of states and another of transitions. It made easier to me to clone the machines (it was a requirement to me) and to have a smaller transition function.
I hope it helps,
Carlos.
状态机可用于表示任何类的行为。如果传入事件的顺序对于类行为(组合类)并不重要,则使用状态模型不会带来特殊的好处。
但是,如果类的行为取决于传入事件的顺序(顺序类),则状态机代表行为分析和实现的最佳选择。
如果您关心可读性/可维护性,请使用图形表示。属于不同工程领域的类的行为示例以图形和可执行形式呈现在 http://www.StateSoft.org< /a>->状态机画廊。
-贾努斯
State Machine can be used to represent behavior of any Class. If the order of incoming events does not matter to a Class behavior (combinatorial Class), use of State Model delivers no special benefit.
However if the behavior of a Class depends on the order of incoming events (sequential Class) State Machine represents the best choice for behavior analysis and implementation.
If readability/maintainability is your concern, use graphical representations. Examples of behavior of Classes belonging to different engineering domains are presented in a graphical and executable form at http://www.StateSoft.org -> State Machine Gallery.
-Janusz