AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Automaten in Source Code

Ein Thema von Christian18 · begonnen am 20. Nov 2009 · letzter Beitrag vom 1. Dez 2009
Antwort Antwort
Seite 3 von 7     123 45     Letzte »    
SebE

Registriert seit: 31. Jul 2004
Ort: Chemnitz
316 Beiträge
 
Delphi 7 Personal
 
#21

Re: Automaten in Source Code

  Alt 21. Nov 2009, 17:02
@NamenLozer:

Fehleranfällig in der Hinsicht, dass man nicht SOFORT erkennt, wer was wo erzeugt.

Es ist besser, wenn die Zustände in der Gesamtheit von Anfang an "fest stehen", also existieren.

Zu meinem Code:
Wegen der BEGIN-END-Positionierung?
Jedem das seine, das meinte ich aber nicht, hier ist nicht die Formatierung das Thema, sondern die Semantik!
Sebastian
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#22

Re: Automaten in Source Code

  Alt 21. Nov 2009, 18:04
Zitat von SebE:
Zu meinem Code:
Wegen der BEGIN-END-Positionierung?
Unter anderem, aber z.B. auch, dass du alle Methodennamen mit einem Unterstrich beginnst. Was soll das bitte?
  Mit Zitat antworten Zitat
Benutzerbild von Mithrandir
Mithrandir
(CodeLib-Manager)

Registriert seit: 27. Nov 2008
Ort: Delmenhorst
2.379 Beiträge
 
#23

Re: Automaten in Source Code

  Alt 21. Nov 2009, 18:10
NamenLozer,

ist doch völlig Latte.

Es entspricht so zwar nicht dem Style Guide, auf den sich viele immer beziehen, aber es ist immernoch leserlich. Also wieder zurück zum Thema.
米斯蘭迪爾
"In einer Zeit universellen Betruges wird das Aussprechen der Wahrheit zu einem revolutionären Akt." -- 1984, George Orwell
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#24

Re: Automaten in Source Code

  Alt 21. Nov 2009, 19:00
Zitat von SebE:
...[/delphi]
.. //KANN MAN DIE TABELLE "SCHÖNER" FÜLLEN?
[/delphi]
Ja.
Da es dem Automaten egal ist, ob es sich um eine 1, 2 usw. handelt, kann man das drastisch verkürzen: Der DEA kennt nur Ziffern, Komma, das Terminalsymbol (Ende der Eingabe) sowie ungültige Zeichen. Da ungültige Zeichen zu einem sofortigen Abruch führen, wird die Tabelle ziemlich klein. So klein, wie das Problem, das der DEA lösen soll:
Delphi-Quellcode:
Const
  DEA : Array [symDigit..symTerminal, stStart..stDecimals] =
// symDigit , symKomma, symTerminal
{stStart }  (stDigits , stError , stError),
{stDigits}  (stDigits , stComma , stStop),
{stComma}   (stDecimals, stError , stError),
{stDecimals}(stDecimals, stError , stStop)
            );
// Natürlich implementiert man eine Funktion/Methode, die das nächste Symbol der Eingabe extrahiert,
// klassifiziert und sowohl Symbolklasse als auch das Symbol selbst zurückliefert.
So sehr Du an dem Case-Konstrukt zu hängen scheinst, es verstößt gegen diverse Grundregeln des 'clean coding' (DRY, KISS), weshalb ich das persönlich ablehne. Das ist aber Geschmackssache.

Ich stell mir nur gerade ein Case-Konstrukt mit 1700 Zuständen vor, bei dem nur bei 3 Zuständen etwas passiert...
Bei der Implementierung als Tabelle habe ich die Tabelle in einer Resource. Diese Tabelle wurde vorher vermutlich automatisch generiert und ist daher fehlerfrei. Die Implementierung selbst ist extrem kompakt und übersichtlich.

Zitat von SebE:
Nicht dass ich nicht mit Klassen, Vererbung, etc. umgehen kann...erzeugt der StartZustand automatisch den "NextState" und das geht rekursiv immer so weiter bis StopZustand?
Äh..Nein.

Zitat von SebE:
Ist das die "gute" OOP-Lösung?
Imho schon.

Zitat von SebE:
Ich finde diese unübersichtlich und fehleranfällig.
Nein. Jede Klasse, die das IAbstractState-Interface implementiert, MUSS Code für den Übergang zur nächsten Klasse implementieren, sowie den eigenen Zustand dokumentieren (IsStop, IsError). Spaghetti-Code ist hingegen unübersichtlich und fehleranfällig, da man sich jedesmal neu hineindenken muss und es ein leichtes ist, irgendwo einen Korken eingebaut zu haben (siehe unten)

Zitat von himitsu:
ich würde es dann eher so machen...
Logisch, ich wollte nur den von mir einmal gemachten Fehler (im Codebeispiel für die Abarbeitung der Tabelle) nicht implizit korrigieren.

Zitat von Reinhard Kern:
..in Assembler war das noch herrlich einfach ... war das schon fast selbstdokumentierend. Ausserdem fiel gleich auf, wenn das Programm unvollständig war, ... Natürlich ist das einer 2 fach verschachtelten Case-Struktur völlig gleichwertig. Aber wenn man das im Source-Code auch als n x m Tabelle schreiben kann, wird es sehr übersichtlich.
Siehe oben.

Zitat von SebE:
Fehleranfällig in der Hinsicht, dass man nicht SOFORT erkennt, wer was wo erzeugt.
@SebE: Ich habe deinen Code abgeschrieben. Er funktioniert nicht. Wieso?
Delphi-Quellcode:
unit Imperative;
interface

type
  state = (sStart, sFrac, sTrunc, sStop);

type
  DEA_imperative = class
    private
      fInput,
      fOutput: string;
      fPos: BYTE;
      fState: state;
    public
      constructor _create(const input: string);
      destructor _destroy;

      procedure _execute;

      function _getOutput: string;
    end;

implementation

constructor DEA_imperative._create(const input: string);
begin
fInput := input + #0
end;

destructor DEA_imperative._destroy;
begin

end;

procedure DEA_imperative._execute;
begin
fPos := 1;
fState := sStart;
fOutput := '';

while fState <> sStop do begin
    case fState of
    sStart:
        case fInput[fPos] of
        '1'..'9': begin
          fOutput := fInput[fPos];

          fState := sTrunc
          end
        else fState := sStop
        end;
    sTrunc:
        case fInput[fPos] of
        '1'..'9': fOutput := fOutput + fInput[fPos];
        ';': begin
          fOutput := fOutput + '-';

          fState := sFrac
          end
        else fState := sStop
        end;
    sFrac:
        case fInput[fPos] of
        '1'..'8': fOutput := fOutput + fInput[fPos];
        else fState := sStop
        end
    end;

  fPos := fPos + 1
  end
end;

function DEA_imperative._getOutput: string;
begin
_getOutput := fOutput
end;

end.
Man muss sich in den kompletten Code eindenken und ALLES lesen, bis man den Fehler gefunden hat.
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#25

Re: Automaten in Source Code

  Alt 21. Nov 2009, 19:20
Nachdem ich sowas gerade in ner Übung vorgesetzt bekommen habe, äußere ich mich auch mal

Für kleine Aufgaben reicht definitiv ein case-Statement. Rückblickend (mir ist diese Woche erst in den Sinn gekommen dass diese Zustandsautomaten existieren und Sinn machen) muss ich allerdings sagen dass ein case-Statement schwer wartbar ist.

Für größere Sachen (die Grenze liegt je nach Geschmack woanders ... für mich vll. so bei 4x4 oder so) ist definitiv eine Tabelle von Vorteil.

Die Tabelle kann man dann auch in einer Datei ablegen, damit erübrigt sich auch die Frage, wie man eine 10x10 Tabelle übersichtlich im Source deklariert ^^

Das was ich letztens gemacht habe war so ne Art Drag 'n Drop um mit ein paar grafischen Objekten zu spielen. Es lief dann darauf hinaus, dass ich ein "CurrentTool" (Typ: Enum) habe, und in den Events (MouseDown, MouseMove und MouseUp) jeweils ein Case-Statement in dem dann ein paar Sachen gemacht werden. (Das Tool kann nur über Buttons am Rand geändert werden, in den Maus-Events finden also keine Tool-Änderungen statt)
Wenn man das mit so einer Tabelle machen würde, wären wahrscheinlich ganz schön viele Zustände dabei und ziemlich viele "Error-Zustände" - sobald ich den Überblick verliere werde ich das Programm entsprechend umgestalten
  Mit Zitat antworten Zitat
SebE

Registriert seit: 31. Jul 2004
Ort: Chemnitz
316 Beiträge
 
Delphi 7 Personal
 
#26

Re: Automaten in Source Code

  Alt 21. Nov 2009, 20:06
@NamenLozer:
der Unterstrich macht mir deutlich, was MIR gehört und was vordefiniert (oder Compilermagic) ist.

@alzaimar:

Zitat:
SebE hat folgendes geschrieben:
Nicht dass ich nicht mit Klassen, Vererbung, etc. umgehen kann...erzeugt der StartZustand automatisch den "NextState" und das geht rekursiv immer so weiter bis StopZustand?

Äh..Nein.
Wer erzeugt die Zustände denn dann?
Im Beispiel wurde nur der Startzustand erzeugt!
-> Meine Frage lautete:
erzeugt der Startzustand SEINEN NextState automatisch?
StartZustantsInstanz := StartZustand.Create; //erzeugt von selbst zB Zustant2, den man mittels StartZustantsInstanz.GetNext verwenden kann Wenn dem so WÄRE, DANN wäre es unübersichtlich.
(entspricht nicht meinem Gedanken von Überschaulichkeit)


Ich versteh nicht wieso man beim Case den gesamten Code durchdenken muss - es handelt sich immer um den gleichen Aufbau.
(Zustand suchen, Eingabe suchen und ändern)

Ich hab nichts gegen die Tabellenlösung (ab einer gewissen größe würde ich auch nicht auf diese Möglichkeit verzichten wollen), aber ICH finde, dass man sich die Tabelle bei evtl. Änderungen genauer ansehen müsste als "meine" Case.
Sebastian
  Mit Zitat antworten Zitat
SebE

Registriert seit: 31. Jul 2004
Ort: Chemnitz
316 Beiträge
 
Delphi 7 Personal
 
#27

Re: Automaten in Source Code

  Alt 21. Nov 2009, 20:11
Was mir grad noch auffällt:

Delphi-Quellcode:
Const
  DEA : Array [symDigit..symTerminal, stStart..stDecimals] =
// symDigit , symKomma, symTerminal
{stStart }  (stDigits , stError , stError),
{stDigits}  (stDigits , stComma , stStop),
{stComma}   (stDecimals, stError , stError),
{stDecimals}(stDecimals, stError , stStop)
            );
Du musst deine Eingabe (wir gehen davon aus, dass wir sie als String bekommen) erst einmal in deine Token/Symbole umwandeln.
Spricht du brauchst einen Scanner/Lexer -> dann kommst du ja auch nicht um deine Case-Anweisung.

Das war der Grund, warum meine Tabelle so riesig geworden ist (zwar groß, aber schnell).

Es bleibt natürlich immernoch Geschmackssache.
Ich für meinen Teil, bastle mir meine Parser (TopDown) ohne Generatoren -> Ich bin an die Cases gewöhnt.
Die Tabellenlösung kommt aus der "BottomUp-Ecke".

PS: die Quellcodes tun das, was ich von ihnen verlangt habe (Delphi 7 PE)
Sebastian
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#28

Re: Automaten in Source Code

  Alt 22. Nov 2009, 03:51
@_: Lustig ist, dass Delphi in der Unit System gerade die Funktionen die Compilermagic sind, mit einem vorangestellten _ definiert (Zumindest sagt mir mein Elefantenhirn das, dass dies mal vor ein paar zweistelligen Monaten gesehen hat... *hust*)
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#29

Re: Automaten in Source Code

  Alt 22. Nov 2009, 04:09
Zitat von SebE:
Spricht du brauchst einen Scanner/Lexer -> dann kommst du ja auch nicht um deine Case-Anweisung.
Äh..Doch: Ein Scanner benötigt kein CASE. Ein Scanner implementiert einen NDEA. Du meinst aber eher soetwas:
Delphi-Quellcode:
Var
  SymbolClass : Array [Char] Of TSymbol;
Entsprechend befüllen, fertig. Dann einfach 'Symbol[CurrentChar]' nehmen und freuen, wie einfach das Leben sein kann.

Zitat von SebE:
(zwar groß, aber schnell).
Wer primär auf Nanosekunden schaut, hat noch nicht kapiert, worum es beim Programmieren geht.

Zitat von SebE:
die Quellcodes tun das, was ich von ihnen verlangt habe (Delphi 7 PE)
Ja, aber Du findest einen Fehler nicht so leicht. Hast Du meine denn gefunden? Du verwendest zudem zig mal den gleichen Code (case..of '0'..'9'). Das ist doch überflüssig und verstößt eben gegen Grundprinzipien der sauberen Programmierung.
Aber ich gebe zu, bei so keinen Geschichten ist ein Mini-DEA wirklich nett anzusehen (wenn man das nochmal sauberer hinbekommt) und ausreichend.

Zitat von SebE:
Wer erzeugt die Zustände denn dann?
Jede State-Klasse wäre dann dafür zuständig für jede Symbolklasse einen Folgezustand zu definieren.

Zitat von SebE:
Im Beispiel wurde nur der Startzustand erzeugt!
Nö.
 State := State.NextState; Was macht denn diese Zeile?
Zitat von SebE:
-> Meine Frage lautete: erzeugt der Startzustand SEINEN NextState automatisch?
Nein, nur wenn man ihn darum bittet ('NextState')

Zitat von SebE:
(entspricht nicht meinem Gedanken von Überschaulichkeit)
Aber Du hast doch noch gar keine Ahnung von Interfaces, Klassen usw. Wie willst Du dir denn dann ein Urteil erlauben?

Zitat:
Ich versteh nicht wieso man beim Case den gesamten Code durchdenken
Hast Du den Fehler denn gefunden? Man tippt so viel und irgendwo vertippt man sich. Tippt man weniger, weil man sich z.B. nicht wiederholt, vertippt man sich auch nicht so oft. Ist doch logisch, oder?
Mein Code ist wesentlich weniger fehleranfällig, schneller einsatzbereit (weil weniger Zeilen), wiederverwendbar, allgemeingültig, robust und leichter verständlich (Als DEA). Deiner nicht. In deinem Code ist es viel leichter möglich, einen Fehler einzubauen (siehe mein Beispiel). Er ist nicht für einen ähnlichen DEA verwendbar, sondern muss komplett neu geschrieben werden. Viel Spass, wenn der DEA auch Buchstaben oder Zahlen à la '1,234E+99' verarbeiten soll.

Eine DEA-Tabelle ist natürlich kryptisch. Das stimmt.

Bleib halt bei deinen CASE-Konstrukten und -vor allen Dingen- kodiere Parser, Scanner, Lexer und DEA per Hand.

Zitat von jfheins:
Wenn man das mit so einer Tabelle machen würde, ...
Dafür ist es dann für alle Eingaben 100% korrekt und man muss sich keine Gedanken mehr machen.
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
SebE

Registriert seit: 31. Jul 2004
Ort: Chemnitz
316 Beiträge
 
Delphi 7 Personal
 
#30

Re: Automaten in Source Code

  Alt 22. Nov 2009, 10:33
Zitat:
Ja, aber Du findest einen Fehler nicht so leicht.
Tut mir Leid, ich beharre darauf, dass man (in diesem Beispiel) nicht sagen kann, dass CASE unüberschaubarer sein soll.

Ob ich die Case durchsuchen muss oder die Tabelle neu "berechnen" muss - ist für mich der gleiche Aufwand!

Zitat:
Du verwendest zudem zig mal den gleichen Code (case..of '0'..'9')
Nur als Denkanstoß:
Delphi-Quellcode:
Const
  DEA : Array [symDigit..symTerminal, stStart..stDecimals] =
// symDigit , symKomma, symTerminal
{stStart }  (stDigits , stError , stError),
{stDigits}  (stDigits , stComma , stStop),
{stComma}   (stDecimals, stError , stError),
{stDecimals}(stDecimals, stError , stStop)
            );
Man muss bei jeder Variante JEDEN Zusstandsübergang angeben/implementieren.
Wenn ich nun möchte, dass mein Automat ("0"en hab ich übrigens vergessen) nach dem Komma nur Ziffern "1".."8" akzeptieren soll, dann hab ich hier schon keinen Doppelten Code.
Will sagen: es ist Zufall, dass hier doppelter Text steht.

Wenn DU keine Fehler in der Tabelle machst, dann mache ICH keinen in meiner Case.

Zitat:
Wer primär auf Nanosekunden schaut, hat noch nicht kapiert, worum es beim Programmieren geht.
Aus dem Zusammenhang gerissene Zitate verarbeiten tust du gern, gell?


NOCHMAL:

Also werden alle Zustände "on demand" erzeugt(?).

Wenn aktueller Zustand in den nächsten übergehen soll, erzeugt dieser (wenn nicht schon getan) den Neuen.

WENN das die Lösung ist, geht mir hier OOP eindeutig zu weit (oder auch nicht(?)).

Ich würde ein Objekt, welches die Tabelle an sich repräsentiert modellieren, die dann alle Zustände erzeugt.
Sonst wären ja die Zustandsüberführungen über große Text-Entfernungen hinweg definiert.

Es ist nicht die Aufgabe eines jeden Zustandes, sich um den nächsten zu kümmern. (MEINE Meinung)

Zitat:
Aber Du hast doch noch gar keine Ahnung von Interfaces, Klassen usw. Wie willst Du dir denn dann ein Urteil erlauben?
Mit solchen Äußerungen wär ich an deiner Stelle vorsichtig!

Zitat:
Bleib halt bei deinen CASE-Konstrukten und -vor allen Dingen- kodiere Parser, Scanner, Lexer und DEA per Hand.
Du hast dem Anschein nach keinen Spaß mehr am (von-Hand-)Programmieren?

@Medium:
Was interessiert es den Programmierer, wie die die interne Umsetzung von etwas aussieht?
Ich GLAUBE, dass machen auch C-Compiler so (im Assembler-Code stehen dann "_" oder "__" vor allen Routinen)
Sebastian
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 7     123 45     Letzte »    


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:44 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz