Am Donnerstag und Freitag habe ich einen 2-tägigen Workshop zu openArchitectureWare besucht. In zwei Blogeinträgen berichte ich über das Gelernte. (Zu Teil 1)
Teil 2: Überblick über openArchitectureWare
OpenArchitectureWare ist eine Sammlung von Tools für die Modellgetriebene Software-Entwicklung. Die oAW ist Open Source, in Java implementiert und befindet sich gerade auf dem Weg in das Eclipse Modeling Framework. Schon jetzt gibt es für oAW eine gute Eclipse-Editorunterstützung
Die wesentlichen Modellierungskomponenten sind die Code-Generierung (M2T, Xpand), Modelltransformationen (M2M, Xtend), Validierung (Check) sowie die Unterstützung durch grafische und textuelle Editoren.
oAW versteht eine ganze Menge von Modellen und Modellformaten. oAW berücksichtigt die Eigenheiten der von diversen Tool-Herstellern erzeugten UML 1 und 2 XMIs in einer Masse von Parsern und formt sie zu typisierten Modellen um. Seit einiger Zeit exportieren jedoch so gut wie alle Tools konformes EMF UML 2.0, das von oAW vollständig unterstützt wird.
Sprachen in oAW
Im Rahmen der oAW wurden drei neue Sprachen erfunden, die speziell darauf abgestimmt sind, aus Modellen andere Modelle, Source Code oder andere Artefakte zu generieren. Jede Sprache beleuchtet einen definierten Aspekt, alle verfügen jedoch über ein gemeinsames Typsystem, eine einheitliche Expression-Syntax und sie lassen sich teilweise untereinander aufrufen.
Eine ausführliche Referenz zu den drei Sprachen gibt es hier.
Xtend
Xtend ist eine in Ihrer Syntax an funktionale Programmiersprachen angelegte Sprache, die zur Erweiterung der durch oAW definierten Funktionsbiliothek dient.
In einer auf “.ext” endenden Datei werden Funktionen mit Rückgaben definiert. Etwas gewöhnungsbedürftig ist, das es kein return-Schlüsselwort gibt.
Eine Methode kann auch auf dem Typ des ersten Parameters aufgerufen werden. Definiert man also eine Methode foo(String), kann diese auf einem String direkt aufgerufen werden: “hello”.foo()
Einige Beispiele:
-
// Definiert eine Methode foo() für String String foo(String s): s.toUpperCase();
-
// Der Parameter this ist der Kontext für direkt aufgerufene Methoden String foo(String this): toUpperCase();
-
// Wenn expressions mit "->" gechained werden, ist das letzte Element der // Chain die Rückgabe. // Der Aufruf erfolgt über eine Entity: myEntity.prependName("Abstract") Entity prependName(Entity this, String prepend): setName(prepend + name) -> this;
Aus Extend kann zusätzlich auf statische Java-Methoden zugegriffen werden. Dazu dient das Schlüsselwort JAVA.
// Die Java-Methode und ihre Signatur muss voll qualifiziert werden String formattedToday(String format): JAVA myPackage.MyClass.myStaticTodayMethod(java.lang.String);
Ausführliche Referenz zu Xtend
Xpand
Xpand ist eine XSLT-ähnliche Template-Sprache, die jedoch auf die Generierung von Dateien spezialisiert ist. Neben einigen gewohnten Sprachkonstrukten wie foreach, if-then-else helfen defines und expands bei der Strukturierung der Templates.
Wie man es aus Template-Sprachen kennt, werden in die Ausgabe Codeblöcke hinein codiert. Dazu dienen die Guillements « und ».
Über das Schlüsselwort DEFINE werden Template-Methoden deklariert. Wie bei Xtend wird das Template an einen Typen (meist aus dem Metamodell) geknüpft. Die Methoden unterstützten Polimorphismus.
«DEFINE name[(parameterlist)] FOR type» ...code... «ENDDEFINE»
Mittels EXPAND werden diese Templates aufgerufen:
«EXPAND name[(parameterlist)] FOR|FOREACH expression» «REM»Kommentar: FOR ruft das Template auf dem Ergebnis der expression auf, FOREACH geht von einer Ergebnismenge aus und führt die Templates einzeln aus.«ENDREM»
Mit FILE wird der Output eines Bereiches des Templates in eine Datei umgelenkt.
«FILE "filename.java" [outlet]» /*Dieser Inhalt wird direkt in das file "filename.java" geschrieben. Über das outlet können zusätzlich Postprozessoren oder verschiedene Ausgabe- Verzeichnisse angesteuert werden.*/ «EXPAND JavaClass FOREACH model().allContents.typeSelect(Entity)» «ENDFILE»
oAW unterstützt protected regions, d.h. dass Teile des Generats beim nächsten Generieren nicht überschrieben werden und somit manuell modifiziert werden können. Diese definiert man mit PROTECT.
«PROTECT CSTART "<!--" CEND "-->" ID expression» // TODO: Hier bitte die Methode xy ausimplementieren throw new NotImplementedException(); «ENDPROTECT»
Wie bei den meisten Template- oder Scriptsprachen hat der Entwickler die Wahl zwischen Pest und Cholera: Soll das Generat schön aussehen, oder lieber das Template übersichtlich bleiben. Xpand bietet zwei Hebel, mit denen man dieses Problem in den Griff bekommt.
Mit einem “-” vor dem schließenden Guillement eines Script-Blocks lässt sich die Ausgabe der folgenden Whitespaces unterdrücken.
«FILE "test.txt" -» A ist der erste Buchstabe im Textfile. «"Und weiter? " -» B folgt noch in der selben Zeile. «ENDFILE»
Zusätzlich lassen sich für bestimmte Outlets Beautifier als Postprozessoren konfigurieren, die nachträglich z.B. alle Java-Klassen vernünftig formatieren.
«FILE "TestClass.java" javaOutlet» public class TestClass{ /* Gerade bei verschachtelten Templates, die Schlüsselwörte und Befehle ausgeben wäre es sehr aufwendig, alle Umbrüche, Einrückungen und Zeilenabstände perfekt zu kontrolieren. */ } «ENDFILE»
Dies war nur ein kleiner Auszug aus Xpand. Alle Xpand Schlüsselwörter und deren Syntax hier.
Check
Check ist eine an OCL angelehnte Sprache zur Validierung von Metamodellen oder anderen Objektbäumen. Baut man Code anhand von modellen auf, ist es wichtig, das diese formalen Regeln folgen und eindeutig sind. Diese Regeln werden mit check ausgedrückt. Besonders wichtig ist es, check bei Modell-zu-Modell-Transformationen zu verwenden, um sicherzustellen, dass das Zielmodell korrekt ist.
Einer Definition eines Fehlers oder einer Warnung für einen Typ folgen die Regeln, die nicht verletzt werden dürfen.
context type ERROR|WARNING "Message": rule_expression;
Beispiele:
-
context Class ERROR "Eine Klasse muss einen Namen besitzen!": name != null && name.lenght > 0;
-
context Entity IF isAbstract WARNING "Der Name abstrakter Entitäten sollte mit 'Abstract' beginnen.": name.startsWith("Abstract");
AOP in oAW
Die Sprachen Xtend und Xpand unterstützen Ansätze der Aspektorientierten Programmierung (AOP).
So kann man sich von außen um Templates und Extensions legen und die Kontrolle übernehmen. Das Schlüsselwort dazu ist in beiden Sprachen around.
Um die in Dateien “*.xpt” oder “*.ext” abgelegten Aspekte anzuwenden, konfiguriert man sogenannte advices.
Workflow
Als Start-Script für oAW dient ein Workflow Script das in XML beschrieben wird. Die Syntax erinnert ein wenig an Ant. In diesem Workflow werden Konfiguration, Transformationen, Generatoren, Aspekte usw. in aufeinanderfolgenden Schritten Konfiguriert.
oAW führt u.a. Komponenten für die Ausführung von Check, XPand, Xtend, Aspekte (Advices). Zur strukturierung kann man auch andere workflows aufrufen, oder mit Java eigene Komponenten erstellen.
Zwischen Komponenten werden Parameter über sog. Slot-Objekt übermittelt.
Cartridges
Cartridges sind komplette oAW-Pakete für bestimmte Anwendungsfälle. Sie bringen gewöhnlicherweise eine DSL sowie dazugehörige Metamodelle, Checks, Extensions und Generatoren.
Ein Beispiel ist die Hibenate Cartridge von Darius Jockel, mit dessen Hilfe sich Entities für die Persistenz mit Hibernate mittels UML2 modelieren lassen.
Auf der Fornax-Plattform sind viele Cartridges wie z.B. für EJB oder Spring zu finden.