- I am a programmer.
- -- Kenneth Thompson
Seit längerem habe ich vor, kniffelige Sachverhalte in meinen Qt Programmen statt in Variablen und komplizierten Abfragen lieber in sogenannten Finite State Machines (in Deutsch auch
Endlicher Automat genannt) abzubilden. Diese Woche habe ich mich dazu aufgerafft, diese Vorbaben bei einer von mir programmierte Abfrage der FreeDB Datenbank via des
CDDB-Protokolls umzusetzen.
Irgendwie gab es immer einen Fall, in dem die Abfrage, die außerdem noch eine Schnittstelle zum Auslesen der CD-Daten via CD-Text verwendet, nicht so funktioniert hatte, wie ich es meinte. Habe ich mal schnell eben das eine Problem gelöst, habe ich meistens damit ein bis zwei andere Probleme geschaffen. Unterm Strich blieb immer mindestens ein Problem über. Also habe ich mir Gedanken gemacht, wie die Beschreibung der Funktion in einem Zustandsautomaten aussehen sollte. Nachdem ich dies graphisch beschrieben habe, habe ich es dann "von Hand" runter programmiert. Dabei sind mir noch Unzulänglichkeiten aufgefallen, die ich aber überraschend einfach in den Griff bekommen habe, durch das Hinzufügen eines neuen Zustandes und ein paar übersehener Übergänge. Das vorläufige Endergebnis habe ich hier noch einmal aufgezeichnet.
Wenn ich mir das Bild noch einmal anschaue, verstehe ich auch, warum viele Beispiele von State Machines Ampeln nachbilden: die Dinge neigen dazu, schnell an Komplexität zuzunehmen.
Seit der Version 4.6 gehört ein
State Machine Framework bei Qt zum Standard, welches ich dafür verwendet habe. Leider wird ein großer Vorteil von State Machines nicht umgesetzt: sie lassen sich graphisch beschreiben und entwickeln. So schafft man es auf eine recht einfache Art, komplexe Sachverhalte deutlich besser "im Griff" zu behalten, als mit nicht-graphischen Methoden. Idealerweise hat man ein "Malprogramm" für State Machines, welches einem auf Knopfdruck auch den Code für die gewünschte Programmiersprache zu erzeugen. So etwas gibt es, zum Beispiel bei meinem ehemaligen Arbeitgeber, dort war es Bestandteil des verwendeten Frameworks. Leider gibt es so etwas nicht bei Qt, was meiner Meinung nach unter anderem daran liegt, dass die State Machines stark mit dem "Rest" von Qt verwoben sind, und man so einen Teil der extrem starken Verzahnung mit anderen Teilen von Qt verlieren würde. Außerdem ist es ein immenser Aufwand, einen Finite State Machine Editor zu programmieren.
Bei dem jetzigen Versuchsballon habe ich festgestellt, dass ich einen solchen Editor nicht zwingend benötige, und es einigermaßen schaffe, den Automaten mit Codezeilen noch recht übersichtlich zu beschreiben. Allerdings bin ich damit dann doch nicht wunschlos glücklich. Zur Fehlersuche wäre es extrem nützlich, wenn ich mir ein Diagramm wie das oben aus dem Code maschinell erzeugen könnte.
Formal lässt sich der oben abgebildete Graph wie folgt beschreiben:
Zustände:
Ejected, Cleared, Query, Read, CDText, Done
Übergänge:
Ejected --[cdinsert]--> Cleared
Cleared --[automatic]--> Query
Cleared --[eject]--> Ejected
Cleared --[found]--> Done
Query --[cdinsert]--> Cleared
Query --[found]--> Done
Query --[automatic]--> Read
Query --[eject]--> Ejected
Read --[cdinsert]--> Cleared
Read --[gotdata]--> Done
Read --[eject]--> Ejected
CDText --[cdinsert]--> Cleared
CDText --[gotdata]--> Done
CDText --[eject]--> Ejected
Done --[cdinsert]--> Cleared
Done --[query]--> Query
Done --[cdtext]--> CDText
Done --[select]--> Read
Done --[eject]--> Ejected
Was ich also suche ist ein Programm, dass eben genau dieses leistet. Natürlich muss ich kein C++ oder Qt verstehen, die Graphbeschreibung habe ich mit etwas "
grep" und "
sed" erzeugt. Die "Sprache", um ein solches Diagramm zu beschreiben braucht nur zwei Befehle. Erstens: "Kreis(Name)", um einen Zustand zu erzeugen, und zweitens: "Pfeil(Beschriftung,von,nach)" um einen Zustandsübergang zu beschreiben. Und aus dieser Beschreibung möchte ich dann gerne ein Bild haben, was mit dem oben vergleichbar ist. Ich habe das Bild oben recht eng gepackt, die Software kann sich da ruhig mehr Platz genehmigen. Weiß hier irgendjemand, welches Programm ich denn dafür zweckentfremden könnte?
P.S.: Ja, ich weiß, dass ich State Machines hier stark vereinfacht habe, aber verschachtelte und parallele Zustände lassen sich notfalls auch über separate Diagramme abbilden. Die hier geschriebene Basisfunktionalität sollte mir fürs Erste reichen. Um Erweiterungen mache ich mir erst dann Gedanken, wenn sich wirklich eine "Graph-Erzeugungs-Software" finden sollte. Wenn es sie geben sollte, kann sie wahrscheinlich sowieso schon mehr, als ich hier beschrieben habe.
Ich habe neben dem Kommentar von Matthias noch in im Chat "Graphviz" empfohlen bekommen. Hier das Bild, welches von Graphviz erzeugt wurde:
Sieht brauchbar aus, ich werde mir da definitiv noch ein paar Skripte bauen.
Kommentare