Was ist diese "Execute Around" -Sprache (oder ähnliches), von der ich gehört habe? Warum könnte ich es benutzen und warum könnte ich es nicht benutzen wollen?
java
language-agnostic
design-patterns
idioms
Tom Hawtin - Tackline
quelle
quelle
Antworten:
Grundsätzlich ist es das Muster, in dem Sie eine Methode schreiben, um Dinge zu tun, die immer erforderlich sind, z. B. Ressourcenzuweisung und Bereinigung, und den Anrufer dazu bringen, "was wir mit der Ressource tun wollen" zu übergeben. Beispielsweise:
Der aufrufende Code muss sich nicht um die Open / Cleanup-Seite kümmern - er wird von erledigt
executeWithFile
.Dies war in Java ehrlich gesagt schmerzhaft, da Schließungen so wortreich waren, dass Java 8-Lambda-Ausdrücke wie in vielen anderen Sprachen (z. B. C # -Lambda-Ausdrücke oder Groovy) implementiert werden können. Dieser Sonderfall wird seit Java 7 mit
try-with-resources
undAutoClosable
Streams behandelt.Obwohl "Zuweisen und Bereinigen" das typische Beispiel ist, gibt es viele andere mögliche Beispiele - Transaktionsbehandlung, Protokollierung, Ausführen von Code mit mehr Berechtigungen usw. Es ähnelt im Grunde dem Muster der Vorlagenmethode, ist jedoch nicht vererbt .
quelle
Die Execute Around-Redewendung wird verwendet, wenn Sie Folgendes tun müssen:
Um zu vermeiden, dass all dieser redundante Code wiederholt wird, der immer "um" Ihre eigentlichen Aufgaben ausgeführt wird, würden Sie eine Klasse erstellen, die sich automatisch darum kümmert:
Diese Redewendung verschiebt den gesamten komplizierten redundanten Code an einen Ort und macht Ihr Hauptprogramm viel lesbarer (und wartbarer!).
In diesem Beitrag finden Sie ein C # -Beispiel und in diesem Artikel ein C ++ - Beispiel.
quelle
Bei einer Execute Around-Methode übergeben Sie beliebigen Code an eine Methode, die Setup- und / oder Teardown-Code ausführen und Ihren Code dazwischen ausführen kann.
Java ist nicht die Sprache, in der ich dies wählen würde. Es ist eleganter, einen Abschluss (oder Lambda-Ausdruck) als Argument zu übergeben. Obwohl Objekte wohl gleichbedeutend mit Verschlüssen sind .
Es scheint mir, dass die Execute Around-Methode einer Art Inversion of Control (Abhängigkeitsinjektion) ähnelt , die Sie bei jedem Aufruf der Methode ad hoc variieren können.
Es könnte aber auch als Beispiel für eine Steuerkopplung interpretiert werden (indem man einer Methode anhand ihres Arguments sagt, was in diesem Fall wörtlich zu tun ist).
quelle
Ich sehe, dass Sie hier ein Java-Tag haben, daher verwende ich Java als Beispiel, obwohl das Muster nicht plattformspezifisch ist.
Die Idee ist, dass Sie manchmal Code haben, der immer dieselbe Boilerplate enthält, bevor Sie den Code ausführen und nachdem Sie den Code ausgeführt haben. Ein gutes Beispiel ist JDBC. Sie greifen immer zu einer Verbindung und erstellen eine Anweisung (oder eine vorbereitete Anweisung), bevor Sie die eigentliche Abfrage ausführen und die Ergebnismenge verarbeiten. Am Ende führen Sie immer die gleiche Bereinigung der Boilerplate durch, indem Sie die Anweisung und die Verbindung schließen.
Die Idee mit Execute-Around ist, dass es besser ist, wenn Sie den Boilerplate-Code herausrechnen können. Das erspart Ihnen das Tippen, aber der Grund liegt tiefer. Hier gilt das DRY-Prinzip (Don't-Repeat-Yourself): Sie isolieren den Code an einem Ort. Wenn also ein Fehler vorliegt oder Sie ihn ändern müssen oder ihn nur verstehen möchten, ist alles an einem Ort.
Die Sache, die bei dieser Art des Factorings etwas schwierig ist, ist, dass Sie Referenzen haben, die sowohl die "Vorher" - als auch "Nachher" -Teile sehen müssen. Im JDBC-Beispiel würde dies die Verbindung und die (vorbereitete) Anweisung enthalten. Um dies zu handhaben, "verpacken" Sie Ihren Zielcode im Wesentlichen mit dem Boilerplate-Code.
Möglicherweise kennen Sie einige häufige Fälle in Java. Eines sind Servlet-Filter. Ein anderer ist AOP um Beratung. Ein dritter sind die verschiedenen xxxTemplate-Klassen im Frühjahr. In jedem Fall haben Sie ein Wrapper-Objekt, in das Ihr "interessanter" Code (z. B. die JDBC-Abfrage und die Verarbeitung der Ergebnismenge) eingefügt wird. Das Wrapper-Objekt führt den "Vorher" -Teil aus, ruft den interessanten Code auf und führt dann den "Nachher" -Teil aus.
quelle
Siehe auch Code Sandwiches , das dieses Konstrukt in vielen Programmiersprachen untersucht und einige interessante Forschungsideen bietet. In Bezug auf die spezifische Frage, warum man es verwenden könnte, bietet das obige Papier einige konkrete Beispiele:
Und später:
In diesem Artikel wird nicht untersucht, warum dieses Idiom nicht verwendet werden soll, es wird jedoch beschrieben, warum das Idiom ohne Hilfe auf Sprachebene leicht falsch zu verstehen ist:
quelle
Ich werde versuchen zu erklären, wie ich es einem Vierjährigen tun würde:
Beispiel 1
Der Weihnachtsmann kommt in die Stadt. Seine Elfen codieren hinter seinem Rücken, was sie wollen, und wenn sie sich nicht ändern, wiederholen sich die Dinge ein wenig:
Oder dieses:
.... ad nauseam millionenfach mit millionen verschiedenen Geschenken: Beachten Sie, dass nur Schritt 2 anders ist. Wenn Schritt zwei das einzige ist, was anders ist, warum dupliziert der Weihnachtsmann den Code, dh warum dupliziert er Schritte? 1 und 3 eine Million Mal? Eine Million Geschenke bedeutet, dass er die Schritte 1 und 3 unnötig millionenfach wiederholt.
Execute around hilft, dieses Problem zu lösen. und hilft, Code zu beseitigen. Die Schritte 1 und 3 sind grundsätzlich konstant, sodass Schritt 2 der einzige Teil ist, der sich ändert.
Beispiel 2
Wenn Sie es immer noch nicht bekommen, ist hier ein anderes Beispiel: Stellen Sie sich ein Sandwich vor: Das Brot auf der Außenseite ist immer das gleiche, aber was auf der Innenseite ist, hängt von der Art des Sandes ab, das Sie wählen (z. B. Schinken, Käse, Marmelade, Erdnussbutter usw.). Brot ist immer außen und Sie müssen es nicht milliardenfach für jede Art von Sand wiederholen, die Sie herstellen.
Wenn Sie nun die obigen Erklärungen lesen, werden Sie es vielleicht leichter verstehen. Ich hoffe, diese Erklärung hat Ihnen geholfen.
quelle
Dies erinnert mich an das Strategie-Design-Muster . Beachten Sie, dass der Link, auf den ich verwiesen habe, Java-Code für das Muster enthält.
Offensichtlich könnte man "Execute Around" durchführen, indem man Initialisierungs- und Bereinigungscode erstellt und einfach eine Strategie übergibt, die dann immer in Initialisierungs- und Bereinigungscode eingeschlossen wird.
Wie bei jeder Technik zur Reduzierung der Code-Wiederholung sollten Sie sie erst verwenden, wenn Sie mindestens zwei Fälle haben, in denen Sie sie benötigen, vielleicht sogar drei (nach dem YAGNI-Prinzip). Beachten Sie, dass die Wiederholung des Entfernens von Code die Wartung reduziert (weniger Codekopien bedeuten weniger Zeit für das Kopieren von Fixes für jede Kopie), aber auch die Wartung erhöht (mehr Gesamtcode). Die Kosten für diesen Trick bestehen also darin, dass Sie mehr Code hinzufügen.
Diese Art von Technik ist nicht nur für die Initialisierung und Bereinigung nützlich. Dies ist auch gut geeignet, wenn Sie das Aufrufen Ihrer Funktionen vereinfachen möchten (z. B. wenn Sie es in einem Assistenten verwenden möchten, sodass für die Schaltflächen "Weiter" und "Zurück" keine riesigen Groß- und Kleinschreibung erforderlich sind, um zu entscheiden, was zu tun ist die nächste / vorherige Seite.
quelle
Wenn Sie groovige Redewendungen wollen, hier ist es:
quelle