CASE-Tools: Code Generation
Transcription
CASE-Tools: Code Generation
1 CASE-Tools: Code Generation Vortragender: Alexander Kullik 2 Gliederung ● ● ● ● ● ● ● ● Definition von code generation Hand coding vs. code generation Code generation skills Aktive Codegeneratoren Vorteile und Nachteile von Codegeneratoren Wahl der Generatorsprache Forward und reverse Engineering Die Tools – – – Rexml ERb Kodekopelli 3 Definition von Code generation "Ein Code Generator ist ein Programm zur Erzeugung von Quellcode" (Wikipedia) ●"Code generation is about writing programms that write programms"(Manning C.G.I.A.) ● – z.B. Compiler sind im weiteren Sinne auch Code Generatoren, werden aber heute nicht behandelt ● "Code generation is the technique of building code using programs. These programs can range from very small helper scripts, to grand creations that turn abstract models of business logic into complete applications. There is no one style of code generation application, they can work on the command line or using a GUI, they can build code for one or more languages at a time, they could build code once or multiple times. There are an unlimited variety of inputs and outputs. The unifying feature of code generation is that the output of the generator is code that an engineer would otherwise have to write by hand." (www.codegeneration.net) 4 Hand-coding vs. code generation ● Hand Coding – – – – – Qualität steigt Manuell anpassen Einzelnes bugfixing Ein unit test pro Klasse; ein unit test framework Compatiblity layer benötigt für: ● – ● Code Generator – – – – – Code -> neue Sprache/Framework Schemen können vom Code abweichen – Qualität bleibt gleich Nur Generatorupdate Bugfixing in template Kritisch; text Differenzing und Klassiche unit tests Kann Code für mehrere Sprachen/FW's erzeugen Schemen und Code gleichzeitig generiert 5 Code Generation Skills ● ● ● ● ● Text templates Regular expressions Parsing XML File and directory handling Command-line handling 6 Zwei high - level Kategorien ● passive – – – ● Erzeugen freies, editierbares Kodeset Generator übernimmt keine Verantwortung für Code "Wizards" in IDE's active – Generator übernimmt langfristig Verantwortung für den Code 7 Aktive Code Generatoren - Code Munger Source Code ● Dokumentationen ● ● ● CodeMunger OutputFile Doxygen Java Doc Ließt Konstanten oder Prototypen aus Datei 8 Aktive Code Generatoren - Code Munger 9 Aktive Code Generatoren - Code Munger 10 Aktive Code Generatoren - Code Munger am Beispiel von Java Doc ● ● ● ● Java - Datie -> HTML - Dokumentationsdatei parst nach Kommentaren der Form '/**... */' parst '@' oder '{@' in den Kommentaren z.B. – – @author name @param name description 11 Aktive Code Generatoren - Code Munger 12 Aktive Code Generatoren Inline Code Expander ● Source Code InlineCodeExpander Output Source Code Compiler Executable Ersetzt markierte Stellen z.B. durch SQL im Source Code -> verbesserte Übersichtlichkeit 13 Aktive Code Generatoren Inline Code Expander '.sqlc' file: int main( int argc, char *argv[] ) { < SQL select * from users > return 0; } Nach Aufruf des SQLC - Generators: #include "db.h" int main( int argc, char *argv[] ) { DBHandle *db_handle = db_connect(); DBQueryDara *db_data = db_db_query( db_handle, "select * from users" ); for( int record = 0; record < db_data->length; record++ ) { // fetch and process data } return 0; } Man erhält '.c' - file 14 Aktive Code Generatoren Mixed - Code Generator Source Code ● ● MixedCodeGenerator Output Source Code Compiler Executable Testcase building Database access code 15 Aktive Code Generatoren Mixed - Code Generator '.sqlc' file: int main( int argc, char *argv[] ){ // SQL: select * from users // SQL end return 0; } Nach Aufruf des SQLC - Generators: #include "db.h" int main( int argc, char *argv[] ) { // SQL: select * from users DBHandle *db_handle = db_connect(); DBQueryDara *db_data = db_db_query( db_handle, "select * from users" ); for( int record = 0; record < db_data->length; record++ ) { // fetch and process data } // SQL end return 0; } Man erhält '.c' - file ABER Kommentare bleiben erhalten => Ersetzung bei Aufruf erneut 16 Inline - Code Expander (ICE) vs. Mixed - Code Generator (MCG) ● ICE – – – ● Debugging gegen den Output Input nicht kompilierbar Tags im Output durch Kode ersetzt ● Keine visuelle Korrespondenz zwischen Tags und Kode MCG – – – Debugging gegen den Input Input kompilierbar (Kommentartags) Tags und Kode nebeneinander ● Visuelle Korrespondenz 17 Aktive Code Generatoren Partial-Class Generator ● Definition File Templates Partial-Class Generator ● BaseClass Sourcecode Compiler Executable DerivedClass SourceCode ● Basis Daten als Leitlinie für User Interfaces RPC layers (überschreibbar) Data access classes überschreibbar um business logic hinzuzufügen 18 Aktive Code Generatoren Partial-Class Generator Das Definition File fields.txt: Person:first,middle,last output.java: public class PersonBase { protected String _first; protected String _middle; protected String _last; public PersonBase(){ _first = new String(); _middle = new String(); _last = new String(); } public String getFirst() { return _first; } public void setFirst( String value ) { _first = value; } public String getMiddle() { return _middle; } public void setMiddle( String value ) { _middle = value; } public String getLast() { return _last; } public void setLast( String value ) { _last = value; } } 19 Aktive Code Generatoren Partial-Class Generator Der Generator in Ruby: require "erb/erb" File.open( "fields.txt" ).each_line { |line| ( class_name, field_text ) = line.split( ":" ) fields = field_text.strip.split( "," ) erb = ERb.new( File.open( "field_class.template.java" ).read ) new_code = erb.result( binding ) print "Creating #{class_name}Base.java\n" File.open( "#{class_name}Base.java", "w" ).write( new_code ) } Das ERb Template: public class <%= class_name %>Base { <% fields.each { |field| %> protected String _<%= field %>;<% } %> public <%= class_name %>Base() { <% fields.each { |field| %> _<%= field %> = new String();<% } %> } <% fields.each { |field| %> public String get<%= field.capitalize %>() { return _<%= field %>; } public void set<%= field.capitalize %>( String value ) { _<%= field %> = value; } <% } %> } 20 Aktive Code Generatoren Partial-Class Generator 21 Aktive Code Generatoren Tier Generator ● Definition File Templates Tier Generator Output Source Code Compiler Executable Z.B. Web application server: Erzeugt eine von den n-tier Ebenen (database access, business logic oder user interface) vollständig 22 Aktive Code Generatoren Tier Generator 23 Code generation workflow ● Ohne Generator ● Mit Generator 24 Vorteile von Codegeneratoren ● Qualität – ● Consistenz – – ● Leicht drauf aufzubauen Gute Optik Produktivität – ● In direkter Beziehung zur Qualität der Templates Flexibles Design Abstraktion – – Plattformunabhängigkeit Verschiedene Sprachen 25 Nachteile von Codegeneratoren ● ● ● ● ● Lange Anlaufzeiten Hoher Planungsoverhead Stabile Muster als Anwendungsziel wichtig Instandhaltungskosten Dokumentieren und Leute einarbeiten 26 Wahl der Generatorsprache ● Wichtig: – – – – – ● Quellcodeproduzierende Sprache und Quellcode sollten verschieden sein Lesen, parsen, suchen Leichtverwendbare, mächtige Templates Eingebautes XML - Handling Einfaches File/Directory Handling Unwichtig: – Language performance 27 Kodegeneratorsprachen 28 Forward/Reverse Engineering bezüglich UML ● Forward Engeneering – – ● Reverse Engineering – – – ● UML - Diagramm => Source Code Normalerweise für eine spezielle Sprache oder ein Sprachenset Genaue Gegenteil von Forward Engineering Lädt den Quellcode Rekonstruiert die Diagramm - Struktur Round-trip Engineering – Ständiges Updaten durch Forward/Reverse Engineering 29 Rexml - ein XML-Parser für Ruby ● XML - File "names.xml" <names> <name><first>Charles</first><last>Bronson</last></name> <name><first>Chuck</first><last>Norris</last></name> <name><first>Stephen</first><last>Segal</last></name> </names> ● Ruby - Script require 'rexml/document' doc = REXML::Document.new( File.open( "names.xml" ) ) doc.root.each_element( "name" ) { |name_obj| first = name_obj.elements[ "first" ].text last = name_obj.elements[ "last" ].text print "#{first} #{last}\n" } 30 "ERb" - ein Templatetool für Ruby ● Ruby Script require 'erb/erb' names = [] names.push( { 'first' => "Jack", 'last' => "Herrington" } ) names.push( { 'first' => "Lori", 'last' => "Herrington" } ) names.push( { 'first' => "Megan", 'last' => "Herrington } ) File.open( ARGV[0] ) { |fh| erb = ERb.new( fh.read ) print erb.result( binding ) } ● Das Template <% names.each { |name| %> Hello <%= name[ 'first' ] %> <%= name[ 'last' ] %> <% } %> 31 Kodekopelli ● ● ● Geschrieben in Ruby Benutzt ERb - Templates Quellcodeerzeugung in jeder Sprache – ● Konzepte: – – – ● ● Z.B. flexible Massenproduktion von JSP's DRY - Don't Repeat Yourself! Do it well. Do it once. Let Kodekopelli do the rest. Ideomatisch zu Tools wie Ant, Nant und Rake Aktiv oder passiv? Tier Code Generator 32 Kodekopelli Konfigurationsfile <kodekopelli> <property ... /> <attribute ... /> <filegroup> <file> . . . </file> </filegroup> </kodekopelli> <!-- exactly 1 <!-- 0 or more <!-- 0 or more <!-- 1 or more <!-- 1 or more --> --> --> --> --> 33 Ende Danke fürs Zuhören!