2010-04-24 17 views
7

Ich habe ein kleines Problem, das die Modellierung einer Zustandsmaschine beinhaltet.Entwerfen einer Zustandsmaschine in C++

Ich habe es geschafft, ein bisschen Wissenstechnik zu machen und eine Reihe von primitiven deterministischen Regeln zurückzuentwickeln, die sowohl Zustands- als auch Zustandsübergänge bestimmen.

Ich möchte wissen, was die besten Praktiken in Bezug auf:

  • Wie rigoros Übergänge meine Zustände und Zustands testen, um sicherzustellen, dass das System nicht in einem unbestimmten Zustand kann am Ende.

  • Wie Zustandsübergangsanforderungen (zum Beispiel erzwingen, sollte es unmöglich sein, direkt von stateFoo zu StateFooBar gehen, dh jeden Staat mit ‚Wissen‘ um es zu übergehen kann über die Zustände zu durchtränken.

Idealerweise würde ich gerne ein sauberes, musterbasiertes Design mit Vorlagen verwenden, wo immer möglich

Ich brauche aber irgendwo etwas anzufangen und ich wäre dankbar für irgendwelche Hinweise (kein Wortspiel beabsichtigt), die mir geschickt werden.

+0

Suche nach „formale Zustandsmaschine Validierung“ – bobah

Antwort

7

Werfen Sie einen Blick auf die Boost Statechart Library.

+0

auch einen Blick auf MSM (http: // www. boost.org/doc/libs/1_55_0/libs/msm/doc/HTML/index.html), sie sind sehr unterschiedlich. – bobah

0

Klingt wie eine echte Anwendung für Komponententests. Es gibt viele Unit-Test-Frameworks da draußen. Ich mag die Boost one.

1

Testen hat wenig mit Mustern, Vorlagen usw. zu tun. Ich würde ein Test-Framework wie CppUnit (Teil der xUnit-Familie) empfehlen, um alle Ihre Testfälle zu erfassen. Die Anzahl hängt natürlich von der Komplexität der Zustandsmaschine ab.

Ihre Frage zum Erzwingen von Zustandsübergängen gehört zum Kern Ihres Klassendesigns für Ihre Zustandsmaschine. Ich würde sagen, dass ein Staat eine Sammlung von Kind-Zuständen haben wird, zu denen er wechseln könnte, zusammen mit dem Ereignis, das jeden auslösen wird. Wenn Ereignis Foo kein FooBar-Kind hat, gibt es keine Möglichkeit, zu diesem Kind zu wechseln.

Ich würde Google "objektorientierte endliche Zustandsmaschinen" beginnen, einige Designideen zu bekommen.

Als ich über solche Probleme nachdachte, dachte ich, dass das Composite Design Pattern ein Teil davon sein könnte, weil ein State eine komplexere FSM darstellen könnte. Ich hätte eine State-Schnittstelle mit SimpleState und CompositeState als Implementierungen. Ich musste wieder anfangen und schauen, ob alles klappte.

3

Gott, es ist nicht so kompliziert wie es scheint. Der Status des Maschinencodes ist sehr einfach und kurz.

Speichern Sie den Status in einer Variablen, sagen wir myState.

Sie State Machine wird eine switch-Anweisung sein, Verzweigung auf den Wert der Variable MyState, um den Code für jeden Zustand auszuüben.

wird der Code wie folgt voller Linien:

myState = newState; 

Zustandsübergangs Anforderungen zu erzwingen, müssen Sie stattdessen, wie diese schlage ich vor, dass diese

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); 
} 

genannt ein wenig Methode hinzufügen Einfach und kurz genug, dass die Inspektion einen besseren Job macht als der Unit-Test - es wird sicherlich viel schneller sein!

Der Punkt der Unit-Tests ist, dass der Test-Code einfacher als der getestete Code ist, so dass es einfacher auf Korrektheit überprüft werden kann, dann verwendet, um den komplizierten Code zu testen. Es ist oft einfacher, den Zustandsmaschinencode als den Zustandsmaschinentestcode zu überprüfen. Es macht wenig Sinn einen 100% Unit Test Pass zu melden, wenn Sie keine Ahnung haben ob die Unit Tests korrekt sind.

Anders ausgedrückt: Die Codierung einer Zustandsmaschine ist einfach, das Entwerfen der richtigen Maschine ist schwierig. Komponententests sagen Ihnen nur, ob Sie das Design korrekt codiert haben, nicht ob das Design korrekt war.

1

Verwenden von Zustandsautomaten ist etwas, das von Zeit zu Zeit kommt. Normalerweise mache ich das wie Ravenspoint vorgeschlagen und mache einfach eine switch-Anweisung. Das funktioniert aber nur, wenn die Zustände nicht zu groß sind. Das hört sich nach deinem Fall an. Wenn ich das in Betracht ziehe, denke ich, dass es am besten ist, mit einer guten Architektur zu beginnen, die einige der Dinge ermöglicht, die Sie tun möchten. Ich nahm Duffymos Vorschlag an und probierte Google aus. Dieses Papier sah interessant aus - Object-Oriented State Machines. Es könnte zu viel werden, aber ich denke, es wird einen Rahmen geben, der mit etwas wie CppUnit leicht zu testen wäre.

Einige andere gute Referenzen aus der Google-Suche

A Finite State Machine Framework

Object-Oriented Finite State Machines

0

Wenn Sie die klassische GOF Design Patterns State Machine Muster suchen, dann auf wikipedia suchen.

Schauen Sie sich diese Seite (zum Zeitpunkt des Schreibens) im Java-Beispiel an.

Es hat eine StateContext Klasse, die Sie aus dem Beispiel Verwendung sehen können, hat Kunden, die über die writeName Methode wissen. Die Implementierung ist: this.myState.writeName(this, name); was bedeutet, dass es den Aufruf an den aktuellen Status weiterleitet und sich selbst als erstes Argument übergibt.

Betrachten Sie jetzt interface State, es hat eine writeName Methode, die die obige Verwendung entspricht. Wenn Sie sowohl StateA als auch StateB betrachten, rufen sie den Kontext auf, der einen neuen Status festlegt.

Das ist die meisten der State Pattern genau dort. Das einzige, was zu erkennen ist, ist, dass die Klasse StateContext alle Daten enthalten kann, die an ihrer Operation beteiligt sind, einschließlich einer Referenz (es muss ein Zeiger in C++ sein) auf den aktuellen Zustand. Alle Staaten zusammen halten alle das Verhalten, aber keine Daten, anstatt die Daten (plus Hilfsmethoden) im Kontext zu verschieben.

Wenn ich eine Zustandsmaschine entwickle (ich verwende normalerweise TDD), tue ich keine Mühe, Zustandsübergänge zu testen, nur dass das endgültige Verhalten so ist, wie ich es möchte.

Verwandte Themen