Sonntag, 27. Juli 2008

Gelegenheit macht Generierung

Ich muß bekennen, Routineentwicklungsaufgaben finde ich langweilig und meist nicht wert, dafür aufzustehen. Aber für langweilige Aufgaben sind doch die Maschinen erfunden worden. Also warum nicht den Computer die Arbeit machen lassen. Das ist der Grund, warum ich zum überzeugten Metaprogrammierer geworden bin.

Aber Vorsicht: Metaprogrammierung macht süchtig. Schon die Jungs in der Zeit von Flower power haben nicht nur LSD eingeworfen. Einige waren auch - wie man hört - süchtig nach M4. Dabei handelt es sich um einen vielseitigen Makroprozessor, der auch zur Codegenerierung verwendet wird. Leute, die mal sendmail konfiguriert haben, wissen, von welchem Werkzeug ich schreibe.

Die Kanonen: MDA und DSLs

Das ist zunächst MDA. MDA steht für "Model Driven Architecture", wobei mir niemand bekannt ist, der erklären kann, wie es zu dem "A" dabei gekommen ist. Die Architektur steckt im Modell und was getrieben werden soll ist die Generierung eines fertigen Systems. Der MDA-Ansatz wird von der OMG vorangetrieben, die uns CORBA und UML gebracht hat. Die Idee dabei ist, ein Modell basierend auf dem UML-Metamodell zu erstellen und daraus über eine oder mehrere Transformationen am Ende ausführbaren Code zu bekommen. Klingt kompliziert, ist kompliziert, aber es gibt einige vielversprechende Realisierungsansätze z.B. im Eclipse Modeling Project.

Der andere Ansatz sind DSLs. Hier baut man sich eine Grammatik auf für eine Sprache, die es möglichst einfach erlaubt, die für das konkrete Problem relevante Information zu erfassen. Dann kann man z.B. mit einem Parser Generator wie Antlr die Information in eine geeignete interne Darstellung einlesen, die es erlaubt mit einer Templateengine daraus Code zu erzeugen.

Besonders vorteilhaft sind diese Ansätze, wenn man unterschiedlichen Code aus derselben Information erzeugt. So kann man aus derselben Information die DDL für die Datenbankobjekte, die Zugriffsschicht für die Datenbank und die XSD für die XML-Darstellung erzeugen.

Die Spatzen

Oft ist es überhaupt nicht notwendig, sich über eine Sprache Gedanken zu machen, in der man die Information darstellen will. Vielmehr finden sich immer wieder strukturierte Dokumente, wie z.B. Excel-Tabellen, in der Information abgelegt ist, die man brauchen kann, um die Programme zu schreiben. Diese Dokumente sind viel zu schade um nur abgeschrieben zu werden. Notfalls müssen sie ein wenig nacheditiert werden. Danach geht es ans parsen.

Parsen

Dazu reicht in einfachen Fällen, wie csv-Dateien oft schon die split-Funktion, die in vielen Programmiersprachen zu finden ist. Bei Textdateien braucht man meist reguläre Ausdrücke. Manchmal hat man es auch mit XML-Dateien zu tun. Da tut es ein Sax-Parser.

Die Daten, die beim Parsen anfallen, müssen jetzt in geeignete Datenstrukturen untergebracht werden. Man kann da, wenn man gelehrt klingen will, von einem Meta-Modell sprechen. Meist braucht man aber nur wenige Listen und Dictionaries (Hashtable oder wie das Ding auch immer genannt wird), manchmal auch verschachtelt.

Transformieren

Gelegentlich wird nach dem ersten Einlesen noch eine einfache Transformation gebraucht, z.B. wenn Beziehungen zwischen den Elementen hergestellt werden müssen, wozu man die vollständig gefüllten Dictionaries braucht.

Generieren

Jetzt kann Code generiert werden. Es geht hier nicht um ganze Systeme, wie z.B. bei dem MDA-Ansatz. Vielmehr freuen wir uns schon über Codefragmente. Schön ist es, wenn es ein abgeschlossenes Dokument ergibt. Es ist aber auch nicht schlimm, wenn das Ergebnis noch nicht 100%ig ist. Wenn hunderte Zeilen Code generiert werden, dann aber 5 Zeilen manuell hinzugefügt werden, ist immer noch viel gewonnen.

Der so generierte Code kann auch manuell weiterverarbeitet werden. Dann kann der Codegenerator nach einmaliger Benutzung erst einmal eingemottet werden. Der Code ist aber sicher hilfreich als Vorlage für den nächsten Fall. Wenn sich die zugrundeliegenden Dokumente häufig ändern, lohnt es sich, darauf zu achten, daß man für die Einarbeitung der Änderungen die Codegenerierung nutzen kann.

Die Werkzeuge

Codegeneratoren kann man mit allen möglichen Werkzeugen bauen. Wenn die Daten in einer Exceltabelle vorliegen, benutze ich auch schon mal einen Excelausdruck und kopiere die resultierende Spalte. Wenn die Daten in einer Datenbank liegen, läßt sich Code auch mit SQL erzeugen.

Meist benutze ich eine Skriptingsprache. In früheren Jahren war das Perl. Heute benutze ich Ruby oder Python. Pythonprogramme sind meist lesbarer und haben die bessere Unterstützung für die Verarbeitung von XML. Ruby hingegen hat seine Stärken u.a. bei der Codegenerierung. Man kann leicht sehr mächtige Templates mit dem #{}-Ausdruck schreiben, der es erlaubt Codefragmente in das Template einzubetten. Damit sind auch rekursive Templates kein Problem.

Das Ergebnis

Mit recht wenig Aufwand kann man Code aus allen möglichen Dokumenten generieren. Abschreibefehler entfallen dabei. Der Code ist völlig konsistent. Dadurch fallen Feher schnell auf und entdeckte Fehler müssen nur an einer Stelle korrigiert werden.

Natürlich braucht es etwas Übung, aber es lohnt sich. Man bekommt nicht nur schneller bessere Ergebnisse. Die Arbeit macht auch mehr Spaß.

Keine Kommentare: