Was ist die Alternative zu langen Switch Case Anweisungen bei Befehlsverarbeitung in Java?

3 Antworten

Command Pattern

https://en.wikipedia.org/wiki/Command_pattern

Leider wird das dort etwas sehr umständlich beschrieben, im Grunde ist es aber sehr simpel.
Einfach mal machen.

Nieder mit den ewig langen switch-case. Nieder mit else.

Gruß


Mathelatte  30.12.2021, 21:55

Und wo ist der Unterschied von dem hier

            if (argument == "ON")
            {
                // Switch (the Invoker) will invoke Execute() on the command object.
                @switch.Close();
            }
            else if (argument == "OFF")
            {
                // Switch (the Invoker) will invoke the Execute() on the command object.
                @switch.Open();
            }
            else
            {
                Console.WriteLine("Argument \"ON\" or \"OFF\" is required.");
            }

zu Switch-Case/If-Else?

0
AldoradoXYZ  30.12.2021, 21:57
@Mathelatte

Der Unterschied ist, dass man bei switch-case und else-if kotzen möchte.

Schlecht wartbar, schlecht testbar, schlecht erweiterbar. Einfach schlechter Stil.

Und keine Frage, wikipedia ist auch nicht der beste Ort um clean code zu lernen. Da wird dann zwar irgendwie das command pattern gezeigt, aber eben auch gleichzeitig wieder anderer Dreck.

Gruß

0
Mathelatte  30.12.2021, 22:00
@AldoradoXYZ

Da oben steht doch auch if/else-if/else... Und wenn es mehr mögliche Befehle wären, würden da noch mehr else-if's stehen. Das macht doch keinen Unterschied im Code. Der Vorteil des "Command patterns" ist eher, dass man Befehle in Arrays zwischenspeichern kann, nicht die Übersichtlichkeit.

0
AldoradoXYZ  30.12.2021, 22:05
@Mathelatte

Wie gesagt, Wikipedia ist auch nicht super toll, dort kann ja jeder schreiben.

if-else-Ketten sind auch Dreck.

Beim Command-Pattern hat man einen Command-Executor und viele Commands.
Man kann das etwas erweitern, dann besitzt das Command nicht nur eine execute-Methode, sondern noch eine isApplicable-Methode, welche prüft, ob das Command aktuell ausgeführt werden kann - damit kann man dann Bedinungen abbilden unter denen Commands ausgeführt werden.
Ein Command weiß dann unter welcher Bedingung es ausgeführt wird und was genau zu machen ist.

Gruß

0
KarlRanseierIII  30.12.2021, 22:13
@AldoradoXYZ

Wie sieht denn das Command-pattern aus, wenn Du z.B. 100 verschiedene Kommandos unterscheiden mußt? Bzw. jene Stelle, an der das Command identifziiert wird?

Zu irgndeinem Zeitpunkt muß doch festgestellt werden welche Wirkung auf was stattfinden soll?

0
Palladin007  30.12.2021, 22:20
@KarlRanseierIII

In so einem Fall müssen die Commands automatisch registriert, gesucht und ausgeführt werden z.B. per Reflection.

Bei diesen zwei Operationen + Default würde ich es aber beim switch belassen. Das Command-Pattern ist deutlich aufwändiger und komplexer in der Handhabung und solange es keine anderen Gründe dafür gibt, würde ich das nicht nutzen.

Aber ich frag mich auch, was "argument" sein soll und ob man nicht lieber schauen sollte, ob man die Daseinsberechtigung von diesem "argument" beseitigen kann, anstatt ihre Komplexität zu verschleiern.

1
KarlRanseierIII  30.12.2021, 22:25
@Palladin007

In dem Fall kommt argument von der Kommandozeile. Von daher auch meine Frage, wenn ich sowas wie einen Befehlsinterpreter habe, der eine hohe Anzahl Commands in form von Keywords unterstützen muß, muß ich den Token ja irgendwie auf das korrekte Command abbilden können.

Rudimentär gedacht, würde ich für sowas einen Lookup in einem Hash (o.ä.) machen um so zu identifizieren. Ich bin kein Javaianer, aber selbst wenn ich die Kommandos irgendwie 'registriere' oder ähnliches, muß es ja einen Punkt geben, an dem ein solcher Lookup stattfindet, auch wenn ich den nicht mehr selbst direkt implementiere?

0
Palladin007  30.12.2021, 22:27
@KarlRanseierIII

Die Kommandozeile wäre in der Tat ein Paradebeispiel für das Command-Pattern.
Dann würde ich aber auf bestehende Implementierungen zurückgreifen und die Befehlsdefinitionen zu den Commands mappen.

Das alles basiert aber auf Reflection - das ist dann dein Lookup.
Wie dieser Lookup sucht, ist dann beliebig, da gibt's zig verschiedene Möglichkeiten. Z.B. für C# gibt's mehrere solcher Frameworks, die mit komplexen Metadaten arbeiten, über die man alle möglichen Details einstellen kann und die dann auch sowas wie die Hilfe-Seite zusammen bauen können.

1
Palladin007  30.12.2021, 22:31
@Palladin007

Wobei man aber auch ein Mediator-Pattern aufziehen könnte - wäre bei besonders komplexen CLIs vermutlich die bessere Lösung.

0
KarlRanseierIII  30.12.2021, 22:51
@Palladin007

Mit Reflections kann ich doch die (eigenen) Eigenschaften enumerieren, um z.B: eine Liste aller Methodennamen o.ä. zu generieren und darauf zuzugreifen, soweit grob richtig?

Sofern also eine Liste von Command-Objekten vorliegt und diese wiederum den entsprechend String/Token als Attribut haben, könnte ich so durch Enumerierung das korrekte Command-Object identifizieren. Alternativ halt ein Hash mit den Zuordnungen - oder was auch immer. (Oder ich suche mir die Objekte auch über Reflections, indem ich die Hierarchie nach irgend einer Form von Marker absuche, so könnte ich mir die Liste sparen)

Und es gibt fertige Komponenten, die diesen Teil automatisieren, indem man sie mit einer Art formalen Bechreibung füttert, ähnlich wie z.B. Lexergeneratoren?

0
Palladin007  30.12.2021, 22:57
@KarlRanseierIII

Ich weiß nicht, wie gut Reflection von Java ist, aber wenn ich mir den Trend bei Java so anschaue: Nicht gut :D
Ich kann nur von C# sprechen und da geht das definitiv und noch deutlich mehr, was auch gerne mal zu grausigen Lösungen führen kann.

Aber klar, man kann auch eine klassische Liste aufbauen, allerdings muss die gepflegt werden. Jede Command-Änderung muss also an zwei Stellen stattfinden, min. eine Stelle, die früher oder später vergessen wird. Wenn das alles zusammen steht (Metadaten an der Klasse - die Marker, die Du meinst) und dann per Reflection gesucht wird, kann man dieses Risiko reduzieren.

Und es gibt fertige Komponenten, die diesen Teil automatisieren, indem man sie mit einer Art formalen Bechreibung füttert

Bei C# ja, bei Java ziemlich sicher auch, aber ich kenne keine.

1
Palladin007  30.12.2021, 22:06

Solche Erklärungen sind immer scheiße :D
Und die guten Erklärungen sind schwer zu verstehen.

Geht leider nicht anders, deshalb werden Leute, die den Kram auch wirklich verstanden haben und nicht nur abschreiben, teuer bezahlt ^^

0
AldoradoXYZ  30.12.2021, 22:08
@Palladin007

Gute Erklärungen sind sogar leicht zuverstehen, darum sind sie gut.

Erklärungen die sehr schwer zu verstehen sind, sind Schrott.

werden Leute, die den Kram auch wirklich verstanden haben und nicht nur abschreiben, teuer bezahlt 

Ich kenne so viele Leute die von clean code noch nie etwas gehört haben und grottigen Code schreiben und trotzdem extrem gut bezahlt werden. Manche sind sogar stolz drauf, dass niemand ihren Code versteht und nach 3 Wochen verstehen sie ihn selbst nicht mehr xD

Gruß

0
Palladin007  30.12.2021, 22:12
@AldoradoXYZ
Gute Erklärungen sind sogar leicht zuverstehen, darum sind sie gut.
Erklärungen die sehr schwer zu verstehen sind, sind Schrott.

Ich meine z.B. SOLID. Viele gute und leicht verständliche Erklärungen, aber keine davon erklärt die wirklichen Zusammenhänge, warum man den ganzen Aufwand betreibt. Sie alle fassen das unter irgendwelchen Oberbegriffen zusammen, lassen dabei aber ein paar Prozent aus.

Genau diese paar Prozent sind aber wichtig, ich hab schon zu oft Leute gesehen, die irgendwelchen Regeln folgen, ohne wirklich begriffen zu haben, was sie da machen. Und "nur eine Aufgabe oder Verantwortlichkeit" ist nun mal nicht immer richtig.

Ich kenne so viele Leute die von clean code noch nie etwas gehört haben und grottigen Code schreiben und trotzdem extrem gut bezahlt werden. 

Das Eine schließt das Andere nicht aus ^^
Aber Leute, die wissen, was sie tun, werden meist auch gut bezahlt - vorausgesetzt, sie stellen sich beim Gespräch nicht total bescheuert an.

Ach ja, ich rede nicht von Clean Code :D Clean Code ist einfach.

0
AldoradoXYZ  31.12.2021, 08:21
@Palladin007
Ach ja, ich rede nicht von Clean Code :D Clean Code ist einfach.

Als ob. Es gibt so unglaublich viele Software-Entwickler die völlig ahnungslos sind. Und die arroganten, sind oft die schlimmsten Fälle. Wer überzeugt ist alles zu können, hat schon verloren.

Gruß

0
Palladin007  31.12.2021, 09:40
@AldoradoXYZ

Ich rede von der Software-Architektur.

Clean Code beschäftigt sich nur mit Lesbarkeit und Verständlichkeit vom Quellcode. Viele der verwendeten Patterns und Prinzipien betreffen aber auch die Software-Architektur und da ist das Ziel, da sind die Ziele etwas anders.

Im Kleinen, also bei einem Switch ist das nicht wirklich relevant, aber wenn man die ganze Anwendung nach einem bestimmten Pattern oder Prinzip strukturiert, das aber nicht richtig macht, kann das ganze Projekt zum Tode verurteilt werden, obwohl die Umsetzung super gut lesbar ist.

Weil das sowieso nie perfekt gelingt und man immer etwas falsch macht, teile ich meine Projekte immer in möglichst gut voneinander abgekapselten Module auf, allerdings beeinträchtig das wiederum die Lesbarkeit.

0
Palladin007  31.12.2021, 09:58
@AldoradoXYZ

Schön - und trotzdem sollte man die beiden Varianten entsprechend beachten.

0
AldoradoXYZ  31.12.2021, 10:04
@Palladin007

Man soll ordentlich arbeiten und das bedeutet alles zu beachten, nicht nur zwei Varianten.

Gruß

0
Palladin007  31.12.2021, 10:09
@AldoradoXYZ

Das sind aber die zwei Varianten, die es gibt: Sozusagen ein Blick von Innen und ein Blick von Außen und Letzterer wird gerne vergessen. Dabei ist der fast noch wichtiger, denn je weiter raus man geht, desto schwerer wird es, Fehler nachträglich zu beheben.

0
AldoradoXYZ  31.12.2021, 11:13
@Palladin007

Ich will hier gar nicht diskutieren ob eine gute Architektur gut ist. Das ist völlige Zeitverschwendung.

Gruß

0
Palladin007  31.12.2021, 14:21
@AldoradoXYZ

Zu einer Diskussion gehören immer zwei - ich wollte nur darauf aufmerksam machen, dass das Thema mehr umfasst, als vielleicht auf den ersten Blick klar wird.

0

Command-Pattern oder Strategy-Pattern

Oder Anderes, wie z.B. Mediator-Pattern oder daran angelehnte Pattern.

Je nachdem, was die Anforderungen sind.

Irgendwo musst du schreiben, was bei den jeweiligen Befehlen getan werden soll. Ob mit If-Else, Switch-Case oder sonst was. Um den Code kommst du nicht herum.