Codegenerierung Modellgetriebene Softwareentwicklung bei der IBYKUS AG Theorie – Teil 5: Codegenerierung Dr. Steffen Skatulla IBYKUS AG 03.05.2010 1 Codegenerierung Inhalt Teil 5: Codegenerierung • • Prinzipien, Einordnung und Abgrenzung Techniken der Codegenerierung – – – – • Template Engines: JET, XSLT „Ausprogrammierte“ Generatoren OAW-Xpand IBYKUS Techniken Best Practices 03.05.2010 2 Codegenerierung Codegenerierung • • • Model-to-Code-Transformation (M2C) Erzeugung von (Programm-)Code aus Modellen Erzeugen Code für eine bestimmte Plattform plattformspezifisch • Funktionen für Codegenerierung – – – – 03.05.2010 Lesen/Abfragen des Input-Modells Umformen der Informationen Konkatenieren / Ersetzen von Text Schreiben in Output-Dateien 3 Codegenerierung Codegenerierung • Für Generierung / Transforamtion nötig Modell (abstrakt) „Ausprogrammierte“ Transformation (Konkretisierung) Modell / Code (weniger abstrakt) – Widerverwendbarkeit? – Verständlichkeit? 03.05.2010 4 Codegenerierung Codegenerierung • Für Generierung / Transforamtion nötig – Template – Transformations-Engine • Separiert vs. integriert Modell (abstrakt) Template (Konkretisierung) Trafo-Engine Modell (abstrakt) „Ausprogrammierte“ Transformation (Konkretisierung) (allg. wiederverwendbar) Modell / Code (weniger abstrakt) Modell / Code (weniger abstrakt) – Widerverwendbarkeit? – Verständlichkeit? 03.05.2010 5 Codegenerierung Codegenerierung • Für Generierung / Transforamtion nötig – Template – Transformations-Engine • Separiert vs. integriert vs. generiert Modell (abstrakt) Template (Konkretisierung) Trafo-Engine Modell (abstrakt) Modell (abstrakt) „Ausprogrammierte“ Transformation (Konkretisierung) Generierte Transformation Modell / Code (weniger abstrakt) Modell / Code (weniger abstrakt) Trafo-Modell (Konkretisierung) Trafo-Generator (allg. wiederverwendbar) Modell / Code (weniger abstrakt) – Widerverwendbarkeit? – Verständlichkeit? 03.05.2010 6 Codegenerierung Wie „tief“ soll generiert werden? • Die Nutzung leistungsfähiger Plattform-Infrastruktur kann die Generierung der Anwendung wesentlich vereinfachen – Ziel der Generierung ist Code, der Programmbibliotheken, Frameworks, Middleware benutzt – Keine „Durchgenerierung“ bis zum Bytecode • Aber es gibt auch Gründe bei Bedarf „tiefer“ zu generieren Modell Generierung Generierung auf Frameworkbasis Bauteilvorlagen Code mit Code auf Frameworkbasis Spezialbausteinen Framework mit Universal-Bausteinen Programmiersprache, Basisbibliotheken, … 03.05.2010 7 Codegenerierung Was ist mit Generierung möglich? • Performance und geringe Codegröße trotz Flexibilität – Flexible Frameworks arbeiten oft dynamisch / interpretativ – Dadurch sind sie tendenziell weniger performant und umfangreicher – Flexible Generierung • Statischen Codes Performance • Nur des benötigten Codes geringe Codegröße • Analysierbarkeit – Statischer generierter Code ist besser analysierbar als dynamische / interpretative Frameworks • Fehlerfrüherkennung – Bei statische generierten Typen treten Fehler zur Compilezeit auf und nicht erst zur Laufzeit, wie bei dynamischer Typisierung im Framework • Einschränkungen der Programmiersprache – Z.B. Einführung von objektorientierten Konzepten in die Modellierung auch bei der Generierung in nicht-objektorientierte Programmiersprachen 03.05.2010 8 Codegenerierung Was ist mit Generierung möglich? • Aspekte – Querschnittsfunktionalität läßt sich zentral an einer Stelle modellieren und bei der Generierung in alle relevanten Stellen einweben, auch ohne Aspektorientierte Programmiersprachen Aspekt-Modell Modell Generator Java-Methode Querschnittsfunktionalität Funktion Querschnittsfunktionalität 03.05.2010 9 Codegenerierung Generierung mit Templates • Template – Lückentext – Angabe, wie Lücken zu füllen sind • Template-Engines aus der dynamischen Webprogrammierung – JSP, PHP, … <html> <head><title>First Example</title></head> <body> <h3>Hello World-JSP</h3> Your browser is: <%= request.getHeader("User-Agent") %><br> Your IP address is: <%= request.getRemoteAddr() %> </body> </html> 03.05.2010 Konkatenieren von Text und Schreiben in Dateien Verarbeitung von Informationen Schreiben in mehrere Zieldateien (keine explizite Steuerung in welche) Unterstützung beim Lesen/Abfragen/Navigieren von Modellen 10 Codegenerierung Generierung mit Templates: Java-basierte Template-Engines## Velocity Hello World • Verbreitete Vertreter – JET, Velocity, Freemarker, … <html> <body> #set( $foo = "Velocity" ) ## followed by Hallo $foo Welt! </body> </html> <%@ jet package="hello" imports="java.util.*" class="XMLDemoTemplate" %> <% List elementList = (List) argument; %> <?xml version="1.0" encoding="UTF-8"?> <demo> <% for (Iterator i = elementList.iterator(); i.hasNext(); ) { %> <element><%=i.next().toString()%></element> <% } %> </demo> • Bewertung 03.05.2010 Konkatenieren von Text und Schreiben in Dateien Verarbeitung von Informationen Unterstützung beim Lesen/Abfragen von Modellen Aber nicht optimiert auf Navigation auf Objekt-Netzen (Pfadausdrücke) Schreiben in mehrere Zieldateien (keine explizite Steuerung in welche) 11 Codegenerierung Generierung mit Templates: XSLT • Für Modelle mit XML-Repräsentation Pfadunterstützung /class/attribute[@type="String"] XSLT nicht statisch typisiert Fehler im Modell erst zur Laufzeit Komplexe Transformatioen werden sehr schnell schlecht lesbar 03.05.2010 <class name="Person"> <attribute name="name" type="String"/> <attribute name="age" type="int"/> </class> <xsl:template match="/class"> public class <xsl:value-of select="@name"/> { <xsl:apply-templates/> } </xsl:template> <xsl:template match="attribute"> public <xsl:value-of select="@type"/> <xsl:value-of select="@name"/>; </xsl:template> public class Person { public String name; public int age; } 12 Codegenerierung Generierung mit Templates: Kriterien für eine gute Template-Sprache • Kriterien für eine gute Template-Sprache – – – – 03.05.2010 Unterstützung von Modularisierung Kompakte Syntax Kontrollstrukturen: Bedingungen, Schleifen, … Komfortable, statisch getypte, effiziente Abfrage- und Navigationssprache für Modell 13 Codegenerierung Generierung mit imperativen Programmiersprachen • Java, C++, … bringen mit – Kontrollstrukturen, statische Typisierung, Modularisierbarkeit • Sinnvolle Technik – Klassen für Zielstrukturen – Objekte werden beim Ablesen des Modells erstellt, parametrisiert, vernetzt – Codeerzeugung über verschachtelte toString()-Methodenaufrufe • Probleme – Keine mehrzeiligen Literale String s = "Das ist Zeile eins \n" + "Das ist Zeile zwei \n"; • Zeilenumbruch systemspezifisch \n, \r, \r\n • Verteilung auf Zeilen erfordert Verkettung – Anführungszeichen müssen escaped werden "name=\"" + name + "\""; – Konkatenation nicht implizit sondern mit +-Operator 03.05.2010 14 Codegenerierung Generierung mit imperativen Programmiersprachen – Aufwändige Interation, insbesondere bei variabel tiefer Rekursion public void loopChildren(Node node) { for (Node child : node.getChildren()) { // do something loopChildren(child); } } – Metamodell muß als Java-Klassen zur Verfügung stehen • Entweder dynamische Klassen nicht statisch typisiert, umständlich in Handhabung • Oder Generierung statischer Klassen aus Metamodell aufwändig 03.05.2010 15 Codegenerierung Template-Sprache Xpand • Aus openArchitectureWare «IMPORT metamodel» «EXTENSION my::generator::Extensions» • Eigenschaften «DEFINE javaBean FOR Entity» «FILE name+".java"» public class «name» { «EXPAND property FOREACH attributes» } «ENDFILE» «ENDDEFINE» – Template-Sprache (Lückentext) – OO-artige Modularisierung – Stringkonkatenation durch hintereinander schreiben – Typsystem nicht an Hostsprache gekoppelt 03.05.2010 «DEFINE property FOR Attribute» public «type» «name»; public «type» «getterName()»() { return «name»; } public void «setterName()» («type» «name») { this.«name» = «name»; } «ENDDEFINE» 16 Codegenerierung Template-Sprache Xpand • Metamodell importieren 03.05.2010 «IMPORT metamodel» 17 Codegenerierung Template-Sprache Xpand • 2 Templates – Name – Optionale Parameterliste – Für bestimmten Typ aus Metamodell (statische Typisierung) «IMPORT metamodel» «DEFINE javaBean() FOR Entity» «ENDDEFINE» «DEFINE property() FOR Attribute» «ENDDEFINE» 03.05.2010 18 Codegenerierung Template-Sprache Xpand • 2 Templates – Name – Optionale Parameterliste – Für bestimmten Typ aus Metamodell (statische Typisierung) • • Festlegen in welche Datei geschrieben wird Text im DEFINE-Block wird in jeweils offene Datei geschrieben «IMPORT metamodel» «DEFINE javaBean FOR Entity» «FILE name+".java"» public class { } «ENDFILE» «ENDDEFINE» «DEFINE property FOR Attribute» «ENDDEFINE» 03.05.2010 19 Codegenerierung Template-Sprache Xpand • 2 Templates – Name – Optionale Parameterliste – Für bestimmten Typ aus Metamodell (statische Typisierung) • • • Festlegen in welche Datei geschrieben wird Text im DEFINE-Block wird in jeweils offene Datei geschrieben Ausdrücke in „Franzosen“ (französische Anführungszeichen) werden ersetzt 03.05.2010 «IMPORT metamodel» «DEFINE javaBean FOR Entity» «FILE name+".java"» public class «name» { } «ENDFILE» «ENDDEFINE» «DEFINE property FOR Attribute» «ENDDEFINE» 20 Codegenerierung Template-Sprache Xpand • Aufruf weiterer Templates mi «EXPAND templateName FOR expression» – Z.B. mit Loop-Ausdruck FOREACH für Listen «IMPORT metamodel» «DEFINE javaBean FOR Entity» «FILE name+".java"» public class «name» { «EXPAND property FOREACH attributes» } «ENDFILE» «ENDDEFINE» «DEFINE property FOR Attribute» «ENDDEFINE» 03.05.2010 21 Codegenerierung Template-Sprache Xpand • Ausdruckssprache – Sprachübergreifende Expression-Language & -Engine – OCL-artig – Funktional – Mengenwertig – Navigierend – Closures • Funktionen höhrerer Ordnung • Nehmen als Parameter andere Funktionen auf • Z.B. für Loops über Listen «IMPORT metamodel» «EXTENSION my::generator::Extensions» «DEFINE javaBean FOR Entity» «FILE name+".java"» public class «name» { «EXPAND property FOREACH attributes» } «ENDFILE» «ENDDEFINE» «DEFINE property FOR Attribute» public «type» «name»; public «type» «getterName()»() { return «name»; } public void «setterName()» («type» «name») { this.«name» = «name»; } «ENDDEFINE» name getterName() myClass.attributes.select(a|a.type=='String') myClass.attributes.select(a.name|a.type=='String') 03.05.2010 22 Codegenerierung Template-Sprache Xpand • Statische Typisierung auf Basis des importierten Metamodells Fehler zur Compilezeit • • Möglich durch eigenes, von Xpand getrenntes Typsystem der Expression-Engine Mit Java wäre das nicht möglich «IMPORT metamodel» «EXTENSION my::generator::Extensions» «DEFINE javaBean FOR Entity» «FILE name+".java"» public class «name» { «EXPAND property FOREACH attributes» } «ENDFILE» «ENDDEFINE» «DEFINE property FOR Attribute» public «type» «name»; public «type» «getterName()»() { return «name»; } public void «setterName()» («type» «name») { this.«name» = «name»; } «ENDDEFINE» EObject obj = ... if ("Entity“.equals(Obj.eClass().getName)) { ... } 03.05.2010 23 Codegenerierung Template-Sprache Xpand • Extensions – Operationen, die dynamisch an einen Typ angehängt werden können – Z.B. getterName() an den Typ Attribute aus dem importierten Metamodell – Extensions werden in eigener Datei definiert my::generator::Extensions my/generator/Extensions.ext import metamodel; «IMPORT metamodel» «EXTENSION my::generator::Extensions» «DEFINE javaBean FOR Entity» «FILE name+".java"» public class «name» { «EXPAND property FOREACH attributes» } «ENDFILE» «ENDDEFINE» «DEFINE property FOR Attribute» public «type» «name»; public «type» «getterName()»() { return «name»; } public void «setterName()» («type» «name») { this.«name» = «name»; } «ENDDEFINE» getterName(Attribute this) : "get“ + name.toFirstUpper(); setterName(Attribute this) : "set“ + name.toFirstUpper(); 03.05.2010 24 Codegenerierung IBYKUS-Templates template:Z2M Test(csType="SDW") { parameter:para kmx(dataType="str" default="X"); parameter:in ty(nodeType="AP&TY"); parameter:push pad(nodeType="AP&PAD"); parameter:out sub(nodeType="SDW&subject"); parameter:out att(nodeType="SDW&attribute"); loop T(type="AP&TY" searchPattern="${{.ty}}") { choice:if C1(call="isNull" p1="${{.ty}}") { then T() { text T1(|begin_text| Das ist ein Text. Hier kommt etwas rein: ${{.kmx}}_${{T.name}}_${{P.name}}. |end_text|); }; else E() { ... }; }; }; }; 03.05.2010 25 Codegenerierung Best Practices • Generierter Code soll gut lesbar sein – Lesbarkeit für Debugging • Strukturierung • Formatierung • Kommentare – Referenzen ins Modell und zu Generatoren in Kommentaren (Location Strings) [2010-05-01 11:38:45] GENERATED FROM TEMPLATE SomeTemplate MODEL ELEMENT aPackage::aClass::SomeAttribute • Klare Trennung von generiertem und handgeschriebenem Code – – – – 03.05.2010 Protected Regions Source Cuts Dreistufige Vererbung … Plattformschicht Handgeschriebene, abstrakte Basisklasse Generische Schicht Generierte Klasse Anpassungsschicht Handgeschriebene Klasse 26 Codegenerierung Zusammenfassung • • Prinzipien, Einordnung und Abgrenzung Techniken der Codegenerierung – – – – Template Engines: JET, XSLT „Ausprogrammierte“ Generatoren OAW-Xpand IBYKUS Techniken • Best Practices • Als nächstes – Modellinterpretation 03.05.2010 27