Reflection
Advanced Patterns and Frameworks
Advanced Patterns and Frameworks
-
- 1 / 8
-
Lernkarten
Reflection-Pattern
Das Reflection-Pattern definiert einige Komponenten die bei einem Reflection-System involviert sind. Das Pattern ist unabhängig von der Programmiersprache. Das Pattern findet auch bei den von den Sprachen zur Verfügung gestellten Reflection-API’s, wobei die Metainformationen in diesem Fall vom Compiler generiert werden.
Beim Pattern ist zu beachten, dass die API nicht nur lesend ist, auch wenn dies von vielen sprachgegebenen APIs der Fall ist. Beim Reflection-Pattern ist das Anpassen von den Metaobjekten zur Laufzeit durchwegs erlaubt und könnte z.B. im Falle einer Neukonfiguration erfolgen.
Siehe die Struktur des Patterns in der Abbildung. Die Struktur der Anwendung wird primär in zwei Levels geteilt. Im Base-Level ist die Anwendungslogik, diese wird im Meta-Level beschrieben.
Die Objekte im Base-Level werden durch Metaobjects im Metal-Level beschrieben, welche die Informationen kapseln. In Sprachspezifischen Reflection APIs handelt es sich bei den Metaobjects z.B. um Klassen, Attribute, Properties, Methoden sowie die Hierarchie.
Auf die Metainformationen kann lesend sowie schreibend über das Metaobject Protocol (MOP) zugegriffen werden (z.B. Object.getClass, Class.forName). Dieses bietet eine Schnittstelle für das Manipulieren Metaobjects.
Erkläre die Begriffe Introspection und Intercession
Bei Sprachbezogener Reflection werden noch die Begriffe Introspection und Intercession.
Bei der Introspection werden z.B. die Eigenschaften eines Objektes abgefragt, Methoden, Attribute, implementierte Klassen.
Bei der Intercession werden die Eigenschaften eines Objektes verändert. In Java ist das nicht so einfach möglich, bei Skriptsprachen stellt dies meist kein Problem dar.
Type Object
Type-Object ist ziemlich verbreitet, jedoch ist man sich hierbei nicht bewusst, dass es sich um Reflection handelt. Bei Type Object müssen Objekte gruppiert / kategorisiert werden, wobei das Verhalten der Objekte auch von deren Kategorie abhängt. Die Kategorien sind zur Compilezeit nicht bekannt.
Vorteile Der Hauptvorteil des Patterns ist, dass neue Kategorien vom Benutzer selbst hinzugefügt werden können, ohne dass Änderungen am Code notwendig werden. Dadurch wird auch eine Unmenge an Kategorie-Subklassen vermieden, welche ansonsten notwendig wären. Das Pattern lässt sich auch kaskadieren. Es können Type-Objects für Type-Objects
definiert werden.
Nachteile Durch die Indirektion wird die Effizienz verschlechtert. Zudem kann es Verwirrend sein, da nicht sämtliche Informationen in einem Objekt sind.
Property List
Ist eine Liste mit Namen und die dazugehörige Werte (z.B. wie in JSON)
Property-Lists sind dann angebracht, wenn flexible Methoden-Parameter oder Attribute benötigt werden. Z.B. wenn der Benutzer eigene Attribute definieren kann. Property Lists sind auch dann nützlich, wenn Attribute zur Laufzeit hinzugefügt und wieder entfernt werden müssen. Das Pattern wird nicht benötigt, wenn die Sprachen bereits genügend flexibel sind (z.B. Javascript).
Lösung Dem Objekt wird ein Attribut mit einer Property-List hinzugefügt oder eine Methode akzeptiert eine Property-List als Argument. Die Property-List stellt eine Liste mit Key-Value Paaren dar, wobei bei denWerten nur primitiveWerte erlaubt sind. Eine Property-List kann z.B. einfach mittels einer HashMap umgesetzt werden.
Vorteile
Ein bestehendes Objekt kann erweitert werden, ohne dass es die Identität verliert (z.B. durch kopieren). Da die Properties als Liste gespeichert sind, kann einfach darüber iteriert werden, ebenso kann die Persistenz einfach bewerkstelligt werden. Clients können ein Objekt dynamisch erweitern, ohne dass dies für sämtliche Objekte gilt. Dies erlaubt auch das dynamische übergeben von Argumente, welche zum Designzeitpunkt nicht bekannt waren (wie beispielsweise Javascript options hash).
Anything
Anything ist eine Erweiterung von Property-List. Es unterstützt neben primitiven Datentypen auch ganze Objekt-Strukturen sowie Arrays als Werte (rekursive-Property-List). Eine mögliche Repräsentation von Anything ist z.B. JSON. Anythings sind ideal für Konfigurationen sowie für den Datenstransfer.
Probleme
Anything löst die selben Probleme wie die Property-List, jedoch erlaubt es auch die Übermittlung von Datenstrukturen über das Netzwerk (JSON). Ein Anything erlaubt auch die Entkopplung der Daten von einer Klassenversion. Die Daten bleiben Konstant auch wenn die Klassenversion ändert.
Lösung
Es muss ein Datentyp definiert werden, welcher selbst beschreibend ist. Für die Übermittlung oder manuelle Konfiguration soll eine einfache, vom Menschen lesbare externe Repräsentation verwendet werden. Eine mögliche Struktur eines Anything ist in der Abbildung abgebildet.
Nachteile
Durch diese Struktur ist es nicht mehr möglich heraus zu finden, ob einen Wert immer noch benötigt wird oder nicht. Zudem handelt es sich mehr um Daten als richtige Objekte. Daher können Kontextinformationen verloren gehen.
Extension Interface
Problem Ein allgemeines Problem beim Designen von Interfaces ist, dass diese stabil gehalten werden sollten. Da dies jedoch nicht immer möglich ist, muss eine Möglichkeit geschaffen werden, sodass Interfaces nachträglich noch erweitert werden können. Das Ziel sollte sein, dass neue Funktionen hinzukommen können, ohne dass der Client neu kompilieren muss (somit darf keine Schnittstelle ändern). Das hinzufügen einer neuen Schnittstelle sollte einfach sein und weder das bestehende System destabilisieren noch Interfaces überfüllen.
Lösung
Die Idee ist, dass jede Komponente verschiedene Rollen haben kann. Eine Rolle wird definiert aus zusammengehörenden Methoden. Jede Rolle wird durch ein Extension Interface definiert. Eine Rolle könnte z.B. ein IManagedObject sein, mit welchem verschiedene Eigenschaften eines Objektes ausgelesen sowie gesetzt werden können. Eine zweite Rolle könnte IConnection sein, welche das herstellen oder trennen einer Verbindung erlaubt. Der Client arbeitet nur mit den Extension Interfaces, welche ihm die benötigten Funktionalitäten anbieten. Die Komponente bietet eine Methode an um eine spezifisches Extension-Interface zu erhalten, insofern dies vorhanden ist. Die Implementierungen der Extension Interface kann entweder direkt auf der Klasse erfolgen, oder aber als
separate Inline-Klassen. Der Vorteil von Inline-Klassen ist, dass neue Funktionalitäten ohne Änderungen der Signaturen möglich sind. Wird das Interface auf der Klasse selbst implementiert, wird dadurch die Signatur der Komponente geändert.
Für die Erstellung einer Komponente gibt es für jeden Typ eine ComponentFactory, mit welcher eine Komponente erstellt werden kann. Das Root Interface definiert diejenigen Methoden, welche für sämtliche Extension Interfaces gelten. Es muss mindestens die getExtension Methode definieren, mit welcher ein spezifisches Extension Interface ausgelesen werden kann.
WAM
WAM steht für Werkzeug, Automat, Material. Dahinter versteckt sich eine komplette Entwicklungsmethodik. Der Fokus liegt aber auf den o.g. Metaphern, die sehr gut mit der XP SystemMetapherharmoniert. Nach WAM sucht man nach geeigneten Materialien, Werkzeugen und Automaten, um das System für Entwickler und Anwender verständlich zu beschreiben.