Der Modellierung der Domäne kommt während des Softwareentwicklungsprozesses
eine zentrale Bedeutung zu. Ziel des Modellierungsprozesses ist das Finden
von Abstraktionen, welche die Gegenstände, die Vorgänge und die
Zusammenhänge in der Domäne adäquat beschreiben. Eine wichtige
Qualität der gefundenen Abstraktionen ist die Flexibilität, mit
der sich diese Abstraktionen konfigurieren lassen, um möglichst viele
Sachverhalte und Beziehungen aus der Domäne abzudecken. Es ist unschwer
zu erkennen, daß Wiederverwendung besonders effizient auf der Modellierungsebene
erreicht werden könnte, würde die Wiederverwendung nicht dadurch
eingeschränkt, daß bei der Entwicklung konkreter Softwarekomponenten
bestimmte Entwurfs- und Implementierungsentscheidungen bereits zu einem
zu frühen Zeitpunkt getroffen werden und später unumkehrbar sind,
z.B. Programmiersprache, konkretes Persistenzmodell, bestimmtes Synchronisationsschema,
Zielplattform etc.
Was ist generative und komponentenbasierte Softwareentwicklung?
Generative Softwareentwicklung umfaßt die Entwicklung eines Domänenmodells
und seine Implementierung. Ein Domänenmodell definiert die Terminologie
einer Domäne. Die Semantik dieser Terminologie wird in der Regel in
Form von Konzepten und ihren Beziehungen festgelegt. Eine Domänenmodellimplementierung
stellt dagegen eine Verfeinerung dieses Modells dar, die die Überführung
einer mit Mitteln des Domänenmodells ausgedrückten Spezifikation
eines Systems in ein ausführbares Programm mit Hilfe eines Generators
(z.B. eines Compilers) ermöglicht. Das in einer Domänenmodellimplementierung
enthaltene Wissen umfaßt abstrakte und konkrete Komponenten, die
die Domänenkonzepte realisieren, Kompositionsregeln, Implementierungsstrategien
und Verbindungen zu anderen Domänen.
Die generative Programmierung legt die Grundlage für die Komposition
von Softwaresystemen aus abstrakten und konkreten Bausteinen. Eine wichtige
Voraussetzung hierfür ist die Anpaßbarkeit der Software-Bausteine.
Daher liegen der generativen Programmierung die folgenden wichtigen Prizipien
zugrunde:
Separartion of Concerns: Dieses Prinzip besagt, daß unterschiedliche
Verantwortlichkeiten bzw. Aspekte getrennt betrachtet werden sollen. Die
Trennung soll nicht nur auf der Modellebene eingehalten werden, sondern
auch auf der Implementierungsebene.
Öffnung der Implementierung: Die über die verschiedenen
Kontexte hinweg variablen Teile einer Komponente werden herausgelöst
und zu Parametern der Komponente erklärt. Diese Parameter werden als
Concerns bezeichnet. Beispiele von Concerns sind Schnittstelle, Implementierung,
Struktur, Synchronisation, Fehlerentdeckung und Fehlerbehandlung.
Austauschbarkeit von Aspekten: Für jedes Concern wird eine
Menge von Komponenten zur Verfügung gestellt, die jeweils alternative
Implementierungen für dieses Concern darstellen. Diese Komponenten
werden als Aspekte bezeichnet.
Propagierung von Aspekten: Aspekte können von einer Komponente
zu einer anderen "weitergereicht" werden (eng. information spreading).
Auf diese Art und Weise können globale domänenspezifische Optimierungen
durchgeführt werden.
Verringerung der sichtbaren Komplexität mit Hilfe von Konfigurationsregeln:
Die Funktionalität einer Komponente wird mit Hilfe von sog. Features
spezifiziert. Aus diesen Features werden die internen Aspekte einer Komponente
unter Verwendung von Konfigurationsregeln berechnet.
Erkennung von semantisch unzulässigen Konfigurationen
Als ein weiteres Prinzip kommt die sog. " zero-overhead"- Regel
hinzu. Sie besagt, daß unbenutzte Flexibilität unerwünscht
ist, da sie in der Regel die Effizienz eines Programms beeinträchtigt.
Daher sollte immer darauf geachtet werden, ob eine bestimmte Flexibilität
nur zur Compilierzeit oder auch noch zur Laufzeit benötigt wird.
Die generative Programmierung präsentiert sich heute als aussichtsreichster
Nachfolger des objektorientierten Paradigmas. Weltweit mit Schwerpunkt
in den USA gibt es Reihe von Forschungsaktivitäten auf verwandten
Gebieten, die zu neuartigen Techniken geführt haben, z.B. Parameterisierte
Typen, Adaptive Programming\Demeter, Aspect-Oriented Programming, Metaprogrammierung,
Composition Filters, Transformationssysteme, Intentional Programming, automatische
Verfeinerung von algebraischen Spezifikationen (siehe unten). Alle dieser
Techniken unterstützen vor allem die oben genannten Prinzipien.
Einige ausgewählte Techniken der generativen
und komponentenbasierten Softwareentwicklung
Parameterisierte Typen
Parameterisierte Typen (z.B. Templates in C++ und generic packages in Ada)
können eingesetzt werden, um nicht nur den Typ von Variablen oder
Funktionsrückgabewerten zu parameterisieren sondern auch andere Aspekte,
z.B. Synchronisationsmechanismen, Fehlerentdeckung und Fehlerbehandlung,
implizite Datenstrukturen, Funktionalitätserweiterungen
etc. Parameterisierte Typen dienen Konfiguration zur Compilierzeit und
erlauben es dem Compiler, wichtige Optimierungen durchzuführen. Ein
Beispiel einer Komponentenbibliothek, die auf parameterisierten Typen basiert,
ist die C++ Standard Template Library. Parameterisierte Typen bilden auch
die Grundlage des GenVoca-Modells von Software-Generatoren. Das GenVoca-Modell
unterstützt zusätzlich sog. Konfigurationsregeln, mit deren Hilfe
ungültige Komponentenkonfigurationen erkannt werden, sowie domänenspezifische
Optimierungen mit Hilfe von Transformationen.
Demeter ermöglicht eine weitgehende Trennung von Algorithmen, die
über mehrere Klassen definiert sind, von der konkret benutzten Klassenstruktur
(d.h. Klassen und ihren Beziehungen). Dabei werden Algorithmen in Form
sogenannter Propagationsmuster und die Klassenstrukturen in Form von Graphen
angegeben. Die Trennung wird erreicht, indem ein Propagationsmuster nur
diejenigen Klassen und Beziehungen zwischen Klassen erwähnt, die für
die Formulierung des Algorithmus unbedingt notwendig sind. Ein Programm
besteht dann aus einer Menge von Propagationsmustern und einem Klassenwörterbuch,
das die Klassenstruktur definiert.
In der aspektorientierten Programmierung besteht ein Programm aus einer
Menge von Teilprogrammen, wobei jedes dieser Teilprogramme einen Aspekt
betrachtet (und kann in einer für den jeweiligen Aspekt spezifischen
Sprache geschrieben sein). Das bedeutet, daß auch der aspektorientierten
Programmierung nichts anderes als das Prinzip "Separation of Concerns"
zugrunde liegt. Der besondere Schwerpunkt wird jedoch auf deklarative Kompositionsmechanismen
für Aspekte gelegt.
Der Grundgedanke der subjektorientierten Programmierung (SOP) besteht darin,
daß die Bedeutung eines Objektes von seinem Kontext (bzw. Betrachter)
abhängig, d.h. subjektiv ist. So z.B. ist das Objekt "Mitarbeiter",
das in der Produktionsplanung benötigt wird, anders aufgebaut als
das Objekt "Mitarbeiter", das im Personalwesen eingesetzt wird. Diesem
Grundgedanken entsprechend werden in SOP objektorientierte Programme in
sog. Subjekte aufgeteilt. Ein Subjekt ist ein möglicherweise unvollständiges
Programm, das eine subjektive Sicht auf die zu modellierenden Sachverhalte
verkörpert. Die Aufteilung in Subjekte kann sogar einzelne Objekte
"durchschneiden". Die Subjekte werden mit Hilfe sog. Kompositionsregeln
zusammengefügt. Die subjektorientierte Programmierung entstand am
IBM Watson Research Center, wo auch an ihrer Weiterentwicklung gearbeitet
wird.
Composition Filters stellen eine Erweiterung des OO-Modells dar. Mit Hilfe
von Composition Filters können Nachrichten, die zwischen Objekten
ausgetauscht werden, gefiltert werden. Somit lassen sich Aspekte einer
Komponente, z.B. Echtzeit-Constraints, Delegation, Fehlerentdeckung und
Synchronisation, auf eine kompakte Art und Weise in separaten Objekten
definieren. Composition Filters unterstützen die dynamische Konfiguration
von Komponenten.
Eine Transformation kann als eine semantisch korrekte, automatisierte Modifikation
eines Programms definiert werden. Eine Transformation wird in Form einer
Ersetzungsregel (engl. "rewrite rule" bzw. "transform") spezifiziert. Die
Ersetzungsregel besteht aus einem Kopf und einem Körper, die jeweils
ein Stück Code darstellen. Bei der Anwendung der Ersetzungsregel auf
ein Programm werden die mit dem Kopf der Ersetzungsregel übereinstimmenden
(engl. "matching") Codeabschnitte des Programms durch ihren Körper
ersetzt. Diese Ersetzung erfolgt aber nicht auf der textuellen Ebene, sondern
im Syntaxbaum des Programms. Einige Typen von Transformationen sind z.B.
Inlining, Vereinfachung, partielle Evaluierung, Refactoring und Verfeinerung.
Refine (Reasoning Systems Inc.)
ist ein Beispiel eines Transformationssystems.
Intentional Programming (IP) stellt eine komplette Programmierumgebung
dar, der ein Transformationssystem sowie eine Reihe von neu entwickelten
Konzepten, z.B. Intentionen und Enzyme, zugrunde liegen. Der Grundgedanke
von IP ist der Versuch, den "essentiellen Inhalt" (d.h. die Intention)
eines Programmes weitgehend sprachunabhängig zu repräsentieren.
Automatische Verfeinerung basierend auf algebraischen Spezifikationen
Die Softwareentwicklung durch eine durchgehend formale Transformation einer
Spezifikation in ein ausführbares Programm ist bereits seit über
20 Jahren Gegenstand der Forschung. Einige neue Ergebnisse auf diesem Gebiet
beweisen bereits die Eignung dieser Technologie zur Entwicklung von Anwendungsgeneratoren
für hochspezialisierte Domänen (siehe KIDS
und Transportation Scheduling).
Domänenengineering ist eine systematische Vorgehensweise zur
Entwicklung wiederverwendbarer Assets (d.h. wiederverwendbarer Anforderungen,
Architekturen, Komponenten und sonstiger Formen von wiederverwendbarem
Entwicklungswissen) für eine bestimmte Domäne sowie zur Entwicklung
einer geeigneten Infrastruktur zur Wiederverwendung dieser Assets bei der
Herstellung neuer Systeme dieser Domäne. Ein wichtiges Produkt des
Domänenengineering ist das Domänenmodell, das den Entwurfs- und
Konfigurationsraum der Systeme der Domäne beschreibt.
Wer an o.g. Forschungsschwerpunkten Interesse hat, ist herzlich eingeladen
seine Ideen einzubringen und im Arbeitskreis mitzuwirken.
Ihre Ideen, Kommentare und Meinungen sind uns herzlich willkommen. Wir
würden uns über ihre Hinweise auf Forschungs- und Industrieprojekte,
in denen Sie generative Techniken nutzen, freuen. Auch wenn Sie die Techniken
noch nicht einsetzen, sie aber für Ihre Projekte für relevant
halten, wären wir für Ihre Hinweise dankbar.
Richten Sie bitte Ihre Mail an: czarnecki@acm.org
bzw. eine der oben angeführten Adressen.
Ira Baxter (Semantic Designs) "The
Design Maintenance System, Scale, and application to Refactoring"
Jim Coplien (Bell-Labs, Lucent)
"Design after Modernism: Beyond the Object" und
Brad Cox (Virtual School) "Superdistribution:
Objects as Property"
Hauptprogramm mit Beiträgen über generative und komponentenbasierte
Ansätze
GCSE99
Young Researchers Workshop - besonders interessant für Diplomanden,
Doktoranden und Post-Docs, die zukünftig im Bereich der generativen
und komponentenbasierten Softwareentwicklung ihre Forschungsarbeiten durchführen
wollen
Tutorien von Don Batory, Ira Baxter und Jim Coplien
Das
zweite Treffen des Arbeitskreises hat im Rahmen der STJA'98
vom 6. bis zum 8. Oktober 1998 in Erfurt stattgefunden. Die Keynotes wurden
von Don Batory (University of Texas, Austin) zum Thema "Product-Line Architectures"
und Charles Simonyi (Microsoft Research) zum Thema Intentional
Programming gehalten.
Das erste Treffen des Arbeitskreises hat im Rahmen der STJA'97 (Smalltalk
und Java in Industrie und Ausbildung) am 10. und 11. September 1997 in
Erfurt stattgefunden. Die Keynotes wurden von Karl Lieberherr (Northeastern
University) zum Thema "Aspect-Oriented Programming" und Mark Simos (Synquiry
Ltd.) zum Thema "Organization Domain Modeling". Außerdem hat Mehmet
Aksit (University of Twente) einen eingeladenen Vortrag über "Composition
Filters" gehalten. Die Beiträge sowie der Tagungsbericht
(von Prof. Ulrich Breymann, erschienen in Softwaretechnik-Trends, November
1997) sind online verfügbar.