Hallo zusammen,
ich suche nach einer sinnvollen Namensgebung für meine
Zustandsmaschinen.
Angenommen, ich habe drei statische Zustände:
1
enumctrl_mode_e
2
{
3
ctrl_mode_disabled,
4
ctrl_mode_manual_feed,
5
ctrl_mode_auto_feed,
6
}
Ich nenne diese Zustände mal mit Absicht nicht A, B und C wie
Anleitungen und Tutorials.
Bei meinen Zustandsmaschinen sieht es oft so aus, dass in den
Transitionen mehr passiert als in den statischen Zuständen. Meistens
sind auch mehrere Durchläufe der Hauptschleife nötig, bis der
Zielzustand erreicht ist.
Also sind die Transitionen auch irgendwie Zustände, und es kommen ein
paar Zustände dazu:
1
enumctrl_mode_e
2
{
3
ctrl_mode_disabled,
4
ctrl_mode_disabled_to_manual_feed,
5
ctrl_mode_disabled_to_auto_feed,
6
ctrl_mode_manual_feed,
7
ctrl_mode_manual_feed_to_auto_feed,
8
ctrl_mode_manual_feed_to_disabled,
9
ctrl_mode_auto_feed,
10
ctrl_mode_auto_feed_to_manual_feed,
11
ctrl_mode_auto_feed_to_disabled,
12
}
(Ob die Zustandsmaschine jetzt mit enums oder mit Funktionszeigern
gefüttert wird, lassen wir mal außen vor.)
Es wird schlimmer. Zwei Transitionen sind praktisch identisch.
1
enumctrl_mode_e
2
{
3
ctrl_mode_disabled,
4
ctrl_mode_disabled_to_manual_feed,
5
ctrl_mode_disabled_to_auto_feed,
6
ctrl_mode_manual_feed,
7
ctrl_mode_manual_feed_to_auto_feed,
8
ctrl_mode_auto_feed,
9
ctrl_mode_auto_feed_to_manual_feed,
10
ctrl_mode_manual_feed_or_auto_feed_to_disabled,
11
}
Oder gibt es da irgendwie bessere, "normalere", übersichtlichere
Nomenklatur?
Mein Senf dazu:
Tipp 1: Steig (wenn möglich) auf C++ um und verwende enum classes. Das
macht alles ein wenig lesbarer:
1
enum class ctrl_mode_e
2
{
3
disabled,
4
manual_feed,
5
auto_feed,
6
}
Tipp 2: Transitionen gehören nur dann als Zustände ausgedrückt, wenn
dahinter z.B. eine zeitliche Anforderung steckt (nämlich einen Teil der
Aufgaben erst später abzufrühstücken, oder wenn in der Zwischenzeit
unbedingt das Mainloop laufen muss).
Ansonsten sind Transitionen genau das, nämlich keine Zustände. Also weg
damit.
Tipp 3: Halte Zustandsautomaten so einfach wie möglich. Einen Automaten
mit 100 Unterzuständen versteht niemand mehr, und mag auch niemand
validieren. Vor allem wenn 80% davon triviale Pseudozustände sind.
Wenn die transitionen so komplex sind, verpack den Code doch in
Hilfsfunktionen?
(Pseudocode)
1
switch(state)
2
{
3
case disabled:
4
{
5
if(check_disabled_autofeed())
6
change_disabled_autofeed();
7
else if(check_disabled_manualfeed())
8
change_disabled_manualfeed();
9
break;
10
}
11
}
In den Transitionsmethoden kannst du dich dann austoben.
Johannes schrieb:> Tipp 2: Transitionen gehören nur dann als Zustände ausgedrückt, wenn> dahinter z.B. eine zeitliche Anforderung steckt (nämlich einen Teil der> Aufgaben erst später abzufrühstücken, oder wenn in der Zwischenzeit> unbedingt das Mainloop laufen muss).
✓
(siehe Eröffnungsbeitrag)
Wären die Übergänge nicht zeitabhängig, wäre die Frage einfach.
Das schlimme an transitions ist das sie für eine bestimmte Aufgabe
gebaut werden.
Wenn man dann mal zwei Aufgaben beim Statewechsel braucht steht man da.
Ich arbeite viel mit state machines und habe mir angewöhnt in den
transitions nix mehr zu machen.
State Enter/Exit Methoden reichen mir in 99% der Fälle.
Anzahl states richtet sich natürlich nach der Aufgabe, kleine System
brauchen wenige, andere haben dann ein paar mehr.
Mit dem EnterpriseArchitect lassen sich hierarchische Diagramme
erzeugen, das entspannt die Komplexität, pro UseCase ein Diagram.
Das läßt sich sicher auch mit plantuml o.ä. ebenfalls lösen.
NichtWichtig schrieb:> Ich arbeite viel mit state machines und habe mir angewöhnt in den> transitions nix mehr zu machen.>> State Enter/Exit Methoden reichen mir in 99% der Fälle.
Was dann ganz ohne Umformulierung zu folgender Frage führt:
Walter T. schrieb:> ich suche nach einer sinnvollen Namensgebung für meine> Zustandsmaschinen.
Oliver
Walter T. schrieb:> ich suche nach einer sinnvollen Namensgebung für> meine Zustandsmaschinen.
Das Entscheidende bei der korrekten englischen
Bezeichnung "finite state machine" ist nicht, dass
die Maschine Zustände hat (denn das trifft auf JEDE
"Maschine" zu, auch auf eine reine Kombinatorik, denn
die hat EINEN Zustand) -- das Entscheidende ist, dass
eine "finite state machine" ENDLICH viele Zustände
hat. Das unterscheidet sie nämlich von der Turing-
Maschine oder dem Kellerautomaten, die unendlich viele
Zustände haben.
Aber ich gebe natürlich zu, dass die inhaltlich
korrektere Bezeichnung "endlicher Automat" bei weitem
nicht so prachtmäßig klingt wie "Zustandsmaschine"...
> Angenommen, ich habe drei statische Zustände:
Gibt es auch nicht-statische Zustände?
"Status" (--> statisch) heißt soviel wie Zustand.
> Bei meinen Zustandsmaschinen sieht es oft so aus,> dass in den Transitionen mehr passiert als in den> statischen Zuständen. Meistens sind auch mehrere> Durchläufe der Hauptschleife nötig, bis der> Zielzustand erreicht ist.>> Also sind die Transitionen auch irgendwie Zustände,> und es kommen ein paar Zustände dazu:
Hmm.
Mir will scheinen, Du hast kein Problem mit der
zweckmäßigen Wahl der Namen -- Du hast ein Problem
mit dem abstrakten Denkmodell des endlichen Automaten.
Zustände sind Zustände, und "Transitionen" sind Über-
gänge zwischen Zuständen.
> [...]> Es wird schlimmer. Zwei Transitionen sind praktisch> identisch.>
1
>enumctrl_mode_e
2
>{
3
>ctrl_mode_disabled,
4
>ctrl_mode_disabled_to_manual_feed,
5
>ctrl_mode_disabled_to_auto_feed,
6
>ctrl_mode_manual_feed,
7
>ctrl_mode_manual_feed_to_auto_feed,
8
>ctrl_mode_auto_feed,
9
>ctrl_mode_auto_feed_to_manual_feed,
10
>ctrl_mode_manual_feed_or_auto_feed_to_disabled,
11
>}
12
>
>> Oder gibt es da irgendwie bessere, "normalere",> übersichtlichere Nomenklatur?
Du hast m.E. kein Problem mit der Nomenklatur, Du hast
ein Problem mit dem Verständnis.
Jeder endliche Automat A(X,Y,Z,f,g) wird vollständig
definiert durch Angabe von:
- X, das ist die Menge aller Eingangssignale, und
- Y, das ist die Menge aller Ausgangssignale, und
- Z, das ist die Menge aller Zustände, und
- f, das ist die Überführungsfunktion, und
- g, das ist die Ausgabefunktion.
Die Überführungsfunktion z(n+1) = f(z(n),x(n)) ordnet
jedem Paar von (altem) Zustand und in diesem Zustand
eintreffenden Eingangssignal einen neuen Zustand zu.
(Anders formuliert: Die Überführungsfunktion kennt
alle Kanten (Zustandsübergänge, "Transitionen"); sie
wählt in jedem Zustand für jedes zulässige Eingangs-
signal den richtigen Folgezustand aus und setzt die
Zustandsvariablen entsprechend.)
Für die Ausgabefunktion g gibt es zwei Möglichkeiten:
1. Beim Moore-Automaten gilt y = f(z), d.h. das
Ausgangssignal wird NUR aus dem Zustand gebildet
(reines Umcodieren). Das führt zu einer relativ
einfachen Struktur, hat aber den Nachteil, dass
man u.U. ewig viele Zustände braucht.
2. Für den Mealy-Automaten gilt y = f(x,z), d.h. das
Ausgangssignal wird nicht nur aus dem Zustand
bestimmt, sondern man berücksichtigt zusätzlich
auch noch das Eingangssignal.
Man erkennt, dass der Mealy-Automat die Ausgangssignale
nicht den Zuständen (Knoten im Automatengraphen), sondern
den Kanten (Übergängen, "Transitionen") zuordnet.
Bei Realisierung in Software verwende ich i.d.R.
Mealy-Automaten; mir fällt zumindest im Moment kein
Gegenbeispiel ein.
(Reihenfolge der Berechnung von Überführungs- und
Ausgabefunktion weiss ich gerade nicht. Müsste ich
ein Beispiel angucken.)
Wenn man sich einen Automatengraphen vorstellt, dann
erkennt man außerdem, dass jede Kante ("Transition",
Zustandsübergang) definitionsgemäß zwischen einem Start-
und einem Zielzustand verläuft.
Das kann als Antwort auf die gestellte Frage gelten:
Wenn man alle Zustände sinnvoll benannt hat, dann
kann man sämtliche Übergänge nach dem Schema
"startname_to_endname" benennen -- es kann definitions-
gemäß keine Übergänge zwischen "Zuständen" geben, die
gar nicht zur definierten Zustandsmenge des Automaten
gehören.
Extratipp 1: Beim Entwurf immer Überführungsfunktion und
Ausgabefunktion geistig trennen. Das eine ist "alter
Zustand zu neuer Zustand", das andere ist "Zustand zu
Ausgang".
Extratipp 2: Immer erst alle Zustände und Übergänge
bedenken, die im "regulären Betrieg" auftreten; erst wenn
das stimmt, über Startphase und Stop-Phase nachdenken.
HTH
Mir sind nachträglich beim Lesen noch ein paar
Punkte aufgefallen, die m.E. Ergänzungen erfordern.
> Zustände sind Zustände, und "Transitionen" sind> Übergänge zwischen Zuständen.
Erste Ergänzung: Bei Steuerungsanwendungen ist es i.d.R.
so, dass es irgendeine reale (physische, anfassbare)
Maschinerie gibt, die irgendwas machen soll, und eine
Steuerungsmimik (eine SPS, einen µC o.ä.), der die
Abläufe steuern soll.
Hierbei ist es inhaltlich häufig so, dass Zustände
der Verarbeitungsmaschinerie auf Übergänge der
Steuerung abgebildet werden -- und umgekehrt Übergänge
der Verarbeitungsmaschinerie (=ablaufende Prozesse) auf
Zustände der Steuerung.
Beispiel: "Zylinder 1 fährt aus" ist in der Verarbeitungs-
maschinerie ein Zustandsübergang (=ein Prozess), denn es
ändert sich ja laufend die Position des Kolbens -- in der
Steuerung ist das aber ein Zustand. Solange die Endlage
noch nicht erreicht ist, ändert sich das Eingangssignal
für die Steuerung nicht, d.h. die Steuerung verharrt
solange im selben Zustand, bis der reale Prozess
abgeschlossen ist.
Wenn dann der Endlagenschalter angesprochen hat und in
der Steuerung ein Zustandsübergang erfolgt, passiert in
der Verarbeitungsmaschinerie erstmal nix -- die Endlage
ist ja erreicht, weiter geht es so nicht.
Erst wenn das neue Ausgangssignal in der Steuerung erzeugt
worden ist und irgendwelche Aktoren neue Signale bekommen
haben, gibt es einen neuen Zustandsübergang in der
Verarbeitungsmaschine -- dann gibt es aber gerade KEINEN
solchen Übergang in der Steuerung.
Anders ausgedrückt: Steuerung und Verarbeitungsmaschinerie
führen abwechselnd Zustandsübergänge aus.
Das kann u.U. verwirrend für das Verständnis und die Namens-
gebung sein.
Zweite Ergänzung: Es gibt darüberhinaus komplizierte Fälle,
bei denen das Verhalten der Steuerungsmimik durch ZWEI
gekoppelte Automaten modelliert werden kann, nämlich
z.B. einen übergeordneten Automaten, der die Betriebsart
festlegt und nur auf den untergeordneten Automaten wirkt,
und einen untergeordneten Automaten, der dann das
tatsächliche Verhalten der externen Maschinerie diktiert
und nach außen auf diese einwirkt.
Hierbei tritt scheinbar das Problem auf, dass ganze Ketten
von Übergängen in der realen Maschinerie auf einzelne
Zustände des "höherrangigen" Automaten abgebildet
werden -- aber der Irrtum beruht darauf, dass der
untergeordnete Automat übersehen wird. Ich betrachte diesen
Fall nicht näher.
>> [...]>> Es wird schlimmer. Zwei Transitionen sind praktisch>> identisch.>>
1
>>enumctrl_mode_e
2
>>{
3
>>ctrl_mode_disabled,
4
>>ctrl_mode_disabled_to_manual_feed,
5
>>ctrl_mode_disabled_to_auto_feed,
6
>>ctrl_mode_manual_feed,
7
>>ctrl_mode_manual_feed_to_auto_feed,
8
>>ctrl_mode_auto_feed,
9
>>ctrl_mode_auto_feed_to_manual_feed,
10
>>ctrl_mode_manual_feed_or_auto_feed_to_disabled,
11
>>}
12
>>
>>>> Oder gibt es da irgendwie bessere, "normalere",>> übersichtlichere Nomenklatur?
Deine Namensgebung lässt vermuten, dass es sich in Wahrheit
um drei Zustände ("disabled", "manual_feed" und "auto_feed")
und sechs Zustandsübergänge ("dis_to_manfeed", "dis_to_auto-
feed", "autofeed_to_manfeed", "manfeed_to_autofeed", "man-
feed_to_dis" und "autofeed_to_dis") handelt.
Zwischen drei Zuständen kann man sechs verschiedene
gerichtete Kanten finden; das kommt also hin.
> (Reihenfolge der Berechnung von Überführungs- und> Ausgabefunktion weiss ich gerade nicht. Müsste ich> ein Beispiel angucken.)
Dritte Ergänzung: Ich brauche endliche Automaten nicht
so sehr oft und musste erstmal überlegen, aber ich
handhabe das aus bestimmten Gründen konsequent so, dass
im aktuellen Zustand auf ein zulässiges Eingangssignal
geprüft und zuerst das passende Ausgangssignal berechnet
und ausgegeben wird. Anschließend wird der neue Zustand
bestimmt und die Zustandsvariable gesetzt. Anders aus-
gedrückt: Die Ausgangssignale werden konsequent den
abgehenden Kanten ("Transitionen") jedes Knoten (Zustandes)
zugeordnet.
HTH
Walter T. schrieb:> Wären die Übergänge nicht zeitabhängig, wäre die Frage> einfach.
???
Dann verwendet man Timer als zusätzliche Freigaben bzw.
Verriegelungen.
Vielleicht schilderst Du doch mal das konkrete Problem.
Egon D. schrieb:> Vielleicht schilderst Du doch mal das konkrete Problem.
Gerne.
Gibt es für Zustandsmaschinen irgendwie bessere, "normalere",
übersichtlichere Nomenklatur (als Namensgebung) als jenee, die ich oben
genannt habe?
Egon D. schrieb:> Vielleicht schilderst Du doch mal das konkrete Problem.
Gerne.
Gibt es für Zustände und Übergänge in Zustandsmaschinen irgendwie
bessere, "normalere", übersichtlichere Nomenklatur (also Namensgebung)
als jenee, die ich oben genannt habe?
Ich find die Namen auch OK.
Dazu noch ein Zustandsdiagramm und der Drop ist gelutscht.
Ich habe allerdinges folgendes nicht verstanden:
NichtWichtig schrieb:> Ich arbeite viel mit state machines und habe mir angewöhnt in den> transitions nix mehr zu machen.> State Enter/Exit Methoden reichen mir in 99% der Fälle.
Das ist für mich eine mögliche Darstellungsvariante im Zustandsdiagramm.
Macht das in Deinem Codeaufbau so einen Unterschied?
Wie realisierst Du Transitionen und Enter/Exit Methoden in Code?
BeBe
Ich sehe auch nicht ein, warum die Transitionen extra Namen bekommen
sollen.
Ich mache das oft auch so, daß die Statevariable in jedem Durchgang
automatisch weiter zählt. Soll in einem State auf was gewartet werden,
dann setzt man sie darin einfach wieder auf den alten Wert.
Hier mal ein Beispiel mit Hochzählen (onwire.c):
Beitrag "DS18B20 mit Interrupt, AVR-GCC"
Man sollte auch nicht wild zwischen den States hin und herspringen, dann
sieht ja keiner mehr durch. Typisch laufen die States nacheinander ab
mit nur wenigen Rücksprüngen. Man sollte also erstmal einen Ablaufplan
erstellen (PAP) und nicht einfach drauflos Code einhacken.
Enumerations finde ich hier jedenfalls sehr viel Besser, als einen
Integer der hochgezählt wird. Am Anfang merkt man das vielleicht noch
nicht, aber später wenn man etwas neues einfügt.
Stefan ⛄ F. schrieb:> Enumerations finde ich hier jedenfalls sehr viel Besser, als einen> Integer der hochgezählt wird.
Das Hochzählen bedingt natürlich, daß die Enums schon in der gewünschten
Reihenfolge definiert werden müssen. Es gibt dem Ganzen mehr Überblick,
da default die Transitionen aufsteigend sind und nur die wenigen
Ausnahmen hingeschrieben werden müssen. Auch verhindert es wirkungsvoll,
planloses hin- und herspringen. Weitere States lassen sich weiterhin
bequem einfügen.
Ich weiß aber nicht, ob auch unter C++ das Increment von Enums erlaubt
ist.
Peter D. schrieb:> Es gibt dem Ganzen mehr Überblick,> da default die Transitionen aufsteigend sind und nur die wenigen> Ausnahmen hingeschrieben werden müssen.
Ich würde die Wechsel lieber mit Namen hinschreiben, damit man sieht was
passiert. Auch wenn der Quelltext dadurch etwas größer wird. So etwas
fällt natürlich in die Kategorie "persönlicher Geschmack".
Wenn man in einem Team arbeitet, sollte man solche Details gemeinsam
abstimmen und sich dann auch weitgehend daran halten.
Peter D. schrieb:> Man sollte auch nicht wild zwischen den States hin und herspringen, dann> sieht ja keiner mehr durch.
Du hast das Problem auf den Punkt gebracht. Wenn man das vermeiden kann:
Glückwunsch!
Ich habe das Beispiel aber bewusst so formuliert, dass das
anforderungsbedingt nicht funktioniert.
Mein Beispiel: Ein Nutzer kann zwischen
Stillstand/Handbetrieb/Automatikbetrieb umschalten. Jederzeit und in
jeder Reihenfolge.
Diese drei statischen Betriebsmodi sind (in Bezug auf die
Zustandsmaschine) einfach. Da läuft einfach alles gewohnt wie ein
geöltes Getriebe. Die Übergänge sind (in Bezug auf die Zustandsmaschine,
aber auch den Rest) der interessante Teil. Da muss synchronisiert
werden. Und das dauert eben so lange, wie es dauert. Und das ist auch
keine Kleinigkeit, die man bei den statischen Modi einfach so mitlaufen
lässt, dass die ganze Zeit alles synchron ist. Und die Synchronisation
von A nach B sieht leider anders aus als die von B nach A. *)
PittyJ schrieb:> Das ist doch sehr übersichtlich, die Namen sind sprechend.
Bei drei Zuständen geht es. Ich habe leider in Wirklichkeit fünf. Zum
Glück sind nicht alle Übergänge erlaubt. Klar - es gibt in der Doku ein
niedliches Diagramm. Aber gute Namen und ein Diagramm sind noch besser
als nur ein Diagramm. **)
blub schrieb:> Der TO sprach ja auch nie von einem Problem, nur ob es eine> bessere/schönere Alternative der Bezeichnungen gibt......
✓
Peter D. schrieb:> Hier mal ein Beispiel mit Hochzählen (onwire.c):
Auch wenn das Beispiel hier nicht so passt: Danke dafür! Das hat mir an
anderer Stelle schon genutzt.
*) Da drängt sich natürlich die Frage auf: Ist das nicht testmäßig ein
Alptraum? Die Antwort lautet: "Ja." Mir fällt da nur wildes Monkey
Testing und warten, ob eine Assertion zuschlägt, ein.
**) Und die Diagramme haben sehr dicke Pfeile, weil die Übergänge ja der
interessante Teil sind.
Man muß nicht alles in eine große Statemaschine packen, sondern kann für
Unteraufgaben weitere Statemaschinen anlegen, die dann nur das "Ready"
an die übergeordnete weiter geben.
Ich hab auch Anwendungen, wo ich Abläufe mit meinem Scheduler steuere.
Z.B. muß ich zwischen Hochspannungen umschalten. Dazu muß ich warten,
bis die Kondensatoren sich entladen haben, das eine Relais ausschalten,
warten bis es abgefallen ist und dann das andere einschalten, warten,
bis es angezogen ist und die Spannung wieder hochfahren. In dieser Zeit
darf es sich der Bediener anders überlegen, z.B. doch den ersten Kreis
wieder einschalten wollen. Jedes Kommando fährt also wieder neu in den
sicheren Zustand. Damit ist abgesichert, daß nie zwei Relais gezogen
sind und nie Relais unter Spannung schalten.
Walter T. schrieb:> Und die Synchronisation> von A nach B sieht leider anders aus als die von B nach A. *)
Irgendwie verstehe ich das Problem nicht. Ja, Real-life ist komplexer
als Textbook. Dafür braucht es halt ein paar Zustände mehr. So what.
Oliver
Walter T. schrieb:> *) Da drängt sich natürlich die Frage auf: Ist das nicht testmäßig ein> Alptraum? Die Antwort lautet: "Ja." Mir fällt da nur wildes Monkey> Testing und warten, ob eine Assertion zuschlägt, ein.
Dann ist in meinen Augen das Konzept falsch.
Ein Test ist nur dann erfolgreich, wenn man gezielt jeden möglichen
Ablauf testen kann. Dazu müsen die Möglichkeiten entsprechend
eingeschränkt sein. Ein "wilder" Test ist nutzlos.
Peter D. schrieb:> Hier mal ein Beispiel mit Hochzählen (onwire.c):> Beitrag "DS18B20 mit Interrupt, AVR-GCC"
Ernsthaft?
1
caseOW_WR_DONE:// 1. command byte finished
2
pbuf++;
3
onwi.state=OW_WR_BIT0;
4
caseOW_WR_BIT0:// write bit 0
5
if(onwi.wr_cnt--)
6
{
7
caseOW_WR_BIT1:// write bit 1
8
caseOW_WR_BIT2:
9
caseOW_WR_BIT3:
10
caseOW_WR_BIT4:
11
caseOW_WR_BIT5:
12
caseOW_WR_BIT6:
13
caseOW_WR_BIT7:// write bit 7
14
ONWI_oe=1;// pin = low
15
_delay_us(1);
16
if(*pbuf&1)
17
ONWI_oe=0;// pin = tristate
18
*pbuf>>=1;
19
break;
20
}
Das soll Dein Vorschlag sein? Deinen Humor möchte ich haben!
Um es ganz deutlich zu sagen: Dieser Code ist ein Beispiel wie man es
nicht macht! Völlig unwartbar!
Irgendwie sind an Dir die Erkenntnisse der letzten 50 Jahre spurlos
abgeprallt.
Das muss man erstmal schaffen...
Peter D. schrieb:> Ich hab auch Anwendungen, wo ich Abläufe mit meinem Scheduler steuere.> Z.B. muß ich zwischen Hochspannungen umschalten.> [...]> Jedes Kommando fährt also wieder neu in den> sicheren Zustand.
Das ist schön und ich bin ein bischen neidisch. Der sichere Zustand im
Zwischenraum fehlt mir.
Dein Beispiel ist ein bischen wie ein Schaltgetriebe am Auto. Egal
zwischen welchen Gängen ich umschalte, es geht immer über den Leerlauf,
und die Synchronringe müssen so ausgelegt sein, dass sie nur diese eine
Transition für jeden Gang beherrschen. Und das Ausrücken benötigt seine
Zeit, ist aber zum Glück recht einfach, da die Last abgekoppelt wird.
Jetzt wechseln wir gedanklich zur Nabenschaltung am Fahrrad. Der brutale
Nutzer am Schaltgriff kann zwischen allen Gängen wild hin und
herschalten. Unter Last. Und Anhalten zwischen den Gängen ist auch keine
Option. Der Nutzer sollte zwar nur brav zwischen benachbarten Gängen
wechseln, aber der Konstrukteur muß so auslegen, dass das andere auch
nicht zu Bruch führt.
Peter D. schrieb:> Dann ist in meinen Augen das Konzept falsch.> Ein Test ist nur dann erfolgreich, wenn man gezielt jeden möglichen> Ablauf testen kann. Dazu müsen die Möglichkeiten entsprechend> eingeschränkt sein. Ein "wilder" Test ist nutzlos.
Er ist besser als nichts. In einem System, in dem kinetische Energie
gespeichert ist (siehe Beispiel Nabenschaltung), kann man prinzipbedingt
nicht alle möglichen Zustände systematisch durchfahren.
BeBe schrieb:> Ich find die Namen auch OK.> Dazu noch ein Zustandsdiagramm und der Drop ist gelutscht.>> Ich habe allerdinges folgendes nicht verstanden:>> NichtWichtig schrieb:>> Ich arbeite viel mit state machines und habe mir angewöhnt in den>> transitions nix mehr zu machen.>> State Enter/Exit Methoden reichen mir in 99% der Fälle.>> Das ist für mich eine mögliche Darstellungsvariante im Zustandsdiagramm.> Macht das in Deinem Codeaufbau so einen Unterschied?> Wie realisierst Du Transitionen und Enter/Exit Methoden in Code?>> BeBe
Die Basis ist ein C++ Framework der eine FSM anbietet welche states,
transitions und rules kennt.
Wird ein state instanziert so wird dieser eine Enter und Exit Methode
haben, die läßt sich individuell gestallten.
Eine Transition hat eine exec methode.
Die rules sind immer (ISTstate, trigger, Zielstate, transition)
Das zwingende ist das eben nur exakt eine transition angegeben werden
darf.
Und das stört dann wenn code aus 2 oder mehr transitions dazu kommen
(CR)
Da bleibt dann nur auslagern in eigene Methoden welche dann in den
transitions aufgerufen werden. Schaut häßlich aus und läßt sich
vermeiden.
NichtWichtig schrieb:> Die Basis ist ein C++ Framework der eine FSM anbietet welche states,> transitions und rules kennt.> Wird ein state instanziert so wird dieser eine Enter und Exit Methode> haben, die läßt sich individuell gestallten.
Merci. Ich hatte vor Augen, dass Du änlich wie die Beispiele oben
StateMachines mittels case Strukturen abbildest.
Welches Framework nutzt Du?
Generierst Du Code aus Zustandsdiagrammen?
(Was IMHO bei Zustandsmaschinen im Vergleich zu anderen Diagrammarten
super funktioniert).
Experte schrieb:> Um es ganz deutlich zu sagen: Dieser Code ist ein Beispiel wie man es> nicht macht! Völlig unwartbar!
Du kannst es gerne besser machen.
Ich nutze die Sprachelemente von C so aus, daß sich Copy&Paste möglichst
vermeiden läßt. Switch/Case ist ja vom Prinzip her ein Goto, läßt sich
also auch so verwenden.
Was ich unwartbar finde, ist das Kopieren von gleichen Codesequenzen an
mehrere Stellen. Denn bei Änderungen vergißt man dann eine Stelle und
sucht sich nen Wolf.
Ojeh...
Prinzipiell sollte man es natürlich vermeiden, sinnlose Codeduplikate
herumliegen zu haben.
ABER!
Wenn man den gleichen Code an verschiedenen Stellen benutzt, geht man
damit eine Vereinbarung ein. Nämlich das alle Benutzer immer die
gleichen Anforderungen an den Code stellen werden.
Wenn man das garantieren kann dann gern, aber erfahrungsgemäß laufen
Codeteile mit der Zeit auseinander und stellen dann plötzlich
unterschiedliche Anforderungen an den gleichen geteilten Code.
Zudem schafft man sich mit geteiltem Code eine Abhängigkeit zwischen 2
Codeteilen die mitunter nicht vorhanden sein müsste. Legt man den Code
in eine geteilte Lib hat man zwar erst mal gewonnen, aber
erfahrungsgemäß landen dann noch weitere Dinge in der Lib, diese bekommt
dadurch neue Abhängigkeiten usw.
Und am Ende hat man eine Dependency auf diese Lib, die 100 andere Sachen
hineinzieht, obwohl man nur eine einfache dumme Hilfsfunktion teilen
wollte.
Muss nicht so laufen, tut es aber leider doch häufig genug.
Zu dem verkrampften Codestück von oben, das in der Form auch nur in
C/C++ gültig ist, sag ich mal nichts. würg
Johannes schrieb:> Zu dem verkrampften Codestück von oben, das in der Form auch nur in> C/C++ gültig ist, sag ich mal nichts. würg
Duff's Device war auch mal ein herausragendes Stück Softwarekunst. Die
Zeiten haben sich aber geändert...
Oliver
Johannes schrieb:> Prinzipiell sollte man es natürlich vermeiden, sinnlose Codeduplikate> herumliegen zu haben.
Ich meinte damit, daß man viel gleichen Code in viele Case dublizieren
müßte, um das "böse" Durchlaufen zu vermeiden.
Wenn ich das richtig sehe, war das doch der Kritikpunkt an meiner
Schreibweise.
Ich weiß natürlich daß solche CopY&Paste Monster die Compiler recht gut
optimieren können (Common subexpression elimination).
Aber ich finde, daß die Lesbarkeit stark darunter leidet. Man muß viel
lesen, um dann festzustellen, das Codestück hatten wir doch schon x-mal.
Und oft übersieht man dann kleine aber wichtige Unterschiede.
Das Durchlaufen in den nächsten Case macht meiner Meinung nach die
Abläufe besser sichtbar und verstehbar.
Johannes schrieb:> Und am Ende hat man eine Dependency auf diese Lib, die 100 andere Sachen> hineinzieht, obwohl man nur eine einfache dumme Hilfsfunktion teilen> wollte.
Hat meiner Erfahrung nach zwei Ursachen-Felder:
a.) Mangelhaftes oder nicht existierendes Modul-System der verwendete
Programmiersprache. Erstaunlich viele Programmiersprachen sind hier
richtig schlecht aufgestellt. Gerade auch C/C++.
b.) Keine weitere innere Struktur der Software. Alles ist mit allem
verbunden. Die "Fach"bücher sind voll mit schlechten Beispielen.
Omnipräsent sind irgendwelche Layers, bei denen die höheren
Schichten von den niedrigeren Abhängig sind. Genau da kommen
diese transitive Abhängigen her, wo eine kleine Funktion Tonnen
von Mist reinzieht.
Übrigens, meiner Meinung nach, sind Zustands-Maschinen ein Symptom von
Ursache B, keine innere Struktur. In fast allen Zustandsmaschinen wird
versucht, zu vieles irgendwie alles gleichzeitig zu machen. Da kommt
dann die Explosion der Zustände inkl. unzähliger Transitionen her.
Bestes Beispiel ist doch das Eingangsposting. Ursprünglich gibt es nur
drei Zustände. Aber plötzlich sollen hier auch die Details (zeitliche
Abfolge) von irgendwelchen Sub-Systemen behandelt werden.
Die Basics das in der Griff zu bekommen sind einfach:
- Strikte Trennung zwischen Kommando und Abfrage (CQRS)
- Kommandos so lange es nur irgendwie geht, grundsätzlich
idempotent gestalten.
Am Beispiel vom Eingangsposting wird es doch deutlich. Die drei Zustände
sind in Wirklichkeit doch nur unterschiedliche Konfigurationen von
irgendwelchen Subsystemen. Also muss diese Abstraktionsebene im Prinzip
nur feststellen, welcher der drei Zustände gerade gewünscht ist, und den
Subsystemen per idempotente Kommandos nur die entsprechende
Konfiguration mitteilen. Wie die dahin kommen, ist deren Sache. Und den
Subsysteme wiederum es es doch egal, warum sie eine bestimmte
Konfiguration annehmen sollen. Und wenn sich die Subsystem gerade
umkonfigurieren und dabei unterbrochen werden und eine andere
Konfiguration annehmen sollen, ist das ihr Problem, wie sie dahin
kommen.
So wie immer in der Software: Teile und herrsche. Das führt zum Ziel.
Experte schrieb:> Und wenn sich die Subsystem gerade> umkonfigurieren und dabei unterbrochen werden und eine andere> Konfiguration annehmen sollen, ist das ihr Problem, wie sie dahin> kommen.
Dafür wären Zustandsmaschinen dann nicht verkehrt. Was dann unmittelbar
zur Frage des TO führt.
Die ganze Abstraktion ist prima, aber irgendwann landet man auf dem
Boden der Realität. Walters's Boden sind halt seine oben genannten
Zustände.
Oliver
BeBe schrieb:> NichtWichtig schrieb:>> Die Basis ist ein C++ Framework der eine FSM anbietet welche states,>> Welches Framework nutzt Du?
Firmeninternes Gebilde das seit >20 Jahren wächst.
>> Generierst Du Code aus Zustandsdiagrammen?> (Was IMHO bei Zustandsmaschinen im Vergleich zu anderen Diagrammarten> super funktioniert).
Nein, code wurde lange Zeit von Hand erzeugt.
Inzwischen habe ich eine Parser auf dem device welcher die EA SM
einließt, Objekte erzeugt und die FSM startet.
Ich kann in den states duzende Aktion konfigurieren und die events
ebenfalls per EA konditionieren.
Und da sind wir bei transition ohne code, da habe ich im EA schlechte
Möglichkeiten sinnvolles zu machen, was aber nicht schlimm ist.
Zur Not wird ein frischer State eingeschoben wo wieder alles möglich
ist. Natürlich mit einem hübschen state name der Sinn ergibt :-)
Experte schrieb:> Wie die dahin kommen, ist deren Sache. Und den> Subsysteme wiederum es es doch egal
Mag sein, aber manchmal muss man nicht-blockierend abwarten, bis
bestimmte Aktionen ausgeführt sind, bevor der nächste Arbeitsschritt
ausgeführt werden darf.
Das obige Beispiel mit dem Schaltgetriebe fand ich dazu schon sehr
passend - zumindest für Leute denen die Synchronisierung der Zahnräder
ein Begriff ist.
Stefan ⛄ F. schrieb:> Experte schrieb:>> Wie die dahin kommen, ist deren Sache. Und den>> Subsysteme wiederum es es doch egal>> Mag sein, aber manchmal muss man nicht-blockierend abwarten, bis> bestimmte Aktionen ausgeführt sind, bevor der nächste Arbeitsschritt> ausgeführt werden darf.
Womit ein guter Grund für ein eigener State gegeben ist.
NichtWichtig schrieb:> Stefan ⛄ F. schrieb:>> Experte schrieb:>>> Wie die dahin kommen, ist deren Sache. Und den>>> Subsysteme wiederum es es doch egal>>>> Mag sein, aber manchmal muss man nicht-blockierend abwarten, bis>> bestimmte Aktionen ausgeführt sind, bevor der nächste Arbeitsschritt>> ausgeführt werden darf.>> Womit ein guter Grund für ein eigener State gegeben ist.
Absolut korrekt. Wenn man schon eine Statemachine baut, muss man das mit
den Zuständen auch durchziehen. Und dazu gehört solche Geheimen
Pseudo-Zustände zu eliminieren und als echte Zustände zu behandeln.
Walter T. schrieb:> Egon D. schrieb:>> Vielleicht schilderst Du doch mal das konkrete Problem.>> Gerne.>> Gibt es für Zustände und Übergänge in Zustandsmaschinen> irgendwie bessere, "normalere", übersichtlichere> Nomenklatur (also Namensgebung) als jenee, die ich oben> genannt habe?
Ja, natürlich.
Ein wesentlicher Beitrag zur Übersichtlichkeit ist, dass
Zustände als Zustände erkennbar sind und Übergänge zwischen
Zuständen eben als Übergänge zwischen zwei Zuständen.
Zustände sind keine Übergänge, und Übergänge keine Zustände.
Du kannst das letztlich handhaben, wie Du willst, aber die
Mathematik lässt sich nicht betrügen.
Da hängt dann das Akzeptieren der betrüblichen Tatsache
dran, dass eine Kante im Automatengraphen (= ein Übergang,
eine Transition) GENAU EINEN Anfangszustand und GENAU EINEN
Endzustand hat.
Davon abgesehen: Zustände heissen bei mir "state_irgendwas",
und Übergänge "startzustand_to_zielzustand". Ich finde das
hinreichend übersichtlich.
Peter D. schrieb:> Ich sehe auch nicht ein, warum die Transitionen extra> Namen bekommen sollen.
Weil es bequem sein kann, die Ausgabefunktion für jede
Kante in ein eigenes Unterprogramm zu packen, und das
muss ja irgend einen sinnvollen Namen bekommen.
> Ich mache das oft auch so, daß die Statevariable in> jedem Durchgang automatisch weiter zählt.
Das klappt nur im allereinfachsten Fall.
> Man sollte auch nicht wild zwischen den States hin> und herspringen, dann sieht ja keiner mehr durch.
Das ist aber manchmal notwendig.
> Typisch laufen die States nacheinander ab mit nur> wenigen Rücksprüngen.
Das ist zwar häufig so, aber nicht immer. Endliche
Automaten haben den Charme, dass man mit ihnen jede
beliebige Verkettung zwischen den Zuständen ausdrücken
kann. Das Grundschema ist immer gleich übersichtlich
oder unübersichtlich -- lediglich die Größe, d.h. die
Anzahl der Knoten und Kanten ändert sich.
> Man sollte also erstmal einen Ablaufplan erstellen> (PAP) und nicht einfach drauflos Code einhacken.
Das ist immer eine gute Idee.
Peter D. schrieb:> Dann ist in meinen Augen das Konzept falsch.> Ein Test ist nur dann erfolgreich, wenn man gezielt> jeden möglichen Ablauf testen kann.
Echt? Du glaubst an eine Testüberdeckung von 100%?
Gott erhalte Dir Deinen Kinderglauben.
Walter T. schrieb:> Mein Beispiel: Ein Nutzer kann zwischen> Stillstand/Handbetrieb/Automatikbetrieb umschalten.> Jederzeit und in jeder Reihenfolge.
Wenn das so ist, dann ist es "broken by design".
Sinnvoll wäre: Ein Nutzer kann ein Steuersignal
erzeugen, das seinen Wunsch anzeigt, zwischen
Stillstand/Handbetrieb/Automatikbetrieb umzuschalten.
Jederzeit und in jeder Reihenfolge.
Wann die Steuerung auf dieses Signal reagieren kann,
ist eine andere Frage.
Egon D. schrieb:> Wenn das so ist, dann ist es "broken by design".
Im Gegenteil. Es ist das, was jeder Nutzer von einer guten Steuerung
erwartet.
Egon D. schrieb:> Sinnvoll wäre: Ein Nutzer kann ein Steuersignal> erzeugen, das seinen Wunsch anzeigt, zwischen> Stillstand/Handbetrieb/Automatikbetrieb umzuschalten.
Das ist die Implementierung. Und eine gute Steuerung kommt dem möglichst
schnell -- im Rahmen der physikalischen Möglichkeiten und
Systemparameter -- nach.
"Möglichst schnell im Rahmen der physikalischen Möglichkeiten" und
"einfach zu implementieren" sind leider oft nicht kompatibel. Dann muss
man Prioritäten setzen. Meine liegt auf ersterem.
Andererseits sollte man es sich, wenn es schon anforderungsbedingt
kompliziert ist, wenigstens beim Ordnung halten möglichst einfach
halten.
Egon D. schrieb:> Echt? Du glaubst an eine Testüberdeckung von 100%?> Gott erhalte Dir Deinen Kinderglauben.
Wenn die Sache sinnvoll geplant ist und man die Anzahl der Übergänge
klein hält, geht das durchaus.
Z.B. für sicherheitskritische Anwendungen kann es sinnvoll sein, erstmal
aus jedem alten Zustand in einen sicheren Zustand zu gehen und dann erst
den gewünschten Zustand anzusteuern. Dann muß man nicht wild
umherspringen und kann alles vollständig testen. Daß das Umschalten
vielleicht mal etwas länger dauert, wird durch den Gewinn an Testbarkeit
und Sicherheit aufgewogen.
Egon D. schrieb:> Sinnvoll wäre: Ein Nutzer kann ein Steuersignal> erzeugen, das seinen Wunsch anzeigt, zwischen> Stillstand/Handbetrieb/Automatikbetrieb umzuschalten.> Jederzeit und in jeder Reihenfolge.>> Wann die Steuerung auf dieses Signal reagieren kann,> ist eine andere Frage.
So mache ich das auch. Die Statemaschine arbeitet so lange, bis
current_state == wanted_state. D.h. sie klettert alle Zwischenzustände
hoch bzw. runter und springt nicht wild umher.
Peter D. schrieb:> Die Statemaschine arbeitet so lange, bis> current_state == wanted_state. D.h. sie klettert alle Zwischenzustände> hoch bzw. runter und springt nicht wild umher.
Interessanter Ansatz, das kannte ich noch nicht.
Stefan ⛄ F. schrieb:> Peter D. schrieb:>> Die Statemaschine arbeitet so lange, bis>> current_state == wanted_state. D.h. sie klettert alle Zwischenzustände>> hoch bzw. runter und springt nicht wild umher.>> Interessanter Ansatz, das kannte ich noch nicht.
Das ist dann auch nur eine spezielle Art einer hirarchischen State
machine, die halt für solche Probleme, bei der die Unteraufgaben "linear
durchtackern", brauchbar ist.
Oliver
Peter D. schrieb:> So mache ich das auch. Die Statemaschine arbeitet so lange, bis> current_state == wanted_state. D.h. sie klettert alle Zwischenzustände> hoch bzw. runter und springt nicht wild umher.
Du hast eine sehr spezielle Sicht darauf, was eine Statemachine sein
soll. Allein dass du diese mit einem Ablaufdiagramm beschreiben willst.
Eine "Richtung" in die der Flow läuft usw.
Das passt so nicht. Das ist eben keine Statemachine.
Eine Statemachine wird durch ein Zustandsdiagramm beschrieben. Nicht
durch ein Abblaufdiagram.
Dort sind alle Zustände zu sehen und alle möglichen Übergänge.
Es gibt keine Restriktionen was die Übergänge angeht.
Natürlich kann man die irgendwie gerichtet anordnen und nur Übergänge in
eine "Richtung" definieren. Das ist aber eben keine zentrale Eigenschaft
einer Statemachine sondern die Implementierung eines Sonderfalles. Und
ich würde davon Abstand nehmen dies Anfängern so ans Herz zu legen.
Peter D. schrieb:> Die Statemaschine arbeitet so lange, bis> current_state == wanted_state. D.h. sie klettert alle Zwischenzustände> hoch bzw. runter und springt nicht wild umher.
So macht das meine auch. Das geht ganz gut tabellarisch. Es gibt
- gewünschter Zustand
- aktueller Zustand
- erlaubte Zustände
und dann hangelt sich die Zustandsmaschine vom aktuellen über die
erlaubten Zustände bis zum gewünschten Zustand.
Der Pfad läuft über eine Tabelle (Array) mit "nächstbesten Zuständen",
also erlaubte Zustände, die mich dem gewünschten Zustand näher bringen.
Man könnte den "nächstbesten Zustand" formalisieren: Zustände sind
Knoten, Zustandsübergänge Kanten. Der nächstbeste Zustand wäre dann "Der
Zustand mit der kürzesten Anzahl von Kanten zum gewünschten Zielzustand
im Netz der erlaubten Zustandsübergänge" - aber die Tabelle ist zum
Glück noch klein genug, dass sie einfach von Hand aufgestellt ist. Da
kann ich auf einen aufwendigen Formalismus verzichten. *)
Das Problem: Tabellen und lange Namen sind unübersichtlich. Tabellen und
zu kurze Namen sind noch unübersichtlicher.
Aber die Diskussion verläuft gerade sehr Richtung Implementierung. Das
ist ja nicht überflüssig. Aber auch nicht die Frage. Die Frage ist: "Wie
benennt man die Zustände sinnvoll". Zur Benennung gehören zwei Punkte:
a) Domänenwissen und Fähigkeit zur Abstraktion
b) ein sinnvolles Schema
Nicht dazu gehört die Implementierung.
Teil a) kann man nicht sinnvoll zwischen unterschiedlichen Domänen
diskutieren. b) schon. Deswegen geht es um b).
*) Wobei mir der Gedanke, das als Netz zu betrachten, heute zum ersten
Mal kommt. Vielleicht ist das wirklich ganz übersichtlich. Netze lassen
sich gut automatisch plotten.
Walter T. schrieb:> Mein Beispiel: Ein Nutzer kann zwischen> Stillstand/Handbetrieb/Automatikbetrieb umschalten. Jederzeit und in> jeder Reihenfolge.
Hier noch ein Vorschlag, der eher aus Steuerungssicht ist, weniger aus
softwaretheoretischer Sicht.
Jeder Betriebszustand wird über den Initialisierungszustand "start..."
angefahren. In diesem Zustand gibt es dann die Fallunterscheidung von
welchem Zustand der Ablauf kommt. Man kann damit das System gut
sukzessive aufbauen, der erste Schritt wäre, die Modi nur aus dem
Stillstand ansteuerbar zu machen. Die Entscheidung, welche Schritte zum
Einleiten des Modus gebraucht werden, wird auch nur in dem einen Zustand
getroffen und nicht wie in deinem "disabled_to_manual",
"disabled_to_auto" von außerhalb.
Die Initialisierungszustände können von außen angerufen werden, nach
Durchlauf schieben die sich weiter in den Betriebsmodus. Ist der
Automatikmodus durchlaufen, schiebt er sich in den
"start_disabled"-Zustand.
Maxe schrieb:> Die Entscheidung, [... wird ...] dem einen Zustand> getroffen und nicht wie in deinem "disabled_to_manual",> "disabled_to_auto" von außerhalb.
Die Entscheidung über die "Zwischenmodi" darf natürlich nur die
Zustandsmaschine fällen. Das wäre ja noch schöner!
Die Idee, das über nicht-sprechende kurze Präfixe zu gruppieren, gefällt
mir.
Walter T. schrieb:> und dann hangelt sich die Zustandsmaschine vom aktuellen über die> erlaubten Zustände bis zum gewünschten Zustand.>> Der Pfad läuft über eine Tabelle (Array) mit "nächstbesten Zuständen",> also erlaubte Zustände, die mich dem gewünschten Zustand näher bringen.
Irgend wann muss man sich dann mal entscheiden, ob man für jedes neue
Programm sich eine neue, selbst gebastelte Version eines Mix aus
Zustandsmaschine, Ablaufsteuerung, switch- und if/else-Gräbern und
undefinierten Übergängen bastelt, oder ob man doch mal auf die reine
Lehre zurückgreift.
Wartbar sind diese selbstgebastelten Wunderdinger nämlich nie.
Oliver
Oliver S. schrieb:> oder ob man doch mal auf die reine> Lehre zurückgreift.
Also als Implementierung gibt es die "reine Lehre" sicher nicht. Aber ja
man kann eine Statemachine relativ simpel und nach Lehrbuch
implementieren und so sollte man das auch versuchen.
Was eben nicht trivial ist, ist sich erst mal alle möglichen Zustände
korrekt auszudenken. Wie man auch hier sieht, mutetet das einfach an,
ist es aber nicht.
Von den korrekten Zuständen hängt nachher alles ab. Vertut man sich da,
klappt es später nur mit Verrenkungen (z.B. Zwischenzustände usw.).
In der Theorie gibt es auch nur den einen Zustand, in der Realität muss
man oft noch weitere Zustände prüfen um den nächsten Übergang zu
entscheiden. Das lässt sich selten vermeiden.
Da gibt es dann so nette Requirements, mit der Bitte den Code möglichst
so zu strukturieren wie die Diagramme des Anforderers.
Und dann steht weiter unten im Text so etwas: "Abweichend zum Diagramm
gilt zusätzlich, dass jeder Vorgang abbrechen soll wenn ... passiert.
Ausgenommen wenn .... Und wen ... dann soll der Abbruch aber zu xxx
führen, normalerweise hingegen zu ...".
Und schon ist die schöne heile Welt dreckig.
Oliver S. schrieb:> oder ob man doch mal auf die reine> Lehre zurückgreift.
In der Praxis gibt es aber diese reine Lehre nicht. Jede Aufgabe hat
ihre speziellen Anforderungen, die man nicht nach Schema F lösen kann.
Dazu ist die Natur und damit die Aufgaben zu vielfältig.
Wenn man alles mit einem Universalwerkzeug lösen könnte, dann bräuchte
man keine Entwickler und Programmierer mehr. Es gibt aber immer wieder
neue Aufgaben, die neue Lösungen brauchen.
Die Sichtweise, die Zustände als Knoten und die Übergänge als gerichtete
Kanten zu interpretieren, ist gar nicht übel. Damit lässt selbst bei
sehr komplizierten Ketten sehr schnell statisch überprüfen, ob auch
wirklich für alle wählbaren Zustände ein erlaubter Weg existiert. Aber
das ist erst einmal nur Phantasie - so kompliziert sind die
Möglichkeiten bei mir nicht.
Noch mehr hilft der Ansatz mit den Präfixen zur Gruppierung.
Der erste Präfix ist der Grundzustand. Der zweite der Zielzustand. Das
sieht auf den ersten Blick nach verpönter Duplizierung aus - ist aber
für Tabellen sehr praktisch.
1
enumctrl_mode_e
2
{
3
cmErr,
4
5
cmAA,
6
cmAB,
7
cmAC,
8
9
cmBB,
10
cmBA,
11
cmBC,
12
13
cmCC,
14
cmCA,
15
cmCB,
16
17
cmEnd,
18
19
ctrl_mode_AA_disabled=cmAA,
20
ctrl_mode_AB_disabled_to_manual_feed=cmAB,
21
ctrl_mode_AC_disabled_to_auto_feed=cmAC,
22
23
ctrl_mode_BB_manual_feed=cmBB,
24
ctrl_mode_BA_manual_feed_to_auto_feed=cmBA,
25
ctrl_mode_BB_manual_feed_to_disabled=cmBC,
26
27
ctrl_mode_CC_auto_feed=cmCA,
28
ctrl_mode_CA_auto_feed_to_manual_feed=cmCA,
29
ctrl_mode_CB_auto_feed_to_disabled=cmCB,
30
};
Der Compiler ist clever genug, sich in switch-case mit dem Bezeichner
der Wahl zufriedenzugeben und warnt auch nicht, wenn ein Synonym fehlt.
Die Bezeichner für die Zeilen sind lang und sprechend, die Bezeichner
kurz und übersichtlich. Wie bei einer sinnvollen Tabelle in einem
gedruckten Text.
Die Übergangsmatrix sieht in dem einfachen Fall, dass die Übergänge wie
im Eröffnungsbeispiel erlaubt sind, natürlich absolut regelmäßig aus:
1
/* 1. Index: SOLL, 2. Index: IST */
2
constenumctrl_mode_eswitchMatrix[cmEnd][cmEnd]=
3
{
4
[ctrl_mode_AA_disabled]=
5
{
6
[cmAA]=cmAA,[cmAB]=cmBA,[cmAC]=cmCA,
7
[cmBA]=cmAA,[cmBB]=cmBA,[cmBC]=cmCA,
8
[cmCA]=cmAA,[cmCB]=cmBA,[cmCC]=cmAC,
9
},
10
[ctrl_mode_BB_manual_feed]=
11
{
12
[cmAA]=cmAB,[cmAB]=cmBB,[cmAC]=cmCB,
13
[cmBA]=cmAB,[cmBB]=cmBB,[cmBC]=cmCB,
14
[cmCA]=cmAB,[cmCB]=cmBB,[cmCC]=cmCB,
15
},
16
[ctrl_mode_CC_auto_feed]=
17
{
18
[cmAA]=cmAC,[cmAB]=cmBC,[cmAC]=cmCC,
19
[cmBA]=cmAC,[cmBB]=cmBC,[cmBC]=cmCC,
20
[cmCA]=cmAC,[cmCB]=cmBC,[cmCC]=cmCC,
21
},
22
};
Ich bin nicht glücklich, aber es ist besser als der Status Quo. Was
vorher mehrseitige switch-case-Geschichten waren, ist jetzt eine
drittelseitige Tabelle mit ein paar Nullzeilen.
Edit: Nee, das ist Mist. Nichts gewonnen.
Walter T. schrieb:> Die Sichtweise, die Zustände als Knoten und die Übergänge als gerichtete> Kanten zu interpretieren, ist gar nicht übel. Damit lässt selbst bei> sehr komplizierten Ketten sehr schnell statisch überprüfen, ob auch> wirklich für alle wählbaren Zustände ein erlaubter Weg existiert.
Bitte was??
Die gesamte Automatentheorie ist mathematisch sauber definiert und lässt
sich als Graph interpretieren und auswerten, beweisen usw.
Erst waren die Graphen, Grammatiken, theoretischen Maschinen usw. da,
dann kamen die Leute und haben damit ihre Zustandsautomaten
programmiert. Nicht anders herum.
Leider gibt es heute zu viele Leute die die Theorie nicht mehr können.
Johannes schrieb:> Leider gibt es heute zu viele Leute die die Theorie nicht mehr können.
Vermutlich mehr als 7 Milliarden Menschen. Das war früher vermutlich
weniger schlimm. Da waren es nur 5 Milliarden.
Nicht jeder Mensch, der mit Computern etwas macht, ist Informatiker.
An sich st eine StateMachine doch garnicht so schwer.
Nimm ein geeignetes Werkzeug und designe Deine SM
Z.B. https://plantuml.com/de/state-diagram
Was in welchen State passieren kann und ob oder wie drauf zu reagieren
ist hängt doch vom einzelnen Fall ab.
Das bildet man in den entsprechende Rules ab.
Walter T. schrieb:> NichtWichtig schrieb:>> Das bildet man in den entsprechende Rules ab.>> Hast Du Material, wie die Rules üblicherweise abgebildet werden?
Er meint damit das wird im jeweiligen State je nach Einzelfall
entschieden.
Aber der Kern ist: Statemachines sind eigentlich wirklich schön und
übersichtlich zu implementieren. Gerade weil man sich immer auf einen
State konzentrieren kann.
Aber ich würde auch empfehlen die Statemachine am Anfang mal
aufzuzeichnen. Dann erst programmieren.
Ein bisschen Eigeninitiative kann man doch aber erwarten, oder? Bei
Automaten (und verbunden damit Grammatiken) handelt es sich um eines der
grundlegendsten Konzepte in der Informatik überhaupt.
https://de.wikipedia.org/wiki/Automatentheorie
und dann
https://de.wikipedia.org/wiki/Automat_(Informatik)
inkl. der Unterseite zum endlichen Automaten und zur Turing Maschine.
(Kellerautomaten braucht man eigentlich nicht.)
Kostet dich vielleicht 2h Leseaufwand und gibt zumindest einen Überblick
über die Theorie.
Wie bereits weiter oben beschrieben:
rules( SourceState , Event, DestState, Transition );
Der eine State wird auf 2..3 events reagiren müssen,
ein anderer braucht ein paar mehr, koommt halt drauf an was Du bauen
willst.
Aber glasklar läßt sich das in UML erkennen, verstehen und prüfen ob
alle gewollten events von state X bedient werden - und wohin's dann
geht.
Beispiel aus dem Link:
SourceState -> DestState : event [Transition]
1
@startuml
2
scale 600 width
3
4
[*] -> State1
5
State1 --> State2 : Succeeded
6
State1 --> [*] : Aborted
7
State2 --> State3 : Succeeded
8
State2 --> [*] : Aborted
9
state State3 {
10
state "Accumulate Enough Data\nLong State Name" as long1
Mit UML habe ich ein buntes Bild. Welcher Datentyp, den mein Compiler
kennt, wird aus dem Bild? Wie ich die Informatiker kenne, eine doppelt
verlinkte Liste. Informatiker lieben doppelt verlinkte Listen. Oder eine
Tabelle? Oder generierter Quelltext?
Oder muss ich das Bildchen doch wieder von Hand nachprogrammieren? Dann
sind wir wieder bei der Tabelle am Anfang angelangt.
Wo finde ich Infos zu dem Teil, der anfängt, wenn die bunten Bildchen
aufhören? Es gibt zu viele bunte Bildchen. Auf dem Power Point
Abstraction Layer haben immer alle alles kapiert und können sich darüber
breit auslassen.
Cyblord -. schrieb:> Aber ich würde auch empfehlen die Statemachine am Anfang mal> aufzuzeichnen. Dann erst programmieren.
Die State Machine ist aufgemalt und programmiert und funktioniert. Und
jetzt will ich sie noch einmal in richtig(TM) machen, weil ich sie
demnächst erweitern will/muss.
Walter T. schrieb:> Mit UML habe ich ein buntes Bild.
Mit UML hast du deinen kompletten Automat mit allen Zuständen und
Übergängen mal visualisiert. Das hilft dir enorm.
> Welcher Datentyp, den mein Compiler> kennt, wird aus dem Bild? Wie ich die Informatiker kenne, eine doppelt> verlinkte Liste. Informatiker lieben doppelt verlinkte Listen. Oder eine> Tabelle? Oder generierter Quelltext?
Ziemlich viel Häme für jemand der solche Dinge einfach nicht selbst
gebacken bekommt.
> Die State Machine ist aufgemalt und programmiert und funktioniert. Und> jetzt will ich sie noch einmal in richtig(TM) machen, weil ich sie> demnächst erweitern will/muss.
"Richtig" gibt es halt nicht.
Zeig mal dein Bild.
Cyblord -. schrieb:> Ziemlich viel Häme für jemand der solche Dinge einfach nicht selbst> gebacken bekommt.
Ziemlich viel Häme versteht mein Compiler nicht. Also nützt mir das
nichts.
Walter T. schrieb:> Cyblord -. schrieb:>> Ziemlich viel Häme für jemand der solche Dinge einfach nicht selbst>> gebacken bekommt.>> Ziemlich viel Häme versteht mein Compiler nicht. Also nützt mir das> nichts.
Skill würde dir nützen. Statt dummer Sprüche.
Wo ist denn nun das Bild? Es ist kein Witz dass eine solche Planung die
Implementierung nachher vereinfacht.
Neben den Zuständen ist auch die Eingabemenge wichtig. Welche "Events"
gibt, die Übergänge auslösen? Ist das sauber definiert? Kannst du die in
ein enum packen? Oder musst du kreuz und quer rumsuchen ob jetzt von
irgendwoher ein Übergang ausgelöst werden soll? Das ist wichtig!
Wenn du eine Statemachine nach dieser Art bauen kannst:
1
voidstateMachine(enumeventsevent){
2
switch(state){
3
casestate1:
4
if(event==X)state=state2;
5
if(event==Y)state=state3;
6
break;
7
casestate2:
8
if(event==X)state=state4;
9
if(event==Y)state=state1;
10
break;
11
}
12
}
dann kannst du das sehr übersichtlich gestalten.
Damit das klappt, muss du dir aber über die Eingabe im klaren sein. Und
du musst dir klar machen dass eine Statemachine eine Komponente braucht
welche die "treibt". Eine Statemachine kann Teil eines zyklischen
Prozesses sein, aber sie ist selbst kein zyklischer Prozess. Sie braucht
einen Aufrufer.
Hat man sehr Unterschiedliche "Events" die man nicht gruppieren will,
kann man die SM auch aufteilen:
Klar. Ein Diagramm. Für ein billiges Beispiel mit drei statischen und
drei Übergangszuständen.
"Du must erst das Problem vollständig exakt und genau beschreiben,
vorher kann man keine Tipps geben!"
"Wie kann man nur mit so wenig Ahnung versuchen, überhaupt erst etwas zu
machen?"
"Schau doch einfach mal bei Google. Da steht doch genau, was zu tun
ist!"
Bullshit Driven Design - wie man sich als Wenigkönner zum Foren-Experten
aufspielt.
Egon D. schrieb:> Walter T. schrieb:>>> Mein Beispiel: Ein Nutzer kann zwischen>> Stillstand/Handbetrieb/Automatikbetrieb umschalten.>> Jederzeit und in jeder Reihenfolge.>> Wenn das so ist, dann ist es "broken by design".>> Sinnvoll wäre: Ein Nutzer kann ein Steuersignal> erzeugen, das seinen Wunsch anzeigt, zwischen> Stillstand/Handbetrieb/Automatikbetrieb umzuschalten.> Jederzeit und in jeder Reihenfolge.>> Wann die Steuerung auf dieses Signal reagieren kann,> ist eine andere Frage.
Wenn Stillstand der "NOT AUS" Knopf ist, ist das keine Frage ...
Walter T. schrieb:> Klar. Ein Diagramm. Für ein billiges Beispiel mit drei statischen und> drei Übergangszuständen.>> "Du must erst das Problem vollständig exakt und genau beschreiben,> vorher kann man keine Tipps geben!">> "Wie kann man nur mit so wenig Ahnung versuchen, überhaupt erst etwas zu> machen?">> "Schau doch einfach mal bei Google. Da steht doch genau, was zu tun> ist!">> Bullshit Driven Design - wie man sich als Wenigkönner zum Foren-Experten> aufspielt.
Ich denke nicht dass du noch Hilfe hier suchst oder?
Mal abgesehen von der gewohnt herzlichen Art auf mikrocontroller.net -
in diesem Thread hier geht es ja tatsächlich noch mehr oder weniger
freundlich zu, keine Beleidigungen, kein gegenseitiges Heruntermachen,
kein "halt die Fresse" bisher - ist es halt nicht so einfach wie du die
Lösung gern hättest.
Wenn man State Machines sauber benutzt bleiben sie etwas halbwegs
einfach durchschaubares. Die Kunst liegt darin zu erkennen, wann ein
Problem sich derart verändert (man lernt während der Entwicklung ja auch
viel über das zugrunde liegende Problem) das klassische State Machines
nicht mehr die richtige Lösung sind.
Man muss dafür wissen was damit gut geht und was nicht. Und wenn man
während der Entwicklung wachsam ist kann man den Punkt abpassen ab dem
die Sache "aus dem Ruder" läuft und mit anderen Techniken
gegensteuern/ausweichen, über die man natürlich ebenso Wissen haben
muss.
Wenn man den Punkt verpasst wird der Code immer komplizierter und man
weis am Ende selbst nicht mehr so recht was man da eigentlich tut.
Es gibt dabei aber keine universelle Lösung, sondern es ist halt immer
sehr problemspezifisch. Und das hört auch noch gar nicht bei dem auf was
zu tun ist, sondern schließt noch hunderte Rahmenbedingungen mit ein -
wer soll den Code später lesen, wie teuer werden Fehler, Performance,
ist das eine Lösung die später nie wieder angefasst wird oder steckt da
ein agiles Projekt hinter, ...
Gerade bei State Machines kann man oft ein wenig tricksen und sie
bleiben am Ende doch sehr sauber und übersichtlich. Z.B. indem man nur
einen Teil des Problems als SM darstellt und den Rest anders löst.
Manchmal zeigt sich aber auch, dass sie einfach nicht die richtige
Lösung sind.
Dabei gibt es auch viele verschiedene Herangehensweisen um dieses
Problemwissen zu erlangen. Manchen Leuten hilft es die SM zu
visualisieren (ist zu Dokuzwecken eh immer gut) um die Komplexität zu
erfassen, andere können sich das schon aus dem Stand recht gut
vorstellen (und müssen bei komplexeren Sachen dann auch wieder
visualisieren), wieder andere fangen einfach an zu Coden und schauen wo
es sie hin führt.
TL;DR
Softwareentwicklung ist halt ein komplexes Thema mit vielen
theoretischen und praktischen Aspekten. Man braucht da unbedingt ein
ganzheitliches Denken.
Walter T. schrieb:> enum ctrl_mode_e> {> ctrl_mode_disabled,> ctrl_mode_disabled_to_manual_feed,> ctrl_mode_disabled_to_auto_feed,> ctrl_mode_manual_feed,> ctrl_mode_manual_feed_to_auto_feed,> ctrl_mode_auto_feed,> ctrl_mode_auto_feed_to_manual_feed,> ctrl_mode_manual_feed_or_auto_feed_to_disabled,> }
Bei den From-A-to-B States stellt sich mir die Frage nach der Relevanz
der From-Information (fürs Programm UND für den Nutzer). Was Du da mit
zeitlicher Verzögerung umstellst, kann man nicht einzeln mit einer
Sollvorgabe, dem zweifellos bekannten Istwert und dem Status Busy/Ready
kapseln? (Das geht sogar mit Nutzereingaben!)
Dann würden neben den Stati disabled/manual/auto doch nur noch ein
"busy" (während sich die Einstellungen vornehmen) und maximal noch ein
ein "error" (vielleicht ein Timeout auf busy) bleiben.
Das als Planung auf einem Blatt Papier gezeichnete landet ja sowieso
früher oder später auf einem Display. Was hilft dem Nutzer die
Information "Wechsele von Auto-Modus in den Disabled -Modus"? Wäre da
nicht "Schaltet ab" sinniger?´
Walter T. schrieb:> Egon D. schrieb:>> Wenn das so ist, dann ist es "broken by design".>> Im Gegenteil. Es ist das, was jeder Nutzer von> einer guten Steuerung erwartet.>> Egon D. schrieb:>> Sinnvoll wäre: Ein Nutzer kann ein Steuersignal>> erzeugen, das seinen Wunsch anzeigt, zwischen>> Stillstand/Handbetrieb/Automatikbetrieb umzuschalten.>> Das ist die Implementierung.
Richtig!
Du machst hier selbst den Fehler, den Du an anderer
Stelle Deinem Gesprächspartner (zu Recht) vorwirfst:
Du wechselst willkürlich zwischen Anwendungsdomäne
und Implementierungsdomäne.
Genau darauf wollte ich Dich hinweisen.
Dass es dem Nutzer so erscheint , als könne er
jederzeit sofort zwischen den "Zuständen" Hand-
steuerung, Automatiksteuerung und Aus wechseln,
besagt nicht, dass es technisch auch so ist .
Peter D. schrieb:> Egon D. schrieb:>> Echt? Du glaubst an eine Testüberdeckung von 100%?>> Gott erhalte Dir Deinen Kinderglauben.>> Wenn die Sache sinnvoll geplant ist und man die> Anzahl der Übergänge klein hält, geht das durchaus.
Natürlich.
Dieser Aussage hätte ich auch beim ersten Mal nicht
widersprochen :)
Peter D. schrieb:> Egon D. schrieb:>> Sinnvoll wäre: Ein Nutzer kann ein Steuersignal>> erzeugen, das seinen Wunsch anzeigt, zwischen>> Stillstand/Handbetrieb/Automatikbetrieb umzuschalten.>> Jederzeit und in jeder Reihenfolge.>>>> Wann die Steuerung auf dieses Signal reagieren kann,>> ist eine andere Frage.>> So mache ich das auch. Die Statemaschine arbeitet so> lange, bis current_state == wanted_state. D.h. sie> klettert alle Zwischenzustände hoch bzw. runter und> springt nicht wild umher.
Hmm.
Mir wird nicht genau klar, was Du mit "nicht wild umher
springen" meinst.
Wenn Du meinst: "Die Zustände sind linear geordnet,
und man darf vom aktuellen Zustand nur entweder zum
Vorgänger oder zum Nachfolger gehen", dann würde ich
dem widersprechen. Lineare Ordnung der Zustände kommt
zwar in der Praxis recht häufig vor, ist aber keine
grundsätzliche Eigenschaft eines endlichen Automaten.
Man macht nichts grundsätzlich falsch, wenn der eigene
Automat keine solche (fast) lineare Struktur hat.
Wenn Du aber meinst: "Man darf nur in Zustände übergehen,
die durch eine Kante (in der richtigen Richtung :) mit
dem aktuellen Zustand verbunden sind", dann ist das zwar
korrekt -- aber auch tautologisch: Natürlich gehört zu
einem ganz bestimmten konkret gegebenen Automaten(graphen)
GENAU EINE bestimmte Überführungsfunktion. Übergänge, die
in der Überführungsfunktion nicht auftauchen, sind bei
diesem Automaten somit nicht zulässig und dürfen auch
nicht ausgeführt werden. Andernfalls verkommt der "Automat"
zur Farce.
Oliver S. schrieb:> Irgend wann muss man sich dann mal entscheiden, ob man> für jedes neue Programm sich eine neue, selbst gebastelte> Version eines Mix aus Zustandsmaschine, Ablaufsteuerung,> switch- und if/else-Gräbern und undefinierten Übergängen> bastelt, oder ob man doch mal auf die reine Lehre> zurückgreift.
Das finde ich eine etwas seltsame Wortwahl: Die "reine Lehre"
der Automatentheorie besteht aus Mengenlehre und Algebra; bei
Bedarf an unendlichen Automaten kommt dann noch formale Logik
bzw. Theorie der formalen Sprachen dazu.
Wie implementierst Du damit, ohne auf eine Programmiersprache
zurückzugreifen, einen funktionierenden endlichen Automaten?
> Wartbar sind diese selbstgebastelten Wunderdinger nämlich> nie.
Was empfiehlst Du?
Ich frage ganz im Ernst -- die Sprache, die von vornherein
für softwaredefinierte endliche Automaten vorgesehen ist,
ist AWL aus der SPS-Welt, und das kann doch wohl nicht die
präferierte Lösung sein.
Walter T. schrieb:> Die State Machine ist aufgemalt und programmiert und> funktioniert. Und jetzt will ich sie noch einmal in> richtig(TM) machen, weil ich sie demnächst erweitern> will/muss.
Künstlerpech: Du bist zielsicher in das Minenfeld geraten,
das die "richtigen" Programmierer zwischen sich und den
SPS-Leuten angelegt haben.
SPS-Leute programmieren seit Jahrzehnten Automatennetze
aus Dutzenden lokalen Automaten, deren jeder ein Dutzend
Zustände oder mehr hat -- aber das ist für die "richtigen"
Programmierer noch lange kein hinreichender Grund, das
nicht als Gefrickel von halbverblödeten Elektrikern abzutun.
Dabei sind die Ähnlichkeiten zwischen beiden Kriegsparteien
größer als die Unterschiede -- C-Code sieht für das ungeübte
Auge etwa genauso krank aus wie ein AWL-Programm... SCNR
Soll heißen: Endliche Automaten sind als abstraktes Modell
eigentlich ziemlich einfach, wenn man die Definitionen und
das bissl zugehörige Mengenlehre mal wirklich verstanden
hat.
Merkwürdigerweise gibt es nach meinem Kenntnisstand aber
keine Programmiersprache, die die Klarheit im Grundkonzept
auch im täglichen praktischen Einsatz zum Tragen bringt!
Johannes schrieb:> Die gesamte Automatentheorie ist mathematisch sauber> definiert und lässt sich als Graph interpretieren und> auswerten, beweisen usw.
Das stimmt.
> Erst waren die Graphen, Grammatiken, theoretischen> Maschinen usw. da, dann kamen die Leute und haben damit> ihre Zustandsautomaten programmiert. Nicht anders herum.
Nun ja.
Meine überbordende Höflichkeit gebot mir, den Kommentar
wegzulöschen, der ursprünglich hier stand... :)
Tatsächlich waren da zuerst Mathematiker und Elektro-
techniker; die einen haben sich Gedanken über Codes,
Codewandler, Relais- und Kontaktschaltungen und ähnliches
gemacht, und die anderen haben die Automaten VERDRAHTET.
Relais- und Kontaktschaltungen gab es in der Steuerungs-
technik, der Kryptoanalyse und auch in der Numerik schon
bevor die (frei programmierbaren) Computer im heutigen
Sinne in Massen auftraten.
Es hat seinen tieferen Sinn, dass die Langform von "SPS"
SPEICHER -programmierbare Steuerung heißt. Der Vorgänger
waren nämlich die VERBINDUNGSPROGRAMMIERTEN Steuerungen.
Die damit ausgerüsteten Maschinen haben auch produziert!
Grammatiken und formale Sprachen werden erst mit frei
speicherprogrammierbaren Maschinen interessant; die
sind also historisch jünger als verdrahtete Steuerungen.
Und wer verdrahtete Steuerungen verstanden hat, hat auch
"Statemachines" verstanden...
Hans-Georg L. schrieb:> Wenn Stillstand der "NOT AUS" Knopf ist, ist das keine Frage ...
Richtig. Den Teil habe ich vergessen.
"Es gibt aber noch andere Sachen als das, was hier im einfachen Modell
abgebildet wird! Ätsch!"
Johannes schrieb:> Mal abgesehen von der gewohnt herzlichen Art auf mikrocontroller.net -> in diesem Thread hier geht es ja tatsächlich noch mehr oder weniger> freundlich zu, keine Beleidigungen, kein gegenseitiges Heruntermachen,> kein "halt die Fresse" bisher -
Das ist als Leistung natürlich ungefähr wie die Entwicklungsabteilung,
die ihren neuen "nicht-brennenden und nicht-saugenden Staubsauger" als
Erfolg verbrieft. Er saugt zwar nicht, aber im Vergleich zu
Vorgängermodell trotzdem eine echte Verbesserung.
Johannes schrieb:> - ist es halt nicht so einfach wie du die Lösung gern hättest.
Ich habe nie behauptet, dass es einfach ist. Einfache Sachen brauche ich
nicht zu fragen. Und eine "Lösung" suche ich auch nicht. Ich suche
Anregungen und erlernbare Techniken. GitHub durchlesen und hoffen, dass
in anderer Leute Code gute Zustandsmaschinen zu finden sind, ist sehr
ineffizient.
Cyblord -. schrieb:> Neben den Zuständen ist auch die Eingabemenge wichtig. Welche "Events"> gibt, die Übergänge auslösen? Ist das sauber definiert?
Die Frage ist nicht verkehrt - nur hier außerhalb des
Betrachtungsbereichs. Die Übergangsbedingungen/Events in Ordnung zu
bringen kostet nicht wenig Aufwand, aber sie ist von der Namensgebung
zum Glück relativ naheliegend. Es gibt zwei Structs UserInput und
CtrlState, aus denen sich die Übergangsbedingungen durch einfache
if-Abfragen oder "is"-Bedingungen abprüfen lassen.
Egon D. schrieb:> einen übergeordneten Automaten, der die Betriebsart> festlegt und nur auf den untergeordneten Automaten wirkt,> und einen untergeordneten Automaten, der dann das> tatsächliche Verhalten der externen Maschinerie diktiert> und nach außen auf diese einwirkt.
Das ist auch naheliegend und so implementiert. Praktischerweise sind die
untergeordneten Zustandsmaschinen so gestrickt, dass da einfache lineare
Zustände (stell erst 1), dann 2), dann 3) sicher und dann bist Du
fertig) ausreichend sind.
Die einfache lineare Ablaufsteuerung macht es zum Glück auch
überflüssig, dass die Zustandsmaschinen selbst synchronisiert werden.
Wird A-to-B zwischendrin unterbrochen und in B-to-A gewechselt (das wäre
an dieser Stelle der einzige erlaubte Übergang vor Beendigung von
A-to-B), muss letztere nicht wissen, wo erstere aufgehört hat, sondern
findet einfach viele Bedingungen schon erfüllt vor.
Framulestigo schrieb:> Bei den From-A-to-B States stellt sich mir die Frage nach der Relevanz> der From-Information (fürs Programm UND für den Nutzer).
Für das Programm ist die FROM-Info essentiell. Wenn ich etwas
synchronisieren will, muss ich die Sync-Quelle kennen. Beim Beispiel
oben: Wechsel in den Automatik-Modus aus dem Stand: Langsames
Hochfahren. Wechsel aus dem Automatik-Modus aus dem Handbetrieb: Mit der
gleichen Geschwindigkeit ruckfrei übernehmen.
Framulestigo schrieb:> Das als Planung auf einem Blatt Papier gezeichnete landet ja sowieso> früher oder später auf einem Display. Was hilft dem Nutzer die> Information "Wechsele von Auto-Modus in den Disabled -Modus"? Wäre da> nicht "Schaltet ab" sinniger?´
Ich weiß nicht genau, was "auf dem Display" bedeuten soll. Die Doku
landet natürlich ab und an auf dem PC-Bildschirm. Der Nutzer des
Zielsystems hat nur ein paar rastende Schalter. Er bekommt die
Zustandsmaschine zum Glück nie zu sehen. Ich bin schließlich nicht Hans
Rüdi Giger, der seine Alpträume anderen visuell aufdrängt.
Ich suche gar kein fertiges Rezept. Das kann es nicht geben. Ich suche
gute Ideen und Techniken, wie man Übersicht in "viele" Zustände
hineinbringt.
Walter T. schrieb:> Die Frage ist nicht verkehrt - nur hier außerhalb des> Betrachtungsbereichs. Die Übergangsbedingungen/Events in Ordnung zu> bringen kostet nicht wenig Aufwand, aber sie ist von der Namensgebung> zum Glück relativ naheliegend.
Nur betrifft diese Frage nicht nur eine Benamung. Wie ich in meinen
Beispielen gezeigt habe, hänge die Arten von Events direkt mit der
Implementierung zusammen.
Und in deinem Codebeispiel sieht es so aus als ob du in den States, die
Events "abfragst" anstatt dass diese Events überhaupt erst die Maschine
triggern. Das macht die Sache aber tendenziell komplizierter und
verbirgt die möglichen Eingaben(=Events) in die Maschine. Und zusammen
mit den Zuständen, ist die Eingabemenge DER Essentielle Teil einer SM.
Kein Grund diese Stiefmütterlich zu behandeln.
Und wenn man diese mal hinschreibt(=Definiert) geht es eben nicht
unbedingt um die Namen sondern darum sich diese Menge (die endlich ist)
mal klar zu machen. Ein weiter Grund für das Bild. So ein Bild kannst du
in draw.io doch echt schnell machen.
> Ich suche gar kein fertiges Rezept. Das kann es nicht geben. Ich suche> gute Ideen und Techniken, wie man Übersicht in "viele" Zustände> hineinbringt.
Habe ich dir gegeben. Aber du machst im Moment nicht den Eindruck
wirklich offen für Vorschläge zu sein.
Cyblord -. schrieb:> hänge die Arten von Events direkt mit der> Implementierung zusammen.
Ich habe die Events extra außen vor gelassen.
Ich bin in der komfortablen Situation, alle Event-Eventualitäten in
einem einzigen Satz zusammenfassen zu können: "Neuer Wunschzustand:
Zustand X". Wobei X einer der genannten (in meinem Beispiel drei)
Grundzustände ist.
Sprich: Es gleicht alles einem diskreten Regler. Ich habe einen
SOLL-Zustand und einen IST-Zustand. Der SOLL-Zustand ist einfach. Der
IST-Zustand ist komplizierter, was im Wesentlichen daran liegt, dass
mehrere Übergangszustände vorliegen können (siehe erstes Beipiel).
Vielleicht ist "Zustandsmaschine" auch der falsche Begriff, weil er
untrennbar mit Events verknüpft ist, und es gibt eine bessere
Bezeichnung, die ich nicht kenne. "Zustandsflächennavigator" oder so.
Namen sind schwierig. Womit wir wieder beim Eingangsproblem sind.
Cyblord -. schrieb:> Habe ich dir gegeben. Aber du machst im Moment nicht den Eindruck> wirklich offen für Vorschläge zu sein.
Jeder Mensch behauptet von sich, offen für Vorschläge zu sein. Aber wenn
die Vorschläge in die Richtung "wir lösen ein Problem, das keins ist,
weil das viel einfacher ist als in die Richtung zu gucken, wo das
eigentlich Problem gezeigt wird" gehen, darf man mich gern als stur
bezeichnen.
Eine andere Kategorie, bei der ich gern als stur bezeichnet werden darf,
ist wenn die "Lösung" in Richtung "Hier zeige ich, wie das Problem in
Haskell auf einer Cray gelöst wird. Ich bin nämlich sehr schlau." geht.
Diese Art vom Beitrag ist in diesem Thread zum Glück nur leicht
gestreift.
Walter T. schrieb:> Ich habe die Events extra außen vor gelassen.>> Ich bin in der komfortablen Situation, alle Event-Eventualitäten in> einem einzigen Satz zusammenfassen zu können: "Neuer Wunschzustand:> Zustand X". Wobei X einer der genannten (in meinem Beispiel drei)> Grundzustände ist.
Wozu dann überhaupt eine Statemachine? Wenn einfach zu jeder Zeit jeder
Zustand angesprungen werden soll, dann ist das nicht wirklich eine SM,
höchstens noch formal. Aber es erscheint offensichtlich dass dir dann
das festhalten an diesem Konzept probleme bereiten wird.
Die Idee hinter einer SM ist ja, dass das Verhalten in erster Line vom
aktuellen Zustand abhängt und in einem anderen Zustand ganz anders
aussieht. Wobei "Verhalten" sich hier auf die Übergänge zu anderen
Zuständen bezieht.
Ist bei dir aber dann gar nicht gegeben. Weil die Übergänge in jedem
Zustand gleich funktionieren. Richtig?
>> Sprich: Es gleicht alles einem diskreten Regler. Ich habe einen> SOLL-Zustand und einen IST-Zustand. Der SOLL-Zustand ist einfach. Der> IST-Zustand ist komplizierter, was im Wesentlichen daran liegt, dass> mehrere Übergangszustände vorliegen können (siehe erstes Beipiel).
Im Prinzip hast du verschiedene Abfolgen von Aktionen die in bestimmten
Situationen aufgerufen und abgearbeitet werden sollen.
Dabei hast du "Betriebszustände".
Ich würde hier allerdings auch sagen, dass du diese Zustände NICHT über
eine SM managen solltest.
> Vielleicht ist "Zustandsmaschine" auch der falsche Begriff, weil er> untrennbar mit Events verknüpft ist, und es gibt eine bessere> Bezeichnung. Namen sind schwierig. Womit wir wieder beim Eingangsproblem> sind.
Ja denke ich auch. Eigentlich solltest du alle möglichen fixen Abfolgen
die es gibt implementieren und diese dann je nach gewünschtem Übergang
S0 -> S1 aufrufen und ablaufen lassen.
Cyblord -. schrieb:> Weil die Übergänge in jedem> Zustand gleich funktionieren. Richtig?
Das Auslösen des Übergangs ist in jedem Zustand gleich. Der Übergang ist
in jedem Zustand unterschiedlich.
(Der Übergang von "Stillstand und abgeschaltet" zu "automatischer
Bewegung" ist natürlich komplett komplementär zu der in die
Gegenrichtung.)
Und die Übergänge selbst lassen sich auch gut und übersichtlich als
klassische Zustandsmaschine realisieren.
Walter T. schrieb:> Das Auslösen des Übergangs ist in jedem Zustand gleich. Der Übergang ist> in jedem Zustand unterschiedlich.
Was ist hier der Auslöser der überall gleich ist?
> (Der Übergang von "Stillstand und abgeschaltet" zu "automatischer> Bewegung" ist natürlich komplett komplementär zu der in die> Gegenrichtung.)
Ich behaupte mal, du hast diese "Betriebszustände", aber die sind nicht
identisch mit den nötigen Zuständen deiner SM.
Daher wäre ein Auslöser ala "Gehe in Zustand S3" auch kein Event welches
zu einer SM passt.
Ein Auslöser wäre: Zeitabgelaufen, Knopf gedrückt, Sensor aktiviert usw.
Darauf kann eine SM reagieren.
Also vielleicht musst du deine Betriebszustände von den States der SM
getrennt sehen.
Kannst du an dem obigen konkreten Beispiel mal sagen, was die Maschine
tun muss, um von "Stillstand und abgeschaltet" zu "automatischer
Bewegung" zu kommen?
Cyblord -. schrieb:> Kannst du an dem obigen konkreten Beispiel mal sagen, was die Maschine> tun muss, um von "Stillstand und abgeschaltet" zu "automatischer> Bewegung" zu kommen?
Das ist extrem unspektakulär.
1
/** Zustandsmaschine: Wechsel von Stillstand zu automatischem Vorschub
Es sind klassische Ablaufsteuerungen, die einfach jeweils einen Schritt
weiterschalten. Weil die Bedingungen für die Schritte so einfach sind,
haben die Zwischenzustände noch nicht einmal einen Namen und werden auch
gar nicht erst gespeichert. Timeout wird hier auch nicht benötigt, weil
sich das durch die Systemdynamik selbst ergibt. Also irgendwie
zustandslose Zustandsmaschinen. Das hat den Nebenvorteil, dass man von
einem Übergang in den komplementären Übergang komplikationslos
hinüberspringen kann.
Edit: Der Umgang der Forensoftware mit Leerzeilen im Quelltext nervt.
Ich habe mal einen Übergang versucht zu Zeichnen.
Es ist schon möglich das alles per SM zu definieren. Aber man sieht
schon, so richtig passt es nicht.
Denn, wie du schreibst, du hast mehr Abläufe, mit Verzweigungen.
Klassische Flowcharts. Also sequentielle Programmierung.
Dass du "Betriebszustände" hast, ändert das nicht. Letztlich hast du für
jeden Übergang deiner Betriebszustände einen Flow den du durchlaufen
willst.
Das kann man ohne SM besser implementieren als mit.
Darum hier der 2. Vorschlag der viel besser passt:
Jeder Übergang deiner Zustände ruft eine Funktion auf, welche eine
Sequenz abarbeitet. Wobei es kein einmaliger Aufruf sein muss, kann in
diesem State dann auch zyklisch erfolgen.
Eingabealphabet in deine SM wäre dann z.B.:
"ToDisabled"
"ToManual"
"ToAuto"
"Sequence Finished"
"eStop"
DAS kannst du super einfach modellieren. Jede Eingabe ruft in einem
Zustand die richtige Sequenz auf.
Du musst dir nur noch überlegen wie die Sequenzen getimed werden und wie
du diese Eingaben in die SM genau realisierst.
Die Zustände mit den Sequenzen warten nur darauf, bis die Sequenz
Vollzug meldet. Aus Sicht der SM passiert hier nichts, ausser warten auf
Finished oder ein Fehler oder eStop oder so.
Was du hier auch siehst, du hast zwar für jeden Übergang einen eigenen
SEQUENCE State, aber es könnten dort auch jeweils die gleichen
Funktionen gestartet werden. D.h. du brauchst nicht für jeden Übergang
eine extra Sequenz-Funktion. Den State selbst aber schon.
Walter T. schrieb:> Ich habe nie behauptet, dass es einfach ist. Einfache Sachen brauche ich> nicht zu fragen. Und eine "Lösung" suche ich auch nicht. Ich suche> Anregungen und erlernbare Techniken. GitHub durchlesen und hoffen, dass> in anderer Leute Code gute Zustandsmaschinen zu finden sind, ist sehr> ineffizient.
Dafür musst du ganz generell Erfahrung in der Softwareentwicklung
sammeln.
Deine "Aufgabe" als Entwickler ist nicht, mechanisch die Gegebenheiten
in eine State Machine zu überführen und zu hoffen, dass mit richtiger
Technik alles gut wird. Das funktioniert bei einfachen Problemen aber
fliegt dir bei komplexen Sachen um die Ohren.
Es gab schon genug Versuche Programmierer durch Software zu ersetzen.
Alle schief gegangen, mal von den Tasks abgesehen die tatsächlich
einfach mechanisch sind, z.B. RPC Codegeneratoren. Selbst Sprachparser
werden bei komplexeren Sprachen manuell entwickelt, obwohl es genug gute
Generatoren gibt.
Deine Aufagbe als Entwickler ist es, das Problem zu verstehen und dann
zu sehen, ob, wo und wie eine sehr einfache State Machine das Problem
drastisch vereinfachen könnte. Das ist dann ziemlich häufig nicht die
State Machine, die die Problembeschreibung suggeriert.
Alle generischen Tipps für SM sind hier schon irgendwo gefallen. Mehr
gibt es halt nicht. Im Gegensatz zu z.B. RPC Codegeneratoren haben sich
solche für State Machines auch nie wirklich durchgesetzt, weil sie zu
wenig einsparen.
Mit ein wenig Disziplin bekommt man das händisch genau so gut hin und
hat später nicht das Problem, das irgendwer direkt im Code ändert ohne
den Generator erneut anzuwerfen.
Cyblord -. schrieb:> Darum hier der 2. Vorschlag der viel besser passt
Also Respekt für Deinen Enthusiasmus, aber: Der zweite Vorschlag sieht
am wenigsten schlimm aus, aber es ist das perfekte Beispiel, in dem
billiger Quelltext aussagekräftiger als ein Zustandsdiagramm ist.
Und eigentlich wollte ich bei der Diskussion gar nicht in die
Einzelunterzustände hinabtauchen. Die habe ich im Griff. Du siehst ja,
wie einfach sie im Quelltext aussehen. In der Doku ist das eine einfache
Abhakliste. (Es sind die einfachsten aus der Reihe, aber die anderen
sind auch sehr linear - nur eben mit ein paar Wartezeiten und ein wenig
Synchronisierung.)
Ich bin auch sehr glücklich darüber, dass sich die Einzel-Unterzustände
oder -Abläufe oder wasauchimmer sehr gut voneinander trennen lassen.
Lassen wir sie in Ruhe. Ihnen geht es gut.
Es geht darum, in die Handhabung der übergeordneten Zustände etwas mehr
Ordnung hineinzubringen.
Walter T. schrieb:> Cyblord -. schrieb:>> Darum hier der 2. Vorschlag der viel besser passt>> Also Respekt für Deinen Enthusiasmus, aber: Der zweite Vorschlag sieht> am wenigsten schlimm aus, aber es ist das perfekte Beispiel, in dem> billiger Quelltext aussagekräftiger als ein Zustandsdiagramm ist.
Aber ich habe den Quelltext aus dem Diagramm erzeugt. Nicht andersrum.
Ich habe erst gezeichnet, dann Code geschrieben. Ich empfehle dieses
Vorgehen weiterhin.
> Und eigentlich wollte ich bei der Diskussion gar nicht in die> Einzelunterzustände hinabtauchen. Die habe ich im Griff. Du siehst ja,> wie einfach sie im Quelltext aussehen. In der Doku ist das eine einfache> Abhakliste. (Es sind die einfachsten aus der Reihe, aber die anderen> sind auch sehr linear - nur eben mit ein paar Wartezeiten und ein wenig> Synchronisierung.)
Es geht ja auch nicht um die Zustände selbst sondern um das ganze
System, und wie du deine Anforderung in eine SM gießen kannst. Es sind
und bleiben ja Beispiele, nur eben Beispiele welche sich etwas an deinen
realen Zuständen orientieren.
> Ich bin auch sehr glücklich darüber, dass sich die Einzel-Unterzustände> oder -Abläufe oder wasauchimmer sehr gut voneinander trennen lassen.> Lassen wir sie in Ruhe. Ihnen geht es gut.
Verstehe ich leider nicht. Wo siehst du "Einzel-Unterzustände"? Und wenn
es ihnen so gut gehen würde, hättest du keine Fragen.
> Es geht darum, in die Handhabung der übergeordneten Zustände etwas mehr> Ordnung hineinzubringen.
Aber genau das tut mein Beispiel. Es zeigt NUR Übergeordnete Zustände.
Weniger sollten es nicht werden. Wenn du die Anzahl reduzieren willst,
wirst deine SM nutz- und sinnlos.
Die Zustände hier haben ihren Sinn.
Versuche doch wenigstens mal den zu begreifen.
Johannes schrieb:> Deine Aufagbe als Entwickler ist es, das Problem zu verstehen und dann> zu sehen, ob, wo und wie eine sehr einfache State Machine das Problem> drastisch vereinfachen könnte. Das ist dann ziemlich häufig nicht die> State Machine, die die Problembeschreibung suggeriert.>> Alle generischen Tipps für SM sind hier schon irgendwo gefallen
Also: Welche anderen Maschinen sind denn für ähnliche Zwecke brauchbar?
Zustandsmaschine wohl nicht. Rube-Goldberg-Maschine ist im Moment
implementiert. Es ist ja nicht verkehrt, mehrere Lösungen für ähnliche
Probleme zu kennen.
Cyblord -. schrieb:> Wo siehst du "Einzel-Unterzustände"?
disabled_to_auto_feed und auto_feed_to_disabled sind
Einzel-Unterzustände. Niemand will sie. Sie werden nur
implementierungstechnisch benötigt, um zwischen den drei Hauptzuständen
zu wechseln. Aber sie sind okay, weil innendrin einfach.
Nur außenrum sind sie wie ein Ravensburger Puzzle.
Walter T. schrieb:> Cyblord -. schrieb:>> Wo siehst du "Einzel-Unterzustände"?>> disabled_to_auto_feed und auto_feed_to_disabled sind> Einzel-Unterzustände. Niemand will sie. Sie werden nur> implementierungstechnisch benötigt, um zwischen den drei Hauptzuständen> zu wechseln. Aber sie sind okay, weil einfach.
Es sind wichtige Zustände weil in diesen Zuständen die notwendigen
Abläufe für den Wechsel stattfindet. Alles was erledigt werden muss,
wird dort erledigt.
Für die SM sind sie absolut notwendig. Denn die SM muss wissen dass sie
hier warten muss und sie muss wissen in welchen Zustand sie nach
Abschluss wechseln muss.
> implementierungstechnisch benötigt
Diese Zustände werden schon für die Planung der SM benötigt. Sie sind
kein Implementierungsdetail oder notwendiges Übel.
Es geht nicht um Benutzer Ein-/Ausgaben.
Wobei du diese Zustände sogar direkt in Ausgaben umwandeln könntest.
Damit das klappt musst du deine Zustände etwas umwerfen. Daher auch mein
Tipp ganz am Anfang: Erst mal WIRKLICH gut über die Zustände nachdenken.
Welche gibt es WIRKLICH.
Was gefällt dir z.B. an meinen Zuständen jetzt nicht? Was passt für dich
nicht?
Ich finde es auch etwas befremdlich wenn Zustände in "gut" und
"schlecht" oder "einfach" eingeordnet werden.
Das sind einfach keine passenden Kategorien für so eine Planung.
Ein Zustand ist nicht einfach oder komplex. Vielleicht was du in diesem
Zustand tun willst. Aber genau das musst du getrennt sehen.
Peter D. schrieb:> So mache ich das auch. Die Statemaschine arbeitet so lange, bis> current_state == wanted_state. D.h. sie klettert alle Zwischenzustände> hoch bzw. runter und springt nicht wild umher.
Ich mach es auch so. Das ist nämlich genau die idempotente
Schnittstelle, die ich weiter oben erwähnt habe: Eine Sub-Komponente
bekommt ein Kommando, und klettert dort hin. Es spielt keine Rolle, ob
sie das Kommando einmal oder hundertmal bekommen hat. Der Endzustand
bleibt.
Die Subkomponente muss sich selbst drum kümmern, wie sie zum Ziel kommt.
Triviales Beispiel: Servomotor und Haltebremse. Beim Einschalten muss
erst die Lageregelung vom Servo aktiviert werden, dann die Haltebremse
geöffnet werden. Beim Ausschalten umgekehrt. Erst die Haltebremse
schießen, dann Lageregelung abschalten. Und überall gibt es Wartezeiten
dazwischen.
Jetzt kann man das in einer FSM machen. Dann bekommt man genau das
Problem, das für das einfache Ein- und Ausschalten des Systems,
bestehend aus Servo und Bremse, plötzlich mindestens vier Zustände in
einer FSM verwaltet werden müssen.
Viel zu aufwendig, schlecht wartbar, und das bei einem trivialen
Beispiel.
Ich baue daraus sieben FSM bzw Ketten:
- Bremse_öffnen: Ausgang setzen, warten, fertig.
- Bremse_schließen: Ausgang löschen, warten, fertig.
- Lageregelung_einschalten: Wild mit dem Servo kommunizieren, fertig.
- Lageregelung_ausschalten: Anders wild mit dem Servo kommunizieren,
fertig.
- Servo_an: Lageregelung_einschalten, Bremse_öffnen, fertig.
- Servo_aus: Bremse_schließen, Lageregelung_ausschalten, fertig.
- Master: Bei Event_x, Servo_an, Bei Event_y, Servo_aus.
So muss sich der "Master" nur darum kümmern, wann ein- oder
ausgeschaltet wird. Wie das gemacht wird, ist dieser (trivialen) FSM
egal. Die Subsysteme und deren Subsysteme müssen sich selbst drum
kümmern.
Und in der Realität sind gerade die meisten Wartezeiten keine festen
Wartezeiten, sondern Prädikate, dass eine bestimmte Bedingung mindestens
Zeit X gegeben ist bzw. war. Z.b. bei der Bremse bedeutet das, dass der
Timer für "Bremse ist zu" läuft, sobald die Bremse zu ist. Egal wer sie
geschlossen hat, und warum sie geschlossen wurde.
Mit dieser Technik bekomme ich auch komplexeste Systeme zur völligen
"Agilität", so dass der Benutzer wild drauf schalten und walten kann,
und sich das Ding möglichst schnell, und vor allem stets fehlerfrei, in
den gewünschten Zustand bewegt. Und die einzelnen Teilschritte sind fast
ausschließlich triviale "Vorwärts"-FSM oder Ketten, kaum mit
irgendwelchen Sprüngen. Alles leicht zu warten und validieren.
Walter T. schrieb:> Also: Welche anderen Maschinen sind denn für ähnliche Zwecke brauchbar?> Zustandsmaschine wohl nicht. Rube-Goldberg-Maschine ist im Moment> implementiert. Es ist ja nicht verkehrt, mehrere Lösungen für ähnliche> Probleme zu kennen.
Rube-Goldberg ist doch immer eine gute Lösung ;-)
Mal abgesehen von den Zeugs mit der Übergangstabelle wurde doch schon
eine sehr einfache State Machine herausisoliert:
disabled -> manual_feed_prepare -> manual_feed
disabled -> automatic_feed_prepare -> automatic_feed
Und zurück:
manual_feed -> disabled_prepare -> disabled
automatic_feed -> disabled_prepare -> disabled
Ich würde den Übergang von automatic_feed zu manual_feed und umgekehrt
weglassen wenn möglich, vorausgesetzt, das kann man auch über den
disabled Zustand durchführen. (Also automatic_feed -> disabled_prepare
-> disabled -> manual_feed_prepare -> manual_feed.)
Dafür brauchst du natürlich etwas übergeordnetes, einen
"automatic_request" könntest du aber auch als Trigger für manual_feed ->
disabled_prepare verwenden.
Die Prepare-Funktionen würde ich Kontextfrei anlegen, d.h. denen ist
egal von wo sie angesprungen wurden, die tun den jeweiligen Folgezustand
vorbereiten und schauen sich den sonstigen Zustand deiner Hardware an
was dazu notwendig ist. (von was eigentlich? Was hängt da dran?)
Das ändert natürlich auch die Taktung deiner SM und möglicherweise
benötigst du dafür untergeordnete State Machines. Das hängt jetzt ganz
stark davon ab, was deine sonstige Programmierumgebung so kann. (Läuft
die SM in einem Thread? Im Main Loop? Hast du Threads zur Verfügung?
Coroutinen?)
Das ist jetzt alles mit vielen Sternchen verbunden weil ich keine
zusammenhängende Beschreibung von deiner Problematik finden konnte.
Prinzipiell ist die Beschreibung "Deine Zustände AutoFeed und ManualFeed
benötigen eine nicht weiter spezifizierte Art von Vorbereitung" halt
recht stabil gegen Änderungen der Anforderungen, sprich du musst die SM
nicht bei jeder Änderung über den Haufen werfen.
Dafür musst du diese Vorbereitungen halt je nach Art/Umfang mit weiteren
Techniken umsetzen. Wie hier schon mal geschrieben wurde: Teile und
Herrsche
Johannes schrieb:> Mal abgesehen von den Zeugs mit der Übergangstabelle wurde doch schon> eine sehr einfache State Machine herausisoliert:>> disabled -> manual_feed_prepare -> manual_feed> disabled -> automatic_feed_prepare -> automatic_feed
Genau. Das ganze ist jetzt eigentlich mehr oder weniger klar und auch
recht einfach.
Ich sehe die Schmerzen des TO hier nicht wirklich.
Aber ich merke dass eigentlich jeder Vorschlag und jeder Tipp auf
Ablehnung stößt. Ich sehe auch nicht, dass der TO sich wirklich mal mit
den Vorschlägen beschäftigt. Sämtliche Änderungen sind dem TO zuwider.
Deshalb fange ich langsam an zu Zweifeln ob man dem TO überhaupt helfen
kann.
Wenn man die _prepare Zustände kontextfrei anlegt könnte man natürlich
auch direkt von manual_feed auf automatic_feed_prepare springen und
analog für automtic_feed. Dann ist es aber keine Option mehr (wie im
obigen Beispiel) sondern man muss es tatsächlich so durchziehen und
dokumentieren.
Ja so ganz weis ich auch nicht worauf der TO hinaus will. Oft ergibt
sich Vereinfachung über Betrachtung von Randbedingungen, wie z.B. die
Kontextfreiheit mit der ich mir die Zustände
manual_feed_prepare_from_disabled und
manual_feed_prepare_from_automatic_feed spare und einen gemeinsamen
Zustand draus machen kann. Ganz allgemein hat man dann den Kopf freier
weil man sich drauf verlassen kann, dass den _prepare Zuständen die
Geschichte egal ist.
Das hat aber alles nichts mehr mit der SM an sich zu tun sondern mit den
sonstigen Aspekten der Entwicklung die hier schon mehrfach angesprochen
wurden.
Cyblord -. schrieb:> Ich sehe die Schmerzen des TO hier nicht wirklich.
Das entspricht dem Ansatz, mit dem Blick durchs Mikroskop im
Zellkulturlabor zu sagen: "Ich sehe hier keine Katze."
Stimmt. Die Katze sieht man mit dem Blick durchs Mikroskop nicht. Katze
ist Makro-Level. Wenn man mal das eine Auge vom Mikroskop wegnimmt und
das andere öffnet, kann man sehen, wie die Katze durch die Regale
schleicht und die Proben herunterwirft.
Es geht nicht darum, Mikro-Zustandsmaschinen ordentlich zu bekommen. Die
gehen. Sie sind einfach und ordentlich. Nur sind es viele. Es geht
darum, den großen Zustandsmaschinenanstupsomat irgendwie ordentlicher zu
bekommen.
Der aus den drei Soll-Zuständen über die sechs Übergangszustände zu den
drei Ziel-Zuständen kommt. Oder aus den fünf Soll-Zuständen über die
zwanzig Übergangszustände zu den fünf Zielzuständen kommt. Oder aus den
fünf Soll-Zuständen über die achtzehn erlaubten Übergangszustände zu den
fünf Zielzuständen kommt.
Ein klassisches n^2-Komplexitätsproblem. Für einige gibt es bewährte
Lösungen. Als Nicht-Informatiker kennt man nicht alle. Und ich wette,
als Informatiker auch nicht.
Walter T. schrieb:> Der aus den drei Soll-Zuständen über die sechs Übergänge zu den drei> Ziel-Zuständen kommt. Oder aus den fünf Soll-Zuständen über die zwanzig> Übergänge zu den fünf Zielzuständen kommt. Oder aus den fünf> Soll-Zuständen über die achtzehn erlaubten Übergänge zu den fünf> Zielzuständen kommt.
Weg mit den Übergängen aus dem "Zustandsmaschinenanstupsomat":
Die "Ziel-Zustandmaschine" schaut sich den aktuellen Zustand des Systems
selbst an, und führt die erforderlichen Schritte aus. Das Sub-System
kümmert sich selbst drum.
Du hast es weiter oben selbst geschrieben, einen "diskreten Regler" oder
so ähnlich. Genau so mach ich es nämlich auch. Nur dass es nicht einen
"Regler" gibt, sonder viele. Jeder dieser "Regler" kann irgendwas, und
die Schritte für den Zielzustände, die diese "Regler" erreichen wollen,
sind trivial. So wie in Deinem Beispiel-Code.
Experte schrieb:> Die "Ziel-Zustandmaschine" schaut sich den aktuellen Zustand des Systems> selbst an, und führt die erforderlichen Schritte aus.
Also die kleinen Zustandsmaschinen haben nicht nur einen Ausgang,
sondern jede führt die Umschaltung zu mehreren Zielzuständen selbst
durch?
Walter T. schrieb:> Es geht nicht darum, Mikro-Zustandsmaschinen ordentlich zu bekommen. Die> gehen. Sie sind einfach und ordentlich. Nur sind es viele. Es geht> darum, den großen Zustandsmaschinenanstupsomat irgendwie ordentlicher zu> bekommen.>> Der aus den drei Soll-Zuständen über die sechs Übergangszustände zu den> drei Ziel-Zuständen kommt. Oder aus den fünf Soll-Zuständen über die> zwanzig Übergangszustände zu den fünf Zielzuständen kommt. Oder aus den> fünf Soll-Zuständen über die achtzehn erlaubten Übergangszustände zu den> fünf Zielzuständen kommt.
Es wurde doch schon mehrfach geschrieben, dass es dafür keine Schema-F
Lösung gibt. Es hängt immer vom Detailproblem ab und in 2 Situationen
kommen sicherlich 2 verschiedene Ansätze dafür heraus.
Dafür braucht man natürlich einen gut sortierten Werkzeugkasten an
Lösungskonzepten der nicht nur aus dem Werkzeug "State-Machine" besteht.
Die Dinger bieten für eine gewisse Problemkategorie gute
Lösungsmöglichkeiten, aber abseits davon nimmt man lieber was anderes.
Johannes schrieb:> Dafür braucht man natürlich einen gut sortierten Werkzeugkasten an> Lösungskonzepten der nicht nur aus dem Werkzeug "State-Machine" besteht.
Was hast Du denn in Deinem Werkzeugkasten?
Walter T. schrieb:> Also die kleinen Zustandsmaschinen haben nicht nur einen Ausgang,
Ja, sie haben auch "Eingänge". D.h., diese Mini-Zustandsmaschinen
arbeiten eigentlich einfach nur ein Checkliste ab. Punkte die auf der
Checkliste schon erfüllt sind, müssen nicht mehr angestoßen werden.
Punkte die noch nicht erfüllt sind, werden angestoßen, und es wird
gewartet bis das Subsystem meldet, dass der angestoßene Punkt erfüllt
ist.
Also gibt das nichts anderes als eine Liste von "Checks" die ausgeführt
werden sollen. Für jeden Check-Punkt wird meistens nur gemacht:
Punkt X erfüllt? Nein --> X anstoßen, und auf X warten.
Gelegentlich gibt es in dieser Check-Liste Punkte, die von Bedingungen
abhängen. Also z.B.:
Wenn Bedingung A, dann:
Punkt X erfüllt? Nein --> X anstoßen und auf X warten.
Wenn nicht, dann:
Punkt Y erfüllt? Nein --> Y anstoßen und auf Y warten.
Und nun kommt meine rumreiterei auf "Idempotente Schnittstellen": Wenn
nämlich "X anstoßen" idempotent ist, spielt es keine Rolle, wie oft X
angestoßen wurde. Dann wird das abarbeiten der Checkliste trivial:
- X anstoßen
- auf X warten
- wenn Bedingung A:
- Y anstoßen
- auf Y warten
ansonsten:
- Z anstoßen
- auf Z warten
Wenn Dinge parallel laufen sollen, wird daraus:
- X anstoßen
- Y anstoßen
- auf X warten
- auf Y warten
usw.
Walter T. schrieb:> Es geht nicht darum, Mikro-Zustandsmaschinen ordentlich zu bekommen. Die> gehen. Sie sind einfach und ordentlich. Nur sind es viele. Es geht> darum, den großen Zustandsmaschinenanstupsomat irgendwie ordentlicher zu> bekommen.
Ich habe aber den großen Automaten betrachtet. Nichts mit Mikro. Und ich
habe dir genau aufgezeigt wie du diesen ordentlich bekommst. Du nimmst
aber Hilfe grundsätzlich nicht an.
> Ein klassisches n^2-Komplexitätsproblem. Für einige gibt es bewährte> Lösungen. Als Nicht-Informatiker kennt man nicht alle. Und ich wette,> als Informatiker auch nicht.
Mit Algorithmen und Komplexität hat das Problem wirklich wenig zu tun.
Hier geht es um Software-Pattern.
Hast du dir selbst mal die Frage gestellt welche Art von Antwort dir
hier tatsächliche helfen würde? Gibt es diese überhaupt? Ich bezweifle
das.
Walter T. schrieb:> Johannes schrieb:>> Dafür braucht man natürlich einen gut sortierten Werkzeugkasten an>> Lösungskonzepten der nicht nur aus dem Werkzeug "State-Machine" besteht.>> Was hast Du denn in Deinem Werkzeugkasten?https://de.wikipedia.org/wiki/Entwurfsmuster
Aber es ist halt so, mit dem Werkzeugkasten alleine baut man kein Haus
und kein Flugzeug. Das sollte klar sein. Nur die Kombination aus Können,
Erfahrung und dem richtigen Werkzeug führt zum Ziel.
So ist es. Alle diese Muster sind wenig wert wenn man nicht ihre
Fähigkeiten und Limitierungen kennt, aber diese formalen Werke dazu sind
sicher ein guter Einstieg. Dazu kommen dann später noch Erfahrung,
Übertragungsleistung und Dinge wie z.B. strukturelle und
architektonische Betrachtungen die sich eher auf einer Metaebene
abspielen.
Für den speziellen Fall SM auf Mikrocontroller in C könnte man sich z.B.
mit Protothreads eine Menge Freiheit bei der Umsetzung der einzelnen
Zustände einkaufen.
Protothreads muss man immer mit der Kneifzange anfassen weil die Dinger
schnell unübersichtlich werden, aber wenn man es diszipliniert anwendet
kann man damit gut viele Zustände einer SM in eine einzelne Methode
reduzieren.
Hängt aber wie schon gesagt von den Rahmenbedingungen ab, z.B. Taktung
der SM.
Johannes schrieb:> Protothreads muss man immer mit der Kneifzange
Oh ja, ich hatte sie bis gerade erfolgreich aus meinem Gedächtnis
verbannt.
Falls jemand mehr über Protohtreads erfahren möchte, mag er vielleicht
meinen Aufsatz dazu lesen, den ich vor einigen Jahren schrieb:
http://stefanfrings.de/net_io/protosockets.html
Ich finde nur zwei Design Pattern, die zum Thema passen:
state-pattern, was schon die ganze Zeit diskutiert wird, und chain of
responsibility, was ungefähr Betrag #6774272 entspricht.
Walter T. schrieb:> Ich finde nur zwei Design Pattern, die zum Thema passen:>> state-pattern, was schon die ganze Zeit diskutiert wird, und chain of> responsibility, was ungefähr Betrag #6774272 entspricht.
Und wo ist das Problem dabei? Denkst du wenn du jetzt 10 Pattern hättest
würde dir das irgendwie weiter helfen? Du kannst doch keins davon
ordentlich umsetzen.
Cyblord -. schrieb:> Du kannst doch keins davon ordentlich umsetzen.
Wie kommst du zu dieser Einschätzung? Sind alle blöd, nur du nicht?
Lösungsansätze zu diskutieren und vergleichen ist genau der richtige
weg, um sie später sinnvoll einzusetzen.
Stefan ⛄ F. schrieb:> Cyblord -. schrieb:>> Du kannst doch keins davon ordentlich umsetzen.>> Wie kommst du zu dieser Einschätzung? Sind alle blöd, nur du nicht?
Ich komme dazu weil ich hier jetzt einige Zeit mit ihm "diskutiert"
habe.
Der TO wartet auf ein Wunder, irgendein Werkzeug, irgendeine Idee die
seine Problem sofort löst.
Sowas gibt es nicht.
Er muss selbst den Skill dazu haben. Dieser fehlt ganz offensichtlich.
Es wurde jetzt sehr detailliert aufgezeigt wie sein Problem angegangen
werden kann. Er kann davon nichts mitnehmen, nichts umsetzen. Ich lese
nur Ablehnung und Unverständnis. Daran werden auch 20 Pattern nichts
ändern.
Ich lese heraus, dass er noch Zweifel hat und auf eine für ihn
elegantere Lösung hofft. Der ganze Thread sagt nichts darüber aus, ob er
die Aufgabe vernünftig umsetzen kann.
Stefan ⛄ F. schrieb:> Ich lese heraus, dass er noch Zweifel hat und auf eine für ihn> elegantere Lösung hofft. Der ganze Thread sagt nichts darüber aus, ob er> die Aufgabe vernünftig umsetzen kann.
Tja ich finde schon. Aber du darfst hier gerne eine andere Meinung
haben. Und inzwischen kannst du ihm ja weiter helfen. Ich habe
inzwischen das Handtuch geworfen. Obwohl ich einiges an Aufwand
investiert habe.
Ich beschäftige mich tagtäglich mit dem Entwurf von SW-Architekturen und
damit sie anderen zu erklären und zu rechtfertigen und die Umsetzung zu
überwachen. Auch innerhalb großen Internationalen Teams. Darum habe ich
schon ein wenig Erfahrung wie gut oder schlecht solche eher abstrakten
Gebilde in der Realität umgesetzt werden können. Und von wem.
Ich lese da auch ein wenig mehr als Zweifel. Hier geben Leute freiwillig
Tipps; wenn man eine Frage stellt und viele Anregungen und Tipps
bekommt, sollte man sich doch auch mit den Vorschlägen genauer
beschäftigen.
Imho ist es doch genau das, was man als Entwickler häufiger sieht. Leute
"von außen" empfinden Entwicklung als lästige Arbeit die halt irgendwie
getan werden muss, aber wollen sich nicht mit den Schwierigkeiten von
guter Software beschäftigen. Es soll halt einfach irgendwie tun.
Die Erkenntnis, dass Software halt doch ein wenig komplexer ist, stört
solche Leute dann häufig einfach nur. Ohne Fleiß kein Preis, wer sich
nicht damit beschäftigt wird halt auch nicht besser.
Für viele kommt halt auch noch der Umstand hinzu, dass Software mehr als
viele andere Bereiche von persönlicher Bereitschaft lebt, sich mit dem
Fachgebiet eigenständig auseinander zu setzen.
Johannes schrieb:> [...] wenn man eine Frage stellt und viele Anregungen und Tipps> bekommt, sollte man sich doch auch mit den Vorschlägen genauer> beschäftigen.
Die echten Vorschläge lassen sich an einer Hand abzählen:
- UML: Super für große Teams mit Anforderungsmanagement und Design
Goals und Quality Gates. Bring einen der tatsächlichen Implementierung
kein bischen näher, wenn man nicht schon vorher weiß, wie es geht.
- C-enums: Vorteilhaft wenn es geht. Kommt auf meinen Merkblock für
Begründungen, warum ich mein nächstes Projekt versuchsweise in C++
starten werde.
- C++ State machine Klasse(?): Am Thema vorbei. Hilft dem eigentlichen
Problem -Übersichtlichkeit- kein bischen weiter. Genausogut könnte man
über State Machines in ADA auf einem Ariane-Computer philosophieren.
Keine echten Vorschläge, aber lesenswert: Die Ausführungen von PeDa. Ich
kann sie hier zwar nicht anwenden, aber die Diskussion lieferte eine
perfekte Checkliste, unter welchen Randbedingen man mit einer
Zustandsmaschine unkompliziert zum Ziel kommt. Diese Liste bin ich
implizit schon vorher durchgegangen, aber eben nicht systematisch und
nicht explizit ausformuliert. Jetzt habe ich sie ausformuliert für die
Doku. Schön. Lesenswert. Eigene praktische Lösungen zeigen ist sowieso
öfter lesenswert als Vorschläge à la "das mußt Du so machen!"
Egon D. hat längere Ausführung zum Allgemeinen gemacht. Mir hat das
wenig weitergeholfen, weil das ungefähr dem klassischen Literaturwissen
zu Zustandsmaschinen entspricht, aber offensichtlich fanden andere das
Lesenswert. Auch schön. Ich habe hier keinen Alleinlesensanspruch und
vergebe auch keine Bewertungen.
Ich nehme nicht an, das Cyblord, der das komplette V-Modell über uns
ergießen will, es nicht hilfreich meint. Es geht nur komplett an der
Frage vorbei. Wir landen immer und immer wieder im gleichen Zyklus: "Du
musst mal Grundlagen lernen!" -> "Welche Grundlagen fehlen denn?" ->
"[Wissen, das jeder sofort bei Wikipedia findet]" -> "Wie hilft mir das
weiter?" -> "Dir fehlen Grundlagen!". Dieser logische Automat ist in
einer Endlosschleife gefangen. Ich kann den Automaten nicht terminieren,
weil ich nicht weiß, nach welchem Anwenderwissen ich fragen könnte, das
ich noch nicht kenne. Er kann nicht terminieren, weil er den x-ten
Verweise auf Wikipedia-Grundwissen für hilfreich hält. Warten wir, bis
ein Timeout oder der Watchdog zuschlägt.
Johannes schrieb:> [...] dass Software mehr als> viele andere Bereiche von persönlicher Bereitschaft lebt, sich mit dem> Fachgebiet eigenständig auseinander zu setzen.
Also bitte. Das ist -mit Verlaub- wieder eine wertarme Aussage. "Das
Fachgebiet" ist riesig. Es soll sogar Leute geben, die das mehrere Jahre
lang studieren. Aus einer solchen Aussage kann nur durch eine solide
Eingrenzung Wert entstehen. Eine wertvolle Aussage ist immer konkret,
(z.B. Verweise auf einen konkreten Blog-Beitrag/konkretes Buch/konkreten
Teil eines Open Source Projekts etc.).
Oder der Verweis auf die Design Patterns der GoF. Die sollten allgemein
bekannt sein. Ohne Hinweis, welches Muster jetzt gemeint ist und wie das
auf den genannten Fall bezogen werden kann, ist das ähnlich hilfreich
wie der Verweis auf Google oder den Duden. Zumindest meine Ausgabe der
"Design Patterns" ist sogar dicker als mein alter Duden.
Ich habe mal einen netten Satz gelesen:
"There are four difficult things in computer scrience: n+1 problems,
caching and naming things."
Diese Aussage stimmt. Dingen einen guten Namen geben macht oft den
Unterschied, ob man sie elegant oder umständlich angeht - obwohl die
Namen für den Computer völlig egal sind. Und auch bei Namen kommt es
darauf an, dass sie so konkret wie nötig sind und nicht nur so abstrakt
wie möglich.
Walter T. schrieb:> Ich nehme nicht an, das Cyblord, der das komplette V-Modell über uns> ergießen will, es nicht hilfreich meint. Es geht nur komplett an der> Frage vorbei.
Du hast leider echt nichts kapiert. V-Modell? Ich habe dir einen
Vorschlag für deine SM gemacht. Nicht mehr und nicht weniger.
Sorry du bist echt merkbefreit. Dir kann man nicht helfen. Sogar noch
schlimmer: Dummfrech. Kann nix, aber Klappe offen und über alles
arrogant weggehen.
Frickel bitte dein Zeug selbst.
Walter T. schrieb:> Ich kann den Automaten nicht terminieren, weil ich> nicht weiß, nach welchem Anwenderwissen ich fragen> könnte, das ich noch nicht kenne.
Das ist der Punkt: Es geht nicht um KENNEN -- im Sinne
von "habe ich schon mal gehört und klingt logisch", es
geht um VERSTANDEN HABEN !
> Ich habe mal einen netten Satz gelesen:> "There are four difficult things in computer scrience:> n+1 problems, caching and naming things."> Diese Aussage stimmt.
Naja.
Vielleicht sollten sich ausgerechnet die C-Hanseln damit
zurückhalten, anderen gute Ratschläge bezüglich der Wahl
von Namen zu geben, und erstmal vor ihrer eigenen Türe
kehren. Schlechte Beispiele gern auf Anfrage.
> Dingen einen guten Namen geben macht oft den Unterschied,> ob man sie elegant oder umständlich angeht
Der Prototyp des modernen Programmierers: KORREKTHEIT
ist optional -- Hauptsache, es ist ELEGANT !
> Und auch bei Namen kommt es darauf an, dass sie so> konkret wie nötig sind und nicht nur so abstrakt> wie möglich.
Vor allem kommt es darauf an, dass die GEDANKEN , die
mit den Namen transportiert werden sollen, RICHTIG sind.
Experte schrieb:> Peter D. schrieb:>> So mache ich das auch. Die Statemaschine arbeitet>> so lange, bis current_state == wanted_state. D.h.>> sie klettert alle Zwischenzustände hoch bzw. runter>> und springt nicht wild umher.>> Ich mach es auch so. Das ist nämlich genau die> idempotente Schnittstelle, die ich weiter oben erwähnt> habe: Eine Sub-Komponente bekommt ein Kommando, und> klettert dort hin. Es spielt keine Rolle, ob sie das> Kommando einmal oder hundertmal bekommen hat. Der> Endzustand bleibt.
Hmm. Bemerkenswert. Man kann also auch unter dem scheinbar
völlig eindeutigen Begriff "Statemachine" unterschiedliche
Dinge verstehen :-/
Eine "Statemachine" bekommt keine Kommandos, sondern
Eingangssignale, und diese können keinen beliebigen
Zustand als Zielzustand beschreiben, sondern nur einen,
der (direkt) durch eine abgehende Kante mit dem aktuellen
Zustand verbunden ist.
Das soll jetzt nicht heißen, dass die Idee oben schlecht
ist -- ich finde sie im Gegenteil witzig. Man sollte
das nur vielleicht nicht gerade "Statemachine" nennen,
sondern vielleicht... nun... ich schlage mal den ganz
abenteuerlichen Namen "Kommando-Interpreter" vor...
Egon D. schrieb:> Vielleicht sollten sich ausgerechnet die C-Hanseln damit> zurückhalten, anderen gute Ratschläge bezüglich der Wahl> von Namen zu geben, und erstmal vor ihrer eigenen Türe> kehren.
Was sind denn C-Hanseln?
Falls du damit Menschen meinst, die in C programmieren: Die meisten
haben sich diese Programmiersprache nicht freiwillig ausgesucht, und
designet wurde sie vor 50 Jahren von Menschen die bereits ausgestorben
sind.
Erschaffe du mal eine Programmiersprache, die nach so vielen Jahren ohne
dein Zutun immer noch auf der ganzen Welt benutzt wird. Dann steht es
dir zu, solche Ausdrücke verwenden.
> Schlechte Beispiele gern auf Anfrage.
Findet man in jeder Sprache, das ist keine Kunst.
Stefan ⛄ F. schrieb:> Erschaffe du mal eine Programmiersprache, die nach so vielen Jahren ohne> dein Zutun immer noch auf der ganzen Welt benutzt wird. Dann steht es> dir zu, solche Ausdrücke verwenden.
Bitte nicht! Nicht noch ein python!
Stefan ⛄ F. schrieb:> Was sind denn C-Hanseln?>> Falls du damit Menschen meinst, die in C programmieren: Die meisten> haben sich diese Programmiersprache nicht freiwillig ausgesucht,
Walter hat.
Oliver
Stefan ⛄ F. schrieb:> Falls du damit Menschen meinst, die in C programmieren: Die meisten> haben sich diese Programmiersprache nicht freiwillig ausgesucht, und> designet wurde sie vor 50 Jahren von Menschen die bereits ausgestorben> sind.
Welche (sinnvolle) Alternative hätte es denn vor 20 Jahren gegeben, als
ich damit anfing?
Stefan ⛄ F. schrieb:> Sorry, ich> bin nicht religiös.
Dein Problem.
Du bist aber doch lang genug dabei, und das in jedem Thread. Da müsstest
du wissen, daß das Walter hier schon gefühlte zweihundertdrölf ähnliche
Threads gestartet hat, immer ähnlichen Problemstellungen. Und ja, der
programmiert in C aus Spaß und freiwillig.
Oliver
Oliver S. schrieb:> Und ja, der> programmiert in C aus Spaß und freiwillig.
Ahh, so ein Schlingel also.
Walter T. schrieb:> enum ctrl_mode_e mode = ctrl_mode_auto_feed_to_disabled;
So was hier z.B. macht mir extrem wenig Spaß beim Lesen.
Warum benutzt Du keinen TypeDef?
Wo wird eigentlich im Jahr 2021 immer noch Systems Hungarian Notation
(typ als Teil des Variablennamens
1
enumbla_e;
gelehrt? Das ist seit mindestens 20 Jahren out und war nie nützlich.
Sei bitte möglichst sparsam mit wiederholungen. Statt
1
enumctrl_mode_e
2
{
3
ctrl_mode_disabled,
4
ctrl_mode_manual_feed,
5
ctrl_mode_auto_feed,
6
}
Nutze
1
enumstates
2
{
3
disabled,
4
feed,
5
auto_feed
6
}
Dann spare Dir die vielen if-else oder switch-case Konstrukte, wenn Du
mehr als vier Zustände hast, sondern mache eine Zustandsübergangstabelle
bei der für jeden State eine Funktionszeiger hinterlegt ist, der die
Zustandsfunktion darstellt. Dann brauchst Du nur eine Zustandsvariable
vom Typ states, die dann durch Ereignisse gesetzt wird (Interupt, Timer,
etc). Die eigentlich control loop ist dann nur noch der Aufruf in die
Tabelle.
Egon D. schrieb:> Eine "Statemachine" bekommt keine Kommandos, sondern> Eingangssignale, und diese können keinen beliebigen> Zustand als Zielzustand beschreiben, sondern nur einen,> der (direkt) durch eine abgehende Kante mit dem aktuellen> Zustand verbunden ist.
Nunja, offensichtlich fehlen Dir die geistigen Fähigkeiten um zu
abstrahieren, dass Kommandos, Eingangssignale und sonstige Informationen
die auf eine FSM direkt oder indirekt einwirken ganz ordinäre Events
darstellen.
Eine FSM die in einem X-beliebigen Zustand rum-idelt kann sehr wohl auf
ein Kommando, Verzeihung, für Dich "Event", reagieren und den ersten
Zustand annehmen der nur Teil einer Kette weiterer, sequenzieller
Zustände ist, an deren Ende das Ergebnis des ausgeführten Kommandos,
Verzeihung, für Dich "Zustand", erreicht ist, der dem gewünschten
Ergebnis des FSM-Entwicklers entspricht.
Alternativ kannst Du mir ja die Stelle in der Literatur raus suchen, in
der beschrieben ist, dass bei einem bestimmten Event am Ende eine FSM
nicht einen bestimmten Ziel-Zustand erreichen darf...
Ansonsten hast Du hier noch nicht viel beigetragen, außer Benutzer einer
Programmiersprache als "Hansel" zu diffamieren. Dass Du Dich als
überlegener SPS-Programmierer siehst, hast Du in der Vergangenheit in
diesem Forum schon zu genüge postuliert.
asdf schrieb:> Nutze enum states> {> disabled,> feed,> auto_feed> }
Über die Namen bin ich auch nicht glücklich. Aber meines Wissens nach
müssen sie in allen verwendeten Header-Kombinationen eindeutig sein, und
die "schönen" Namen wie "enabled" und "disabled" finden ihren Platz in
mehreren Kontexten. Andererseits ist es ja schön, wenn der Compiler
darauf achtet, dass in einer switch-case-Umgebung auch wirklich alle
Fälle abgearbeitet werden. Wahrscheinlich ist mit C++-Enums alles ein
wenig schöner.
Über den Postfix _e für enums lässt sich streiten. EmBitz zeigt structs
und enums übersichtlich in einer Liste an - Typedefs nicht. Deswegen ist
es in dieser einen Entwicklungsumgebung mit den Postfixen ein bischen
übersichtlicher.
Walter T. schrieb:> Aber meines Wissens nach> müssen sie in allen verwendeten Header-Kombinationen eindeutig sein, und> die "schönen" Namen wie "enabled" und "disabled" finden ihren Platz in> mehreren Kontexten.
... deswegen wurde ganz zu Beginn schon mal die enum class vorgestellt.
Dann bleibt der Namespace sauber.
Muss man das noch mal weiter ausführen oder reicht dir der Suchbegriff
"enum class" (auch in diesem Thread)?
STK500-Besitzer schrieb:> Welche (sinnvolle) Alternative hätte es denn vor 20 Jahren gegeben, als> ich damit anfing?
Man muss nicht unbedingt 20 Jahre lang an dem festhalten, was man früher
mal gelernt hat. Wenn doch, dann macht man es wohl freiwillig und
absichtlich. Ich habe nichts dagegen.
noiasca schrieb:> ... deswegen wurde ganz zu Beginn schon mal die enum class vorgestellt.> Dann bleibt der Namespace sauber
Den namespace sauber zu halten ist sehr wichtig, denn in C gibt es nur
einen. Leider sind da C++ -enum-classes nur begrenzt hilfreich, aber wie
ich bereits zweimal in diesem Thread schrieb: Bei meinem ersten Projekt
in C++ werde ich wohl davon Gebrauch machen.
Walter T. schrieb:> asdf schrieb:>> Nutze enum states>> {>> disabled,>> feed,>> auto_feed>> }>> Über die Namen bin ich auch nicht glücklich. Aber meines Wissens nach> müssen sie in allen verwendeten Header-Kombinationen eindeutig sein, und> die "schönen" Namen wie "enabled" und "disabled" finden ihren Platz in> mehreren Kontexten. Andererseits ist es ja schön, wenn der Compiler> darauf achtet, dass in einer switch-case-Umgebung auch wirklich alle> Fälle abgearbeitet werden. Wahrscheinlich ist mit C++-Enums alles ein> wenig schöner.>> Über den Postfix _e für enums lässt sich streiten. EmBitz zeigt structs> und enums übersichtlich in einer Liste an - Typedefs nicht. Deswegen ist> es in dieser einen Entwicklungsumgebung mit den Postfixen ein bischen> übersichtlicher.
Ein enum sollte seine "Umgebung" aber direkt sichtbar machen:
enums für States würde ich derart machen.
Stefan ⛄ F. schrieb:> Egon D. schrieb:>> Vielleicht sollten sich ausgerechnet die C-Hanseln damit>> zurückhalten, anderen gute Ratschläge bezüglich der Wahl>> von Namen zu geben, und erstmal vor ihrer eigenen Türe>> kehren.>> Was sind denn C-Hanseln?
Leute, die diesen Spruch...
1
"There are four difficult things in computer scrience:
2
n+1 problems, caching and naming things."
...zitieren und gleichzeitig völlig blind für die
Selbstironie sind, die er enthält.
Ich habe gerade darüber nachgedacht, dass den TE womöglich jemand dafür
bezahlt Code zu schreiben. Flasht einen weg.
Mein Kopf bewegt sich immer noch hin und her. Unglaublich.
Experte schrieb:> Egon D. schrieb:>> Eine "Statemachine" bekommt keine Kommandos, sondern>> Eingangssignale, und diese können keinen beliebigen>> Zustand als Zielzustand beschreiben, sondern nur>> einen, der (direkt) durch eine abgehende Kante mit>> dem aktuellen Zustand verbunden ist.>> Nunja, offensichtlich fehlen Dir die geistigen Fähigkeiten
Beschränke Deine Äußerungen bitte auf das Sachthema.
> Eine FSM die in einem X-beliebigen Zustand rum-idelt> kann sehr wohl [...]
Es geht mir nicht darum, was die FSM kann -- es geht
mir darum, dass ich Peter (und zunächst auch Dich)
nicht verstanden habe, weil ihr den allgemeinen Begriff
"statemachine" für einen endlichen Automaten mit äußerst
spezieller Struktur verwendet habt.
Kann man machen -- sollte man aber mit deutlichen
Hinweisen versehen, andernfalls passiert das, was hier
eingetreten ist: Man wird missverstanden.
> Alternativ kannst Du mir ja die Stelle in der Literatur> raus suchen, in der beschrieben ist, dass bei einem> bestimmten Event am Ende eine FSM nicht einen bestimmten> Ziel-Zustand erreichen darf...
Wozu?
Ich hatte schon in dem Beitrag, auf den Du geantwortet
hast, das beschrieben, was ich mir wünsche:
>> Das soll jetzt nicht heißen, dass die Idee oben schlecht>> ist -- ich finde sie im Gegenteil witzig. Man sollte>> das nur vielleicht nicht gerade "Statemachine" nennen,>> sondern vielleicht... nun... ich schlage mal den ganz>> abenteuerlichen Namen "Kommando-Interpreter" vor...
Cyblord -. schrieb:> Ich habe gerade darüber nachgedacht, dass den TE> womöglich jemand dafür bezahlt Code zu schreiben.> Flasht einen weg.Mein Kopf bewegt sich immer noch> hin und her. Unglaublich.
Wieso?
C ist doch "ganz einfach", das kann man sich doch
innerhalb von zwei Wochen "learning by doing"
aneignen.
Oliver S. schrieb:> Stefan ⛄ F. schrieb:>> Was sind denn C-Hanseln?>>>> Falls du damit Menschen meinst, die in C programmieren:>> Die meisten haben sich diese Programmiersprache nicht>> freiwillig ausgesucht,>> Walter hat.
Und?!
Was hat "freiwillig oder unfreiwillig" damit zu tun,
dass das Finden guter Bezeichnungen in der Regel das
sichere Beherrschen des abstrakten Konzeptes zur
Voraussetzung hat?
Rainer V. schrieb:> Antwort von Tochter oder Sohn des Informatikers auf die Frage , wieviel> Finger hast du? : 9 !> Gruß
Sorry der Witz ist falsch erzählt. Weil eine ANZAHL auch in C korrekt
angegeben wird. Ein Array mit 10 Elementen hat 10 Elemente.
Aber wenn ein Informatiker in den 3. Stock will drückt er im Aufzug die
2. So geht das.
Cyblord -. schrieb:> Ich habe gerade darüber nachgedacht, dass den TE womöglich jemand dafür> bezahlt Code zu schreiben. Flasht einen weg.> Mein Kopf bewegt sich immer noch hin und her. Unglaublich.
Wenn es Dich beruhigt: Ich habe meinen aktuellen Job zwar unter anderem
deshalb bekommen, weil ich behauptet habe, mehrere Programmiersprachen
und -Umgebungen zu beherrschen, muss aber zum Glück nicht selbst
programmieren.
Rainer V. schrieb:> Cyblord -. schrieb:>> Ein Array mit 10 Elementen hat 10 Elemente.>> jaja, braucht aber nur 9 Zahlen...
Um die Zeit schon wieder voll bis oben hin?
Cyblord -. schrieb:> Aber wenn ein Informatiker in den 3. Stock will drückt er im Aufzug die> 2. So geht das.
Verstehe ich nicht. Das Haus beginn mit dem Erdgeschoss (quasi der 0.
Stock).
Egon D. schrieb:>> Ich kann den Automaten nicht terminieren, weil ich>> nicht weiß, nach welchem Anwenderwissen ich fragen>> könnte, das ich noch nicht kenne.>> Das ist der Punkt: Es geht nicht um KENNEN -- im Sinne> von "habe ich schon mal gehört und klingt logisch", es> geht um VERSTANDEN HABEN !
Du musst zugeben: Sachen verstanden zu haben, von denen man noch nie
gehört hat, ist etwas viel verlangt.
Egon D. schrieb:> Leute, die diesen Spruch..."There are four difficult things in computer> scrience:> n+1 problems, caching and naming things."> ...zitieren und gleichzeitig völlig blind für die> Selbstironie sind, die er enthält.
Klar. Witze, die man nicht verstanden hat, kann man sich ja meist auch
sehr gut merken.
Ich weiss nicht, genau, welches Menschenbild ihr habt. Aber ich weiß,
dass ich es nicht genauer wissen will.
Cyblord -. schrieb:> Ich habe gerade darüber nachgedacht, dass den TE womöglich jemand> dafür> bezahlt Code zu schreiben. Flasht einen weg.> Mein Kopf bewegt sich immer noch hin und her. Unglaublich.
Och ich seh das entspannt. Der Faden hier zeigt mal wieder, dass
Softwareentwicklung eben doch eine halbwegs komplexe Arbeit ist die sich
nicht einfach mechanisiert abwickeln lässt. Tausende Bachelor die
Informatik machen weil sich damit gut Geld verdienen lässt werden daran
nichts ändern.
Andere haben keinen so sicheren Arbeitsplatz.
Johannes schrieb:> Och ich seh das entspannt. Der Faden hier zeigt mal wieder, dass> Softwareentwicklung eben doch eine halbwegs komplexe Arbeit ist die sich> nicht einfach mechanisiert abwickeln lässt.
Ja mir kommt das hier auch wie ein Paradebeispiel für "E-Techniker als
Programmierer" vor. Auf jeden Fall Quereinsteiger. Da immer noch
garniert mit Seitenhieben auf Informatiker.
Und ja du hast recht, man sieht sehr schön was passiert wenn man es halt
einfach nicht kann, aber denkt man kann es weil man den Syntax so
halbwegs zusammenkloppen kann.
Für ein Blinky reicht das, für echte Probleme dann schon nicht mehr.
Ich finde besonders die Kombination aus "kann es nicht und versteht es
nicht" und diesem arroganten Auftreten echt interessant. Evt. hat er den
Mund im VG etwas zu voll genommen und muss jetzt doch an den Code an. So
was in der Richtung schrieb er ja auch. Da sollte man dann schon etwas
bescheidener auftreten, aber seine Klappe hat ihn wohl erst in diese
Situation gebracht.
Cyblord -. schrieb:> Ja mir kommt das hier auch wie ein Paradebeispiel für "E-Techniker als> Programmierer" vor.
Ich bin kein E-Techniker.
Cyblord -. schrieb:> [...] und muss jetzt doch an den Code an. So> was in der Richtung schrieb er ja auch.
Es ist nicht peinlich, nicht alle Richtungen des Ingenieurwesens zu
kennen. Wilde Behauptungen als Gewissheit zu äußern, dagegen schon.
Cyblord -. schrieb:> [...] versteht es nicht [...]
Ich will Dir nicht zu nahe treten, aber Du könntest Dich an den Gedanken
gewöhnen, dass es Leute gibt, die etwas verstehen, aber trotzdem nicht
Deiner Meinung sind. Oder noch schlimmer: Statt "trotzdem" "deshalb".
Ich nehme mir auch als Hobbyist die Freiheit heraus, dem "Profi" zu
widersprechen, wenn mir seine Äußerung unpassend oder falsch erscheint.
Wenn das Arroganz ist, bin ich arrogant.
Walter T. schrieb:> Cyblord -. schrieb:>> Ja mir kommt das hier auch wie ein Paradebeispiel für "E-Techniker als>> Programmierer" vor.>> Ich bin kein E-Techniker.
Ich schrieb ja: Zumindest Quereinsteiger.
> Ich will Dir nicht zu nahe treten, aber Du könntest Dich an den Gedanken> gewöhnen, dass es Leute gibt, die etwas verstehen, aber trotzdem nicht> Deiner Meinung sind. Oder noch schlimmer: Statt "trotzdem" "deshalb".
Klar gibt es. Ist bei dir aber nicht der Fall. Du versteht weder die
Aufgabe richtig noch die ganzen Lösungsvorschläge. Das merkt man schon
daran dass du gar nicht in der Lage bist, vernünftige Kritik daran zu
formulieren.
Cyblord -. schrieb:> Du versteht weder die Aufgabe richtig noch die ganzen Lösungsvorschläge.
WTF?
Die einzige Erklärung für diesen Satz lautet: Ich bin offensichtlich der
pefekte Beschreiber und selbst dazu in der Lage, Dinge, die ich selbst
noch nicht komplett durchdrungen habe, komplett und verständlich zu
dokumentieren.
Das ist sogar ein Stück näher an dem, was ich üblicherweise mache.
Aber in diese Thread wäre mir das nicht aufgefallen, dass mir das wieder
besonders gut gelungen wäre.
Walter T. schrieb:> Egon D. schrieb:>>> Ich kann den Automaten nicht terminieren, weil ich>>> nicht weiß, nach welchem Anwenderwissen ich fragen>>> könnte, das ich noch nicht kenne.>>>> Das ist der Punkt: Es geht nicht um KENNEN -- im Sinne>> von "habe ich schon mal gehört und klingt logisch", es>> geht um VERSTANDEN HABEN !>> Du musst zugeben: Sachen verstanden zu haben, von denen> man noch nie gehört hat, ist etwas viel verlangt.
Meine Güte, ist das ermüdend.
Als Leser Deiner Beiträge habe ich das deutliche Gefühl,
dass Du selbst DIE Konzepte nicht verstanden hast, deren
Namen Du kennst und deren Erläuterung Du mit einem
ungeduldigen "Das weiss ich doch alles längst!" beiseite
schiebst.
Das ist natürlich nur ein Gefühl, das aus dem Inhalt
Deiner Beiträge gespeist wird -- aber außer dem Inhalt
Deiner Beiträge habe ich ja nichts anderes von Dir,
und daher erlaube ich mir auch dieses Urteil.
> Egon D. schrieb:>> Leute, die diesen Spruch..."There are four difficult>> things in computer scrience:>> n+1 problems, caching and naming things.">> ...zitieren und gleichzeitig völlig blind für die>> Selbstironie sind, die er enthält.>> Klar. Witze, die man nicht verstanden hat, kann man> sich ja meist auch sehr gut merken.
Das eine hat mit dem anderen nichts zu tun.
Man kann leicht glauben, man hätte es verstanden, und
hat es tatsächlich doch noch nicht ganz verstanden.
Die größte Gefahr ist nicht das offene Unwissen ("Ohh...
davon habe ich ja überhaupt keine Ahnung!"), sondern
das verdeckte: "Was wollt ihr denn alle?! Das ist doch
vollkommen trivial..."
> Ich weiss nicht, genau, welches Menschenbild ihr habt.> Aber ich weiß, dass ich es nicht genauer wissen will.
Ironie: Dein Problem liegt in letzten Satz.
Walter T. schrieb:> Cyblord -. schrieb:>> Du versteht weder die Aufgabe richtig noch die ganzen Lösungsvorschläge.> Die einzige Erklärung für diesen Satz lautet: Ich bin offensichtlich der> pefekte Beschreiber und selbst dazu in der Lage, Dinge, die ich selbst> noch nicht komplett durchdrungen habe, komplett und verständlich zu> dokumentieren.
Nein, du hast das Problem nicht komplett dokumentiert. Du hast aber
Auszüge gezeigt, woraus man bestimmte Dinge folgern kann. Vor allem aus
dem Code. D.h. noch lange nicht dass du das verstanden hast.
Du hast vielleicht deine vielen winzigen Codefetzen verstanden.
Aber du hast du nicht verstanden wie man einen Programmablauf mit einer
SM realisiert. Wie diese Codefetzen in einer geordneten und bekannten
Art und Weise aufgerufen werden können. Genau darum gings ja. Du hast
die genannten Lösungen nicht kapiert. So einfach ist das. Du kannst sie
auf dein Problem nicht anwenden weil du sie nicht verstanden hast.
Darum bleibt dir nur das rumnölen an den Lösungen.
Cyblord -. schrieb:> Ich finde besonders die Kombination aus "kann es nicht und versteht es> nicht" und diesem arroganten Auftreten echt interessant.
Ja das ist echt erstaunlich. Wenn ich als Fragesteller im Verlauf merken
würde, dass da Welten an Grundverständnis fehlen, wäre ich ziemlich
ruhig und defensiv und würde das fehlende schnellstmöglich nachholen.
In diesem Sinne:
Walter T. (nicolas) schrieb:
> Es ist nicht peinlich, nicht alle Richtungen des Ingenieurwesens zu> kennen.
Nein, ist es sicher nicht. Trotzdem mal wieder an der Realität vorbei -
Softwareentwicklung, als praktische Ausprägung der Informatik, ist kein
Ingenieurwesen. Informatik ist eine Geisteswissenschaft, so wie
Mathematik auch. Nur ein wenig praktischer.
Ingenieure bauen Maschinen oder Brücken. Aber immer wenn ich Software
von Ingenieuren sehen musste haben mir danach die Augen geblutet, das
ist einfach nicht deren Ding.
Bevor sich jetzt jemand angegriffen fühlt - es gibt sicher genug Leute
die beides können, Hardware und Software. Aber es sind halt einfach sehr
unterschiedliche Disziplinen mit unterschiedlichen Denk- und
Herangehensweisen.
Johannes schrieb:> Ja das ist echt erstaunlich. Wenn ich als> Fragesteller im Verlauf merken würde, dass da> Welten an Grundverständnis fehlen,
Das merkt man aber in der Regel nicht so einfach.
Man merkt erstmal nur, dass die Kommunikation in
der laufenden Diskussion nicht klappt -- das kann
aber genausogut am Sender wie am Empfänger liegen.
> wäre ich ziemlich ruhig und defensiv und würde> das fehlende schnellstmöglich nachholen.
Das ist deutlich leichter gesagt als getan.
Gerade die Informatik ist m.E. ein Musterbeispiel
an begrifflichem Chaos. Das fällt natürlich immer
dann besonders auf, wenn nicht Informatiker unter-
einander reden, sondern Informatiker mit
Nicht-Informatikern.
> Trotzdem mal wieder an der Realität vorbei -> Softwareentwicklung, als praktische Ausprägung der> Informatik, ist kein Ingenieurwesen.
Das möchten die Informatiker gern so sehen.
Technik ist die praktische Anwendung der Natur-
wissenschaft; Ingenieure sind Leute, die unter
Zeit- und Kostenrestriktionen ein technisch
nutzbares Ergebis abliefern sollen.
Soll heißen: Informatiker, die forschen, sind
Wissenschaftler. Informatiker, die Informatik
anwenden, sind Ingenieure. Sie mögen sich selbst
gern für die Krone freischaffender Künstler halten --
zumindest in meinem Universum sind sie das nicht.
> Informatik ist eine Geisteswissenschaft, so wie> Mathematik auch. Nur ein wenig praktischer.
Genausowenig wie Buchhalter Mathematiker sind, weil
sie ja mit mathematischen Objekten (Zahlen) hantieren
und mathematische Operationen ausführen, genausowenig
sind Informatiker Mathematiker oder Geisteswissen-
schaftler.
> Ingenieure bauen Maschinen oder Brücken. Aber immer> wenn ich Software von Ingenieuren sehen musste haben> mir danach die Augen geblutet, das ist einfach nicht> deren Ding.
Die Erklärung dafür ist sehr einfach: Informatiker können
nicht einfach und allgemeinverständlich erklären, was sie
tun -- und warum sie es genau so tun, wie sie es tun.
Das führt dazu, dass es für Quereinsteiger sehr schwierig
ist, wirklich gute Ideen von hipper Schwurbelei zu unter-
scheiden.
Egon D. schrieb:> Technik ist die praktische Anwendung der Natur-> wissenschaft;
Der Teil ist richtig. Zu den Naturwissenschaften gehört u.a. die Physik,
Chemie und auch die Biologie.
> Ingenieure sind Leute, die unter> Zeit- und Kostenrestriktionen ein technisch> nutzbares Ergebis abliefern sollen.
Das ist Bullshit. Ingenieure wenden Technik an, also
Naturwissenschaften. Davon eben hauptsächlich Physik. Nicht mehr und
nicht weniger.
> Soll heißen: Informatiker, die forschen, sind> Wissenschaftler. Informatiker, die Informatik> anwenden, sind Ingenieure.
Bullshit. Informatik und Mathematik sind keine Naturwissenschaften.
Informatik ist eine Spezialisierung der Mathematik. Informatiker sind
ebenso wie Mathematiker keine Ingenieure.
Informatiker sind keine Ingenieure. Mit Informatikern kann man nicht wie
mit Ingenieuren reden.
Mathematiker sind auch keine Ingenieure, und kann mit ihnen auch nicht
wie mit Ingenieuren reden. Ob beide ähnlich sind, kann ich nicht
beurteilen. Ich habe Mathematiker nur in Umgebungen erlebt, in denen sie
nicht ihr heimisches Mileu fanden. Da war immer eine gewisse Ehrfurcht
dabei, dass die Ingenieure Felder schon sehen konnten, bevor die
Mathematiker sie berechnet haben. Entsprechend waren auch die
Verständigungsversuche durchaus adaptiv.
Informatiker habe ich immer nur in ihrem heimischen Milieu erlebt,
geprägt von einem absoluten Unwillen, Ihre Kommunikationsform an das
Gegenüber anzupassen (wenn man "Herablassung" nicht als Anpassung
zählt). Es kann natürlich sein, dass sich Mathematiker "zuhause" genauso
verhalten. Wobei die Kommunikation zwischen Mathematikern und
Informatikern auch nicht besonders effektiv zu sein schien.
Informatiker verlassen ihre vertraute Kommunikationsstruktur höchst
ungern. Den Grund kann man nur raten:
a) sie haben Angst, sich in einem nicht-vertrauten Gebiet zu bewegen
oder
b) sie haben Angst, dass man "herausfinden" könnte, dass sie auch nur
mit Wasser kochen.
Bei den Ingenieuren erlebe ich auch durchaus auch kommunikationsschwache
Kollegen. Aber selbst unter den Dummbratzen besteht da wenig In-Group
und Out-Group-Gehabe (vom Bildungsweg - von Abteilungen schon). Als
Ingenieur ist man es gewohnt, sich mit allen beteiligten Gruppen, die
sich nicht dagegen wehren, zu verständigen.
Du könntest beschreiben, was in den Transitionen geschieht.
Also: Schublade zu -> Schublade auf, dann heißt der Zwischenzustand:
"Schublade fährt auf" oder "Schublade bewegt sich" oder "Warte bis
Schublade am Endanschlag".
Irgendwas muss ja passieren, sonst würde der Zustand nicht so lange
andauern.
Erfordert natürlich mehr Nachdenken, als den Namen nach Namenskonvention
zusammenzubauen.
SebastianS schrieb:> Erfordert natürlich mehr Nachdenken, als den Namen nach Namenskonvention> zusammenzubauen.
Namenskonventionen sind nicht dafür da, um das Nachdenken zu ersetzen.
Sie sind dafür da, um das Nachdenken nicht zu behindern.
Wie ein aufgeräumter Schreibtisch und kariertes Papier.
Und natürlich: Eventuell finde ich wirklich mal jemanden, der für Geld
oder nette Worte ein anständiges Code Review macht - da sind sprechende
Namen auch ein eigener Wert.
Walter T. schrieb:> Namenskonventionen sind nicht dafür da, um das Nachdenken zu ersetzen.> Sie sind dafür da, um das Nachdenken nicht zu behindern.
Sehr richtig!
Gute Namenskonventionen sind wie Beugungen in der Muttersprache: Wenn
ich ein Verb "coden" habe, brauche ich kein Partizip II Perfect zu
erfinden sondern kann es ableiten und jeder versteht es.
Genauso beim Zustand "Disabled" im Modul "Control".
Wobei ich ctrl_mode_ unglücklich finde. Wenn Du nur ein Modul mit
Zuständen hast, spielen Namenskonventionen keine Rolle. Wenn Dein Code
mehrere 1000 Zeilen umfasst, dann würde ich über prägnantere
Namensschemata nachdenken.
Unsere "Module" wurden wie auch sonst üblich mit 3-5 Buchstaben
abgekürzt. Beispiele aus RL: ABS, DSC, DOLBY, KNX, ...
Dann gab es je Modul Kommandos, Zustände, Parameter, Bitfelder,
generelle Funktionen (init, sps, Kommandoauswertung, ...), ...
Hierfür gab es kurze, prägnante Präfixe. C für Kommandos, Z für
Zustände, ...
Und wie im Deutschen unterschiedliche Groß-Kleinschreibung. Das hört
sich nach Ungarischer Notation durch die Hintertür an, war es aber
nicht. Sondern so natürlich, dass die Regeln dieser Grammatik erst Jahre
später fixiert wurden und bis auf wenige Zweige konsistent waren.
C_ABS_XYZ wäre somit das Kommando Xyz für das Modul ABS (Kommandos als
#define).
AbsInit() dessen Initialisierungsroutine
AbsMain() dessen SPS-Loop
Z_ABS_Idle der Idle-Zustand
absT5nachlauf der Zeitparameter 5, der irgendeinen Nachlauf bestimmt
Wenn ctrl_mode bei Dir nur "Zustand" bedeutet, dann finde ich es zu
lang.
Zu Deinen Zuständen und Transitionen: Es gibt ja viele Ansätze, und noch
mehr, wenn Zeiten dazu kommen. Von daher hatten wir je nach Umfang bis
zu 3:
Z_disabled --> Einsprung zum Zustand disabled. Z.B. irgendwas
abschalten, Timer starten, etc.
Z_disabled_run --> der stabile Dauerzustand
Z_disabled_exit --> Nachbereitung
Dass der Einsprung nicht gesondert gepräfixed wurde, lieg vor allem
daran, dass es z.B. von Z_auto_feed immer den gleichen Einsprung geben
soll, egal ob es intern 1, 2 oder n verschiedene Zustände gibt.
SebastianS schrieb:> Du könntest beschreiben, was in den Transitionen geschieht.> Also: Schublade zu -> Schublade auf, dann heißt der Zwischenzustand:> "Schublade fährt auf" oder "Schublade bewegt sich" oder "Warte bis> Schublade am Endanschlag".> Irgendwas muss ja passieren, sonst würde der Zustand nicht so lange> andauern.>> Erfordert natürlich mehr Nachdenken, als den Namen nach Namenskonvention> zusammenzubauen.
Damit geht halt jegliche Abstraktion flöten. Und wenn sich später
Anforderungen ändern (meist kommen neue hinzu) wird der Zustandsautomat
immer komplexer bis ihn keiner mehr versteht. Genau das scheint ja auch
passiert zu sein. Zudem lässt sich der Automat so auch nicht
wiederverwenden.
Abstraktion hieße in diesem Fall zu sagen "irgendwas passiert bis der
Endzustand erreicht ist", dieses was noch ein wenig einzugrenzen (es
dauert möglicherweise, es lässt sich abbrechen, es lässt sich neu
anstoßen, die Funktionalität des Endzustandes steht erst bereit wenn
dieser erreicht ist) und es damit gut sein zu lassen.
Aber steht ja hier nicht zum ersten mal.