Seiten

Freitag, 2. August 2013

Grundgedanke: Warum CDI

Grundgedanke: Warum CDI? (Wiki)

CDI als eine Technik die auf der SE als auch auf der EE Seite zur Verfügung steht ist ein mächtiges Werkzeug um Quelltext in einer Anwendung zu entkoppeln.

Der modulare Aufbau kann auf einfache Art und Weise unterstützt und bei Alt-Anwendungen eingeführt werden.

kürzere Notation?
Manchmal ist die Notation per Inject kürzer. Sobald allerdings die einzelnen Qualifier dazukommen, ist meist der Aufwand zum Aufruf eines Konstruktors kaum unterschiedlich.

lösen von statischen Abhängigkeiten?
Dieser Punkt ist einer der Wesentlichen. Wie kann man zur Entwicklungszeit die Abhängigkeiten zu den anderen Projektmodulen möglichst gering halten?
Gehen wir von der Definition einer Liste aus. Als Rückgabewert einer Methode wird die List verwendet.

Definition Rückgabewert

image

Damit sind nachfolgende Aufrufer nicht mehr an die Implementierung der List gebunden. In der Methode jedoch besteht meist die Abhängigkeit zu der entsprechenden Implementierung obwohl auch das meist nicht notwendig ist.

Erzeugen der Liste

image

Gehen wir davon aus, dass keine spezifischen Methoden der ArrayList verwendet werden. Selten werden Methoden wie z.B. trimToSize() verwendet. Somit ist die statische Abhängigkeit zu der ArrayList nicht notwendig. Sollte sich zur Laufzeit herausstellen, das die Wahl dieser Implementierung nicht optimal gewesen ist, muss der Quelltext angepasst und neu verteilt werden. Mit std SE Mitteln kann man das durch entsprechende Factories lösen. Beispielhaft soll hier folgende Implementierung verwendet werden.

Definition ListFactory

image

Der Entwickler selbst schreibt nun seinen Quelltext unter Verwendung der Factory. Die Factory sollte unter Umständen immer neu erzeugt werden, um Nebenläufigkeitsprobleme sofort auszuschliessen. Selbstverständlich kann auch die Factory threadsave programmiert werden, im schlimmsten Fall mit den Schlüsselwort synchronized.

Verwendung ListFactory

image

Bisher wurde nun die statische Abhängigkeit zur ArrayList verhindert, die Entscheidung eine ArrayList zu nehmen ist jedoch immer noch expliziet gefallen.

Umgehen kann man das durch die Verwendung der ListFactory. 

Die Implementierung der ListFactory selber hat auch wieder die statischen Abhängigkeiten zu allen vorgesehenen Implementierungen. 

Der nächste Schritt kann ein ContextRsolver sein, der in die Factory eingebunden wird und zur Laufzeit die Wahl der Implementierung trifft.

Der ContextResolver wird entweder beim Methodenaufruf übergeben, oder bei der Initialisierung der Factory erzeugt/übergeben/geholt.

Möchte man nun die Factory so erstellen, das diese wiederum nicht statische Abhängigkeiten zu den jeweiligen Contexten bzw Implementierungen der Liste hat, muss eine Registry gebaut werden.

Dort kann man zur Laufzeit die jeweiligen Implementierungen registrieren und für eine Auflösung zur Verfügung stellen.

Spätestens ab diesem Zeitpunkt wird die Implementierung aufwendig, da man entweder diesen Mechanismus für alle Implementierungen vorhalten muss, oder eine generische Implementierung notwendig ist.

Hier Hilft CDI durch seine Konzepte, ohne das man sich mit der Basisimplementierung der Infrastruktur beschäftigen muss. 

 

Wie ist nun die Lösung mittels CDI?

Für den Entwickler sieht die Verwendung exemplarisch (CDILegacyTest) wie folgt aus.

Def List per CDI

image

Die Verwendung erfolgt wie gewohnt. Das AnnotationsLiteral CDILegacyTest gibt an, welcher Producer zu wählen ist.

Def ListProducer

image

Fertig sind wir.

dynamische Rekonfiguration?

CDI stellt eine sehr angenehme Basis zur Erzeugung dynamisch rekonfigurierbarer Systeme dar. Das Konzept der Instance<T> ist hier der Einstiegspunkt.

In der Definition der Attribute wird der Proxy Instance<T> verwendet.

Def List-Instance

image

Zu dem Zeitpunkt wenn auf die Variable zugegriffen werden muss, wird per get() die konkrete Implementierung geholt.

Verwendung der Liste

image

Damit kann die Entscheidung von der Erzeugung der verwendenden Instanz auf den Zeitpunkt der Verwendung verschoben werden.

In diesem Moment sollten im System hinreichend Informationen zur Verfügung stehen um die richtige Implementierung wählen zu können. Das Konzept basiert auf einem ContextResolver.

In diesem werden die Zustandsinformationen der Laufzeitumgebung, des Benutzers und was immer notwendig ist aggregiert und führen zu einer deklarativen Entscheidung.

Das Ergebnis ist ein umgebungsspezifisches AnnotationsLiteral mit dessen Hilfe die zur Verfügung stehenden Producer ausgewählt werden. Fertig ist das dynamisch rekonfigurierbare System.

Die Implementierung des ContextResolvers kann wiederum lean selektiert werden (Zwinkern)