有限状态机:糟糕的设计?

时间:2010-02-02 00:36:18

标签: c++ language-agnostic state-machine

有限状态机通常被认为是OOP中的糟糕设计吗?

我听到了很多。并且,在我不得不使用一个非常古老的,没有文档的C ++片段之后,我倾向于同意。调试很痛苦。

可读性/可维护性问题呢?

7 个答案:

答案 0 :(得分:18)

FSM应该永远不会被视为坏事。它们太有用了,但是那些不习惯它们的人会经常认为它们很麻烦。

使用OOP实现一个方法有很多种。有些比其他人更丑。你的低级别人员会使用switch语句,跳转表甚至“转到”。

如果您正在寻找更简洁的方法,我建议Boost's State Chart library,它是为在C ++中实现UML状态图而构建的。它利用现代模板技术,使事物更具可读性。它也表现得很好。

答案 1 :(得分:6)

有限状态机是实现某种目的的工具。作为任何工具,它们也可能被滥用。

他们并不是最优雅的工具,但他们擅长的工作是通过其他手段无法实现的(而且通常任何其他方法都注定要比机器差几千倍。)< / p>

该作业在禁止经典等待状态的条件下运行。

我必须阅读触摸屏。为了读取位置,我必须通过SPI交换大约15个命令。我需要一秒钟好100次读数。我必须在每个命令后等待大约1微秒,因为各个忙碌的旗帜在我继续之前消失。还需要在同一界面上实现许多其他操作,例如设置对比度,更改模式,打开或关闭背光,读取温度。如果我为每次等待执行while(BUSY_BIT);,我会在瞬间消耗所有CPU。如果我做sched_yield()usleep(1),我将永远无法达到我想要的读数。唯一的方法是有限状态机。

但是有一些方法可以让有限状态机也很好玩。在幕后隐藏机器并为开发人员提供使用的功能。

到目前为止,我的工作经验主要是基于3种不同的有限状态机的2个系统。

  1. 一个大型门户网站,您可以在每个步骤中从数据库中检索一些数据,并在此基础上准备更多查询。在最后一步中,您将使用数据生成HTML。每个任务 - 一个网页模块 - 都是作为从引擎继承的PHP类实现的。状态保存在类变量中。每个步骤都是一个单独的功能。在步骤结束时,存储的查询被优化并通过缓存发送到引擎,并将答案提供回原始查询。
  2. 具有许多子系统的嵌入式设备。使用任务泵。每个模块都注册一个从主循环中每秒调用多次的处理程序。处理程序可以使用状态保留静态或类变量中的状态。这种协作式多任务处理允许比在单独的线程中运行所有内存更小的内存占用,允许通过将任务注册两次来手动确定任务的优先级,并使线程以高优先级运行,从而使系统的其余部分蒙上阴影。
  3. 半解释器。那个触摸屏。函数调用及其等待状态已注册,但每次只调用一次,然后从程序队列中删除。解释器被称为taskpump的任务,执行有限数量的函数,直到遇到标记为等待状态的函数(或超过要调用的函数的数量)。然后它继续,直到等待状态消失。其他任务将作业排队为(有时很长)要执行的函数序列,然后等待结果。通过这种方式,我可以将需要创建的状态数限制为大约4,我需要结果。如果命令是“发送,永不检查结果”,如“设置对比度”,则它们根本不需要离散状态。因此,实际状态是“等待事件并注册请求的数据”,“等待测量”和“读取结果并正确分配”。
  4. 如果结构或顺序编写,代码将简单两倍,清晰三倍。除非它不起作用,否则会有糟糕的表现。

答案 2 :(得分:5)

无法告诉你他们说的是什么。

但OO和FSM sorta攻击不同的问题域。在对象正在交互的域中 - 这需要面向对象的方法。在世界处于某种状态的领域 - 需要FSM设计。

实际上,你可以将这些设计与不同的抽象层次相混合,这比仅使用其中一个更清晰。

答案 3 :(得分:2)

我想说有限状态机比解决相同问题的其他方法(匹配常规语言等问题)更容易调试。 FSM的优点在于名称......您可能拥有15个状态的状态机,因此您可以在显示所有转换的纸上绘制图表。您可以使用该图来确定系统的有用属性,例如它接受的字符串以及它如何进入错误状态。对于更复杂的系统,图表通常很难或不可能。

即使是那些说“搞砸了”的人也认为他们是实施国家机器的正确方法。 (当然,有些人认为里克斯总是邪恶的......但你不能讨好所有人。)

答案 4 :(得分:1)

我认为如果代码记录良好,使用OOP方法实现它是没有问题的。大多数C / C ++使用switch语句实现FSM,如果机器很大,有时会损害可读性。

最近我需要解析一个常规语言,并使用OOP方法实现了一个FSM,代码可读性和可维护性都很好。我的意思是,比使用大型switch语句要好得多。

提示,在第一时刻,我已经实现了FSM包含状态和包含转换的状态。然而,在我的情况下,它被证明是一个更好的方法来让一个类来表示包含一个状态集合和另一个转换的FSM。我更容易克隆机器(这是我的要求)并且具有较小的过渡功能。

我希望它有所帮助, 卡洛斯。

答案 5 :(得分:1)

如果代码以正确的方式构建,则FSM易于理解和维护。我在以前的工作中实现了FSM,这是一个骨架模板:

FSM

答案 6 :(得分:0)

State Machine可用于表示任何Class的行为。如果传入事件的顺序与类行为(组合类)无关,则使用状态模型不会带来任何特殊好处。

但是,如果类的行为取决于传入事件的顺序(顺序类),则状态机代表行为分析和实现的最佳选择。

如果您关心可读性/可维护性,请使用图形表示。属于不同工程域的类的行为的示例以图形和可执行的形式呈现在http://www.StateSoft.org - &gt;国家机器馆。

-Janusz