【问题标题】:Designing a state machine in C++用 C++ 设计状态机
【发布时间】:2010-04-24 16:15:02
【问题描述】:

我有一个涉及到状态机建模的小问题。

我已经设法进行了一些知识工程并“逆向工程”了一组确定状态和状态转换的原始确定性规则。

我想知道最佳做法是什么:

  • 如何严格测试我的状态和状态转换,以确保系统不会最终处于未确定状态。

  • 如何强制执行状态转换要求(例如,应该不可能直接从 stateFoo 转到 StateFooBar,即向每个状态灌输关于它可以转换到的状态的“知识”。

理想情况下,我希望尽可能使用干净、基于模式的设计,并使用模板。

不过,我确实需要从某个地方开始,我将不胜感激任何以我的方式发送的指示(不是双关语)。

【问题讨论】:

  • 搜索“正式状态机验证”

标签: c++ design-patterns state-machine state-pattern


【解决方案1】:

请务必查看Boost Statechart Library

【讨论】:

【解决方案2】:

天哪,它并不像看起来那么复杂。状态机代码非常简单简短。

将状态存储在一个变量中,比如 myState。

您的状态机将是一个 switch 语句,在 myState 变量的值上进行分支以执行每个状态的代码。

代码将充满这样的行:

myState = newState;

要强制执行状态转换要求,您需要添加一个名为的小方法,像这样

void DoSafeStateTransition( int newState )
{
// check myState -. newState is not forbidden
// lots of ways to do this
// perhaps nested switch statement

switch( myState ) {

 …

case X:  switch( newState ) 
    case A: case B:  case Z: HorribleError( newState );
    break;

 ...

}

// check that newState is not undetermined

switch( newState ) {

// all the determined states
case A: case B: case C … case Z: myState = newState; break;
default: HorribleError( newState );
}
}
void HorribleError( int newState )
{  printf("Attempt to go from %d to %d - disallowed\n",
       myState, newState );
   exit(1);
}

我建议这个简单而简短的检查会比单元测试做得更好 - 它肯定会快很多!

在我看来,单元测试的重点是测试代码比测试代码更简单,因此更容易检查其正确性,然后用于测试复杂的代码。检查状态机代码通常比检查状态机测试代码更容易。当您不知道单元测试是否正确时,报告 100% 单元测试通过并没有多大意义。

换句话说:编写状态机很容易,设计正确的状态机很难。单元测试只会告诉你设计是否正确,而不是设计是否正确。

【讨论】:

    【解决方案3】:

    测试与模式、模板等几乎没有关系。我建议使用像 CppUnit(xUnit 系列的一部分)这样的测试框架来捕获所有测试用例。当然,数量取决于状态机的复杂程度。

    您关于强制状态转换的问题涉及到您的状态机类设计的核心。我想说一个状态将有一组可以转换到的子状态,以及触发每个状态的事件。如果事件 Foo 没有 FooBar 子级,则无法转换到它。

    我会在 Google 上搜索“面向对象的有限状态机”来开始获得一些设计理念。

    当我考虑这样的问题时,我认为复合设计模式可能是其中的一部分,因为状态可能代表更复杂的 FSM。我会有一个 State 接口,使用 SimpleState 和 CompositeState 作为实现。我得重新开始,看看能不能解决。

    【讨论】:

      【解决方案4】:

      使用状态机是不时出现的。我通常按​​照 ravenspoint 的建议进行操作,然后简单地做一个 switch 语句。但是,这只有在州不太大的情况下才有效。这听起来像你的情况。考虑到这一点,我认为最好的办法是从一个好的架构开始,它允许你做一些你想做的事情。我接受了 duffymo 的建议并尝试了谷歌。这篇论文看起来很有趣 - Object-Oriented State Machines。这可能有点矫枉过正,但我​​认为它会提供一个易于使用 CppUnit 之类的东西进行测试的框架。

      来自 Google 搜索的其他一些很好的参考资料

      A Finite State Machine Framework

      Object-Oriented Finite State Machines

      【讨论】:

        【解决方案5】:

        听起来像是一个用于单元测试的原始应用程序。有许多单元测试框架。我碰巧喜欢Boost one

        【讨论】:

          【解决方案6】:

          如果您正在寻找经典的 GOF 设计模式状态机模式,请查看wikipedia

          查看此页面(在撰写本文时)的 Java 示例。

          它有一个StateContext 类,您可以从示例用法中看到,它的客户端知道writeName 方法。实现是:this.myState.writeName(this, name);,这意味着它将调用转发到当前状态,并将自身作为第一个参数传递。

          现在看看interface State,它有一个writeName 方法与上述用法相匹配。如果您同时查看StateAStateB,它们会回调上下文设置新状态。

          这就是大部分的状态模式。唯一需要意识到的是,StateContext 类可以保存其操作中涉及的所有数据,包括对当前状态的引用(它必须是 C++ 中的指针)。所有状态共同保存所有行为,但没有数据,而是在上下文中延迟数据(加上辅助方法)。

          当我开发状态机时(我通常使用 TDD),我不会费心测试状态转换,只是最终的行为是我想要的。

          【讨论】:

            【解决方案7】:

            如果你喜欢状态设计模式,我做了一个实验并将这个模式移到库中: https://code.google.com/p/dpsmlib/

            【讨论】:

              猜你喜欢
              • 2014-10-20
              • 2011-01-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-12-19
              相关资源
              最近更新 更多