2010-04-24 146 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)時,我不打擾測試狀態轉換,只是最終的行爲是我想要的。