5.2 Übersetzung von Objektdiagrammen
Die vollständige Beschreibung zur Generierung von Code aus der UML/P würde den Rahmen dieses Buchs sprengen. Deshalb werden in den folgenden Abschnitten einige der
interessantesten Aspekte der Transformation weiterer Diagramm- und Textarten in Java-Code erläutert, ohne alle Details zu diskutieren.
Objektdiagramme können auf zwei Arten verwendet werden. Zum einen können Objektdiagramme konstruktiv eingesetzt werden, um damit Objektstrukturen zu erzeugen. Diese Funktionalität
kann sowohl im Produktionssystem als auch zur Darstellung von Objektstrukturen, auf denen automatisierte Tests stattfinden sollen, verwendet werden. Zum anderen werden Objektdiagramme als
Prädikate eingesetzt, um zu prüfen, ob eine bestimmte Objektstruktur vorhanden ist. In Abschnitt 4.4, Band 1 wurden diese Verwendungsarten bereits vom methodischen Standpunkt aus
beleuchtet. Dieser Abschnitt wird deshalb Aspekte der Codegenerierung aus Objektdiagrammen diskutieren. Dabei sei zunächst die in Kapitel 4, Band 1 vorgenommene Integration von
Objektdiagrammen und OCL vernachlässigt.
5.2.1 Konstruktiv eingesetzte Objektdiagramme
Die Transformation eines Objektdiagramms in Funktionalität zum konstruktiven Aufbau von Objektstrukturen erfolgt gesteuert durch ein Skript beziehungsweise durch Merkmale, die
dem Objektdiagramm angefügt werden. Dabei sind einige Parameter festzulegen, die bei der Codegenerierung wichtig sind:
- Die Klasse, der die Methode zur Erzeugung der Objektstruktur zugeordnet wird. Ist im Diagramm ein Objekt eindeutig ausgezeichnet, so kann dies
entfallen.
- Der Name der zu erzeugenden Methode. Als Default wird setupDiagramName verwendet, wenn dieser Name
eindeutig ist.
- Die Objekte des Diagramms, die bereits existieren und als Parameter übergeben werden. In der Regel ist dies keines oder eines, das als
übergeordnetes Objekt bereits erzeugt wurde.
- Treten im Objektdiagramm freie Variablen auf, so werden sie ebenfalls als Parameter für die generierte Methode interpretiert.
Da die Ausgangssituation und die damit jeweils bereits existenten Objekte unterschiedlich sein können, kann es sinnvoll sein, mehrere Methoden aus einem Objektdiagramm zu generieren. Diese
können sich durch die Signatur oder, falls dies nicht eindeutig ist, auch durch die Methodennamen unterscheiden.
Die Verwendung freier Variablen und unbesetzter Attribute als Parameter der generierten Funktion erlaubt es, Objektdiagramme wie in Abschnitt 4.2.2, Band 1 diskutiert als Muster mit prototypischen Objekten zu interpretieren, die eine mehrfache Instanziierung mit unterschiedlichen Inhalten erlauben.
Bei der Generierung der setup-Methoden gibt es mehrere Aspekte, die zu beachten sind. Für die Erzeugung eines Objekts ist die Verwendung eines Konstruktors
notwendig. Idealerweise sollte ein Konstruktor ohne Parameter zur Verfügung stehen, der nur das leere Objekt erzeugt. Steht ein solcher Konstruktor nicht zur Verfügung, so kann im
Testsystem ein solcher generiert werden. Im Produktionssystem muss allerdings auf einen existenten Konstruktor zurückgegriffen werden, der entsprechend ausgezeichnet wurde.
Ein weiteres Problem ist die Besetzung der Attribute entsprechend der im Objektdiagramm vorgegebenen Werte. Dafür sollten geeignete Hilfsfunktionen zur Verfügung stehen oder direkter
Zugriff auf die Attribute erfolgen. Die in Abschnitt 5.1.1 diskutierten set-Methoden sind dafür nur partiell
geeignet, da sie unter Umständen zusätzliche Funktionalität beinhalten.
Im Prinzip können dafür auch Konstruktoren mit Parametern weiterhelfen, wenn die Zuordnung zwischen dem Parameter und dem zu besetzenden Attribut aus der Konstruktordefinition
eindeutig hervorgeht.
Ein Objektdiagramm kann grundsätzlich unvollständig sein, indem etwa die Klasse eines Objekts nicht angegeben ist oder manchen Attributen kein Wert zugewiesen wurde. Zum einen
können unbesetzte Attribute als freie Variable verstanden werden und als Parameter in die generierte Methode aufgenommen werden. Ist dies nicht gewünscht, so sind abhängig von der
Art des Einsatzes im Testsystem, zur Simulation oder im Produktionssystem verschiedene Strategien zur Behandlung unbesetzter Attribute möglich. Im Testsystem wird eine Failure-Strategie
genutzt: Unbesetzte Attributwerte sollten für den getesteten Systemablauf keine Rolle spielen und der Zugriff darauf mit einem sofortigen Scheitern des Tests reagieren. Entsprechendes
Verhalten kann in die get-Funktionen integriert werden. Bei der Simulation ist die bereits in Abschnitt 5.1.2
diskutierte Vorgehensweise sinnvoll, fehlende Attributwerte während des Simulationslaufs interaktiv zu erfragen oder mit Default-Werten zu arbeiten. Bei der Codegenerierung für das
Produktionssystem ist schließlich eine vollständige Definition der Objekte im Objektdiagramm Voraussetzung. Dies verhindert Unachtsamkeiten bei der Definition von Objektdiagrammen und
gibt so dem Entwickler Zutrauen in die Zuverlässigkeit des modellierten Systems.
Nicht alle im Objektdiagramm formulierbaren Angaben werden bei konstruktiver oder auch der später diskutierten prädikativen Codegenerierung verwendet. Sichtbarkeiten, die Information
über Kompositionalität eines Links, Merkmale wie {frozen} und ähnliches mehr bedürfen
keiner Umsetzung in den hier diskutierten Code, sondern werden mit den in Klassendiagrammen vorhandenen Informationen abgeglichen oder in Tests eingesetzt.
Ein alternativer, mit Methodenspezifikationen verbundener Ansatz zum konstruktiven Einsatz von Objektdiagrammen ist bereits in Abschnitt 4.4.7, Band 1 diskutiert. Er nutzt ein Objektdiagramm in
der Nachbedingung eines Konstruktors beziehungsweise einer Initialisierungsmethode, das nach denselben Prinzipien wie den hier gezeigten in konstruktiven Code umgesetzt werden kann.
5.2.2 Beispiel einer konstruktiven Codegenerierung
Statt nun die Transformationsregeln für jedes Modellelement des Objektdiagramms zu diskutieren sollen diese anhand des in Abbildung 5.11 gezeigten Objektdiagramms beispielhaft erläutert werden. Dieses Diagramm beschreibt einen Ausschnitt der initialen Objektstruktur des Applets im Auktionssystem
und ist eingebettet in eine OCL-Methodenspezifikation für die Initialisierungsfunktion init(). Der generierte Code ist in Abbildung 5.12
dargestellt, wobei hier und in den folgenden Beispielen vereinfachend angenommen wird, dass der direkte Zugriff auf die Attribute erst noch transformiert wird:
Aus dem zugehörigen (hier nicht wiedergegebenen) Klassendiagramm kann das System ableiten, dass die Links durch die Attribute loginPanel und httpServerProxy in der Klasse WebBidding realisiert werden. Für die Klassen HttpServerProxy und LoginPanel wird ein geeignet parametrisierter Konstruktor verwendet, der die Besetzung der angegebenen Attribute vornimmt.
5.2.3 Als Prädikate eingesetzte Objektdiagramme
Der Einsatz eines Objektdiagramms als Prädikat, das prüft, ob eine bestimmte Objektstruktur vorliegt und die im Objektdiagramm angegebenen Werte übereinstimmen, wird
in eine boolesche Methode transformiert. Ähnlich wie bei der konstruktiven Variante steuern mehrere Parameter den zu erzeugenden Code:
- Die Klasse, der die boolesche Methode zugeordnet wird. Ist im Diagramm ein Objekt eindeutig ausgezeichnet, zum Beispiel durch den Namen this:Classname, so kann dies entfallen. Alternativ kann die Methode als statisch definiert und/oder einer Testklasse zugeordnet werden.
- Der Name der zu erzeugenden Methode. Ist der Name nicht gegeben, so wird als Default isStructuredAsDiagramName verwendet.
- Die Objekte des Diagramms, die als Ausgangsobjekte bereits identifiziert sind und deshalb als Parameter übergeben werden. In der Regel ist dies ein
einzelnes Objekt, das als eine Art Master für die Objektstruktur gilt.
- Treten im Objektdiagramm freie Variablen auf, so werden sie im Normalfall nicht weiter beachtet. Sollen diese Variablen aber bestimmte Werte annehmen, so
werden die Variablen ebenfalls als Parameter für die generierte Methode interpretiert.
Im Gegensatz zur konstruktiven Variante eines Objektdiagramms kann ein prädikativ eingesetztes Diagramm in mehrerer Hinsicht unvollständig sein. Attribute und Attributwerte dürfen
ebenso weggelassen werden wie die Klassen der dargestellen Objekte. Auch Eigenschaften mit einer zeitlichen Implikation, wie etwa das Merkmal {frozen} für Links, können nicht in einem Prädikat über einen Zustand geprüft werden. Dazu ist zusätzliche Infrastruktur
nötig, die dies entweder konstruktiv sichert, indem keine Methoden zur Modifikation eines Links angeboten werden, oder zur Laufzeit prüft, indem der ursprüngliche Zustand des Links
in einer Kopie aufgehoben wird.
In Abschnitt 4.3, Band 1 wurde die Bedeutung eines Objektdiagramms als Prädikat im Kontext der Integration mit OCL-Bedingungen bereits ausführlich diskutiert. Dabei wurde festgestellt,
dass ein Objektdiagramm grundsätzlich als OCL-Bedingung dargestellt werden kann. In genau dieser Bedeutung werden prädikative Objektdiagramme in entsprechende boolesche Methoden, die mit
dem in Abschnitt 3.4.1, Band 1 eingeführten Stereotyp ≪query≫ markiert sind, übersetzt. Die so generierten Methoden
können genau wie die Referenz auf das Objektdiagramm bei Invarianten, Vor- und Nachbedingungen von Methoden und von Transitionen in Statecharts, aber auch in Java-Rümpfen des
Produktionscodes eingesetzt werden.
Für die Verwendung im Produktionscode ist jedoch auf die Effizienz der Umsetzung zu achten. Wie in Abschnitt 4.3, Band 1 diskutiert, wirken anonyme Objekte des Objektdiagramms als
existenzquantifiziert. In derselben Weise werden benannte Objekte behandelt, die jedoch nicht bereits als Parameter an das boolesche Prädikat übergeben werden. Diese Objekte werden vom
Prädikat selbst gesucht, indem die entsprechenden Assoziationen geprüft werden. Die Belegung der freien Objekte erfolgt in einer dem Struktur-Matching der Graph Grammatiken [Roz99, EEKR99] analogen Form.
Bei mengenwertigen Assoziationen kann eine derartige Suche von linearer Komplexität sein und sollte deshalb vermieden werden. Möglichkeiten zur Verbesserung der Situation bieten der
Einsatz eines Qualifikators bei der Assoziation oder die explizite Übergabe gesuchter Objekte als Parameter, wenn diese aus dem Kontext effizient ermittelt werden können.
Anhand des aus dem Auktionssystem stammenden und in Abbildung 5.13 dargestellten Objektdiagramms wird die Transformation in ein
Prädikat illustriert. Der für den Einsatz im Testsystem generierte Code ist in Abbildung 5.14 dargestellt.
Nach einer Phase der Belegung von Objektnamen werden alle Attribute geprüft. Dabei dürfen Attributwerte aufeinander Bezug nehmen. Werden statt der im (hier nicht dargestellten)
Klassendiagramm angegebenen Typen echte Unterklassen angegeben, so wird geprüft, ob das entsprechende Objekt tatsächlich zu dieser Unterklasse gehört.
Anhand der Länge des in Abbildung 5.14 dargestellten Codes ist ersichtlich, dass eine Darstellung im Objektdiagramm kompakter und
übersichtlicher ist, also dem Modellierer insbesondere bei der schnellen Erfassung eines Überblicks und der Suche einzelner Werte Vorteile bringt.
Als Erweiterung beziehungsweise Alternative bei der Codegenerierung kann eine weitere Methode mit dem Namen isExactlyStructuredAsDiagramName generiert werden. Diese Methode kann zusätzlich sichern, dass die Objektstruktur nur die im Diagramm angegebenen Objekte enthält. Das ist besonders bei
mehrwertigen und optionalen Assoziationen von Interesse und kann zum Beispiel durch einen geeigneten Stereotyp ≪complete≫
für Objektdiagramme gesteuert werden. Tabelle 5.15 gibt eine knappe Einführung zu diesem Stereotyp.
|
|
Stereotyp ≪complete≫
|
|
|
|
|
|
Modellelement
|
Objektdiagramm.
|
|
|
|
Motivation
|
Die Bedeutung eines Objektdiagramms als Prädikat ist normalerweise so festgelegt, dass die explizit angegebenen Eigenschaften erfüllt sein müssen. Weitere, im Diagramm
nicht angegebene Objekte können existieren.
|
|
|
|
Rahmenbedingung
|
In einem mit ≪complete≫ markierten Objektdiagramm müssen alle Attribute und Links angegeben sein. Geordnete
Assoziationen sind vollständig darzustellen.
|
|
|
|
Wirkung
|
Der Stereotyp ≪complete≫ fordert, dass keine weiteren Objekte in der angegebenen Objektstruktur existieren. Das
angegebene Objektdiagramm ist also eine vollständige Darstellung der Objektstruktur.
Damit kann die Methode isExactlyStructuredAsDiagramName generiert werden, die diese Vollständigkeit zusätzlich zur
Erfüllung der angegebenen Eigenschaften des Objektdiagramms prüft.
|
|
|
|
|
|
|
|
|
|
Tabelle 5.15.: Stereotyp ≪complete ≫
|
|
|
5.2.4 Objektdiagramm beschreibt Strukturmodifikation
Eine weitere interessante Form des Einsatzes von Objektdiagrammen ergibt sich aus der Kombination beider Einsatzformen. Dabei wird eine existente Objektstruktur auf das
Vorhandensein der im Objektdiagramm beschriebenen Objekte geprüft, die fehlenden Objekte generiert und die falsch besetzten Attribute modifiziert. Derartige Methoden erhalten als Namen
adaptToDiagramName. Mit diesen Methoden kann eine bereits vorhandene Objektstruktur in Abhängigkeit des aktuell gewünschten
Zustands umgebaut werden. Damit lassen sich Objektdiagramme zum Beispiel als Zustandsinvarianten im Statechart oder zur Adaption der jeweiligen Objektstruktur in der Entry-Aktion von Zuständen
einsetzen. Wird beispielsweise das in Abbildung 5.11 gegebene Objektdiagramm (ohne Einbettung in die dort stehende OCL-Bedingung) in dieser Form
eingesetzt, so wird die in Abbildung 5.16 dargestellte Methode erzeugt.
Fehlt ein Objekt oder hat es den falschen Typ, so wird es neu erzeugt. Ist das Objekt bereits vorhanden, so werden seine Attribute in der gewünschten Form modifiziert. Deshalb werden sowohl
Konstruktoren, die in diesem Beispiel bereits Attributwerte als Parameter enthalten, als auch set-Methoden zur Attributbesetzung verwendet.
Die Eindeutigkeit des entlang eines Links zu identifizierenden Objekts wie zum Beispiel dem anonymen Objekt :LoginPanel ist nur bei
Assoziationen der Kardinalität „1“ oder „0..1“ gegeben. Bei mengenwertigen Assoziationen ist ein Vergleich mit
allen vorhandenen Objekten durchzuführen, der auch dessen Attribute einbezieht. Findet sich kein Objekt in der Objektstruktur, das dem im Diagramm angegebenen prototypischen Objekt entspricht,
so wird in diesem Fall keines der vorhandenen Objekte angepasst, sondern ein neues Objekt erzeugt. Dadurch vergrößert sich die Menge der Links entsprechend. Der Nachteil dieser Methode
ist allerdings, dass die Löschung unerwünschter Objekte nicht dargestellt werden kann. Außerdem kann diese Methode ineffizient werden, wenn zum Beispiel mit dem in Abbildung
3.28 gegebenen Objektdiagramm (ohne die OCL-Bedingung) und der daraus generierten und in Abbildung 5.17
dargestellten Methode hundert Personen einzeln angelegt werden.
5.2.5 Objektdiagramme und OCL
Ein wesentliches Mittel zur Steigerung der Ausdrucksmächtigkeit von Objektdiagrammen ist die ab Abschnitt 4.3, Band 1 durchgeführte Integration mit der OCL. Die
Transformation eines um OCL-Bedingungen erweiterten Objektdiagramms in konstruktiven Code beziehungsweise in ein Prädikat hängt daher von der Umsetzbarkeit der OCL-Bedingungen ab. Die
Umsetzung und die Ausführbarkeit von OCL-Bedingungen wurde bereits in Abschnitt 4.1.2 diskutiert.
Zu beachten ist aber auch, dass die in der vorangegangenen Diskussion erwähnte lineare Suchkomplexität für existenzquantifizierte Objekte polynomial ansteigen kann, wenn über
mehrere mengenwertige Assoziationen navigiert wird und die so erreichten Objekte über eine OCL-Bedingung verknüpft sind.
Bernhard Rumpe. Agile Modellierung mit UML. Springer 2012