Instructions und Executors

Instruktionen (Instruction) beinhalten Informationen zur Ausführung einer Aufgabe – nicht aber eine Beschreibung wie diese Aufgabe konkret auszuführen ist. Executors (InstructionExecutor) wissen, wie eine Aufgabe konkret ausgeführt wird und führen diese unter Verwendung der Angaben einer Instruktion aus. Das Prinzip und seine Ausgestaltung ähnelt dem Action & Command Framework,[31] es ist jedoch abstrakter und damit auch flexibler. Die wesentlichen Unterschiede sind:

  • Aktionen halten alle Informationen vor, die benötigt werden um eine konkrete ausführbare Funktionalität in einer grafischen Benutzeroberfläche zu repräsentieren. Instruktionen sind nicht an grafische Benutzeroberflächen gebunden. Sie tragen Informationen zu einer Aufgabe, die durch Anwendung eines Executors zur konkreten Ausführung gelangen können. Ob diese Angaben dem Nutzer präsentiert werden und, wenn ja, in welcher Form, ist für die Instruktion irrelevant.

  • Kommandos führen eine definierte Funktionalität aus, welche durch die Kontextobjekte parametrisiert und durch die Aktion repräsentiert wird. Instruktionen beschreiben eine allgemeine Funktionalität, welche im Zusammenhang der Integration interpretiert und ausgeführt werden muss. Die Ausführung obliegt den Executor-Implementationen. Durch Bereitstellung und Auswahl von Executor-Implementationen bestimmt die Integration, wie die Angabe der Instruktion ausgeführt werden sollen. Falls eine Instruktion beispielsweise vorgibt, dass ein gegebener Hyperlink verarbeitet werden soll, können die Auswirkungen je nach Zusammenhang sehr verschieden sein: In einer GUI-Anwendung könnte der Link an einen Browser übergeben werden. In der Batch-Verarbeitung könnte automatisch ein Screenshot der Webseite erzeugt werden. In der Dokumentenerzeugung könnte eine Fußnote generiert werden. Für jede dieser Varianten könnte es dedizierte Executors geben, die integrationsspezifisch ausgewählt und angewandt werden um das gewünschte Ergebnis zu erreichen.

  • Die Bindung zwischen Instruktionen und Executors ist weniger stark als zwischen Aktionen und Kommandos. Eine Aktion kennt die Kommandos, die durch sie ausführt werden sollen. Eine Instruktion hat keinerlei Beziehung zu Executor-Implementationen. Es können keine, ein einzelner, oder mehrere Executors für eine Instruktion existieren. Welche Ausprägungen existieren und welche letztlich zur Ausführung kommen, ist der Instruktion nicht bekannt.

Die folgenden Abschnitte geben nähere Details zu den einzelnen Komponenten.

Instruktionen

Instruktionen beschreiben auf abstrakte Weise eine Funktionalität, die zur Ausführung gebracht werden soll. Eine Implementation könnte beispielsweise definieren, dass ein Dokument geöffnet werden soll, und es über einen String identifizieren – sie gibt dabei nicht an, wo dieses Dokument zu finden ist. Es könnte aus einem Archiv stammen, als eingebetteter Datenstrom innerhalb eines anderen Dokuments vorliegen, oder on-the-fly generiert werden. Eventuell liegt es in einer Zielumgebung auch überhaupt nicht vor, sodass die Ausführung unmöglich ist.

Instruktionen werden als Realisierungen von Instruction umgesetzt und sind als unveränderliche Objekte konzipiert. Sie enthalten ausschließlich beschreibende Informationen ohne eigene Ausführungslogik. Durch ihre abstrakte Natur sind sie gut zur Speicherung (beziehungsweise Serialisierung) geeignet. Manche Dokumentformate bieten Möglichkeiten, Informationen aus Instruktionen mit einzubetten.

Executors

Implementationen von InstructionExecutor haben den Zweck, aus gegebenen Instruktionen konkrete Handlungen abzuleiten und diese auszuführen. Da sie zu diesem Zweck typischerweise auf andere Objekte der laufenden Anwendung zugreifen müssen, haben sie ein Kontextobjekt zur Verfügung. Dessen Ausgestaltung ist integrationsspezifisch – für eine Anwendung mit grafischer Benutzeroberfläche liegt die Verwendung des GUI Kontexts[32] nahe, es können jedoch beliebige Objekte als Kontext des Executors eingesetzt werden.

Konzeptuell existiert keine Verbindung zwischen Instruktionen und Executors. Jeder Executor muss jedoch angeben können, ob er eine gegebene Instruktion verarbeiten kann oder nicht. Diese Frage muss einerseits auf generelle Weise beantwortet werden: Der Executor erhält das Klassenobjekt einer Instruktion und gibt an, ob an der Verarbeitung Interesse besteht. Andererseits muss sie spezifisch für eine konkrete Instanz von Instruction und ein konkretes Kontextobjekt beantwortet werden. Falls die Antworten positiv ausfallen, können Instruktion und Kontext an den InstructionExecutor zur Ausführung übergeben werden.

Um die Instruktion auszuführen, muss ein Executor interpretieren, was deren Angaben in Bezug auf seine aktuelle Ausführungsumgebung bedeuten. In manchen Fällen liegen Beschränkungen vor: Falls eine Instruktion das Öffnen eines Hyperlinks anweist, könnte dies aus Sicherheitsgründen unterbunden werden. In anderen Fällen bestehen unterschiedliche Möglichkeiten: Falls eine Instruktion ein anderes Dokument referenziert, könnte es in einem separaten Tab geöffnet, in einem Vorschaufenster dargestellt, für späteres Lesen vorgemerkt, als Datenstrom abgespeichert oder als Eintrag in ein Literaturverzeichnis aufgenommen werden. Eventuell sollen auch mehrere dieser Aktionen ausgeführt oder dem Nutzer zur Auswahl präsentiert werden.

Instruktionen zur Ausführung bringen

Die Verbindung zwischen Instruktionen und Executors ist bewusst offen gestaltet und muss integrationssspezifisch gelöst werden. Zunächst muss zum Implementationszeitpunkt definiert werden, welche Executor-Ausprägungen in der Anwendung zur Verfügung stehen. Soll zum Ausführungszeitpunkt eine konkrete Instruktion verarbeitet werden, stellt sich die Frage, welche Implementationen die Ausführung übernehmen können und sollen. Es muss also eine Auswahlstrategie definiert werden. Typischerweise werden dazu alle zur Verfügung stehenden Executors befragt, ob sie die Ausführung generell übernehmen könnten. Aus der daraus entstehenden Teilmenge werden dann ein oder mehrere Executors ausgewählt. Nun kann die tatsächliche Ausführung erfolgen.

Im Lieferumfang der jadice document platform befindet sich eine flexible Umsetzung der beschriebenen Schritte, die auf den Einsatz in GUI Anwendungen in Verbindung mit dem Action & Command Framework zugeschnitten ist. Diese konkrete Ausprägung soll im Folgenden als ein möglicher Lösungsweg beschrieben werden.

  • In der grafischen Benutzeroberfläche wird ein Element repräsentiert, das über Instructions verfügt.

  • Es existieren InstructionExecutor Implementationen, die diese Instruktionen verarbeiten können. Als generisches Kontext-Objekt verwenden die Executors den GUI Kontext.[33]

  • Es existiert eine Aktion,[34] mit deren Hilfe über die grafische Benutzeroberfläche die Ausführung dieser Instruktionen angefordert werden kann.

  • Die Aktion ist mit einem Kommando verknüpft, das die Ausführung auslöst.[35]

  • Dem Kommando sind die Instruktionen, die zur Ausführung gelangen sollen, bekannt. Mit Hilfe einer InstructionChain können sie beispielsweise über den Kontext[36] transportiert werden. Alternativ kann die Bekanntmachung über andere, integrationsspezifische Wege erfolgen.

  • Das Kommando kennt die Menge aller zur Verfügung stehender Executors.[37] Diese können dem Kommando explizit bekannt sein, oder ebenfalls über den Kontext, mittels einer Instanz von InstructionExecutorInventory, transportiert werden.

  • Für jede auszuführende Instruktion befragt das Kommando sämtliche zur Verfügung stehenden Executors, ob sie diese Instruktion prinzpiell ausführen können.

  • Für die Teilmenge der Executors, die eine positive Antwort liefern, prüft das Kommando, ob sie die Instruktionen auf Basis des aktuellen GUI Kontexts ausführen können.

  • Alle Executors, denen auch dies möglich ist, erhalten die Instruktion schließlich zur Ausführung. Alternativ könnte an dieser Stelle noch eine Auswahl getroffen werden, sodass letztlich nur ein einziger Executor die Ausführung übernehmen darf.



[35] Das hier beschriebene Kommando wird beispielhaft von der Klasse InstructionExecutorCommand implementiert.

[37] Der jadice document platform liegen verschiedene beispielhafte InstructionExecutor Implementationen bei, die als Ausgangsbasis für integrationsspezifische Entwicklungen dienen können.

[jadice document platform Version 5.5.12.1: Dokumentation für Entwickler. Veröffentlicht: 2021-08-17]