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!