2010-04-24 145 views
7

我有一个小问题,涉及建模一个状态机。在C++中设计状态机

我已经设法做了一点知识工程和'逆向工程'一组确定状态以及状态转换的原始确定性规则。

我想知道的最佳做法关于什么:

  • 如何严格测试我的状态和状态转换,以确保处于不确定的状态,系统无法结束。

  • 如何执行状态转变的要求(例如,它应该是不可能直接从stateFoo去StateFooBar,即灌输对美国的“知识”每个状态时,它可以转换到。

理想情况下,我想使用干净,基于图案的设计,尽可能使用模板。

我确实需要某个地方开始,但我会感谢任何指针(没有双关语意图),这是发送我的方式。

+0

搜索“国家正规机验证” – bobah 2013-11-28 20:39:15

回答

7

一定要看看Boost Statechart Library

+0

也看看MSM(HTTP:// WWW。 boost.org/doc/libs/1_55_0/libs/msm/doc/HTML/index.html),它们是非常不同的。 – bobah 2013-11-28 20:43:59

0

听起来像单元测试的原始应用程序。那里有很多单元测试框架。我碰巧喜欢Boost one

1

测试与模式,模板等无关。我建议使用像CppUnit这样的测试框架(xUnit系列的一部分)来捕获所有测试用例。当然,这个数字将取决于状态机的复杂性。

你关于执行状态转换的问题是你的状态机类设计的核心。我想说,一个州将会有一系列可以过渡到的州的州,以及将触发每个州的事件。如果事件Foo没有FooBar子项,那么无法转换到它。

我想谷歌“面向对象的有限状态机”开始获得一些设计思路。

当我想到这样的问题时,我认为复合设计模式可能是其中的一部分,因为一个国家可能代表更复杂的FSM。我有一个状态接口,SimpleState和CompositeState作为实现。我必须重新开始,看看它能否全部解决。

3

天哪,它没有看起来那么复杂。状态机代码非常简单和简短。

将状态存储在一个变量中,让我们说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%单元测试通过没有太多意义,当你不知道单元测试是否正确时。

换句话说:编码状态机很简单,设计正确的状态机很困难。单元测试只会告诉你,如果你正确地编码设计,而不是如果设计是正确的。

1

使用状态机是不时出现的。我通常按​​照建议的ravenspoint做,并且简单地做一个switch语句。但是,只有在州不太大的情况下才有效。这听起来像你的情况。考虑到这一点,我认为最好的做法是从一个好的架构开始,这将允许你想要做的一些事情。我采取了duffymo的建议并尝试Google。这篇论文看起来很有趣 - Object-Oriented State Machines。这可能是矫枉过正,但我​​认为它会给出一个很容易用CppUnit等测试的框架。

从谷歌搜索其他一些很好的参考

A Finite State Machine Framework

Object-Oriented Finite State Machines

0

如果你正在寻找的经典GOF设计模式状态机模式,然后再看看wikipedia

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

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

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

这就是那里的大部分州模式。唯一要认识到的是,StateContext类可以保存涉及其操作的所有数据,包括引用(它必须是C++中的指针)到当前状态。所有的州都集体持有所有的行为,但是没有数据,而是推迟了上下文中的数据(加上辅助方法)。当我开发一个状态机(我通常使用TDD)时,我不打扰测试状态转换,只是最终的行为是我想要的。