Sie sind auf Seite 1von 16

Implementierung eines OCL-Toolkits

Seminar Software-Systemtechnik des Fachgebiets Echtzeitsysteme

Martin Schäfer

21. Juni 2004

1
INHALTSVERZEICHNIS 2

Inhaltsverzeichnis
1 Einleitung 3

2 Kurze Einführung in die OCL Syntax 3


2.1 Beispiel: GPS-Steuerung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2 Aufbau eines OCL-Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.3 Invariants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.4 Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.5 Pre- und Postconditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

3 OCL Toolkit aus Dresden 7


3.1 Modulare Struktur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.2 Schnittstellen des Toolkits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.2.1 UML-Modellinformation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.2.2 OCL-Constraints Eingabe . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.2.3 Ausgabe des Codegenerators . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.2.4 Integration des erzeugten Codes in die Modelldateien . . . . . . . . . . . . 8

4 Einsatz des Toolkits 9


4.1 OCL-Constraints der GPS-Software . . . . . . . . . . . . . . . . . . . . . . . . . 9
4.2 Ablauf der Modifikationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

5 Erweiterungsmöglichkeiten 13
5.1 Interpreter anstatt Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
5.2 Support von XMI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
5.3 Erweiterung auf UML 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

6 Fazit 14
1 EINLEITUNG 3

1 Einleitung
Bereits seit einigen Jahren gilt die Modellierungssprache Unified Modeling Language (UML)
als Standard, um Software übersichtlich, strukturiert und unabhängig von der verwendeten
Programmiersprache zu beschreiben. UML ermöglicht die Definition des Klassengerüsts und
der Abhängigkeiten der Klassen untereinander in Form von Klassendiagrammen (siehe auch
[OMG04]). Diese werden von zahlreichen CASE Tools zur automatischen Codegenerierung be-
nutzt und ersparen so bereits jetzt einen Großteil der Programmierarbeit, zumindest was die
Objektstruktur des Codes betrifft. Es ist zwar möglich die Abhängigkeiten in einer objektori-
entierten Programmstruktur durch Klassendiagramme zu beschreiben, jedoch werden die Be-
dingungen, unter denen diese Abhängigkeiten gelten, unterschlagen. Hierin liegt die Stärke der
Object Constraint Language (OCL), die seit 1997 ein Teil des UML Standards ist (vgl. [WaKl99]
und [WaKl03]). OCL erfüllt den Zweck einer mathematischen Spezifikationssprache (Für alle X
im Bereich [0-7] gilt X ≤ Y), allerdings ohne mathematische Symbole sondern in verständlichem
Text. OCL wird nicht zur Codedefinition verwendet. Vielmehr wird es benutzt, um eine Anfor-
derungsspezifikation in Form eines UML-Diagrammes durch hinzufügen von Einschränkungen
(OCL-Constraints) so eindeutig wie möglich zu gestalten und den aus der Spezifikation erzeug-
ten Code effizient gegen diese zu testen. Da es sich bei OCL-Constraints um Kommentare zu
einem Klassendiagramm handelt, kann ein solcher Test nur durch Analyse mit Blatt und Papier
erfolgen, oder er muss manuell in das Programm integriert werden. Ganz andere Möglichkeiten
ergeben sich jedoch, wenn OCL-Constraints automatisch ausgewertet werden. Diesen Ansatz
verfolgt das in Abschnitt 3 vorgestellte OCL-Toolkit.

2 Kurze Einführung in die OCL Syntax


Im folgenden soll eine kurze Einführung in den Aufbau einiger OCL-Constraints gegeben wer-
den. Für eine detailliertere Betrachtung sei auf [Schä04] bzw. auf [WaKl99], [WaKl03] verwie-
sen. Die verschiedenen OCL-Constraint Beispiele sind aus dem Kontext einer fiktiven GPS-
Steuerungssoftware gewählt, die auch als Beispiel für die Funktion des OCL-Toolkits dient.
2 KURZE EINFÜHRUNG IN DIE OCL SYNTAX 4

2.1 Beispiel: GPS-Steuerung

Es handelt sich hierbei um eine Steuersoftware, die z.B. Teil eines handelsüblichen GPS-Hand-
gerätes sein könnte. Satellitensignale werden von dem Gerät ausgewertet, um seine aktuelle
Position zu bestimmen. Diese wird, je nach Funktionsmodus, in eine Reiseroute gespeichert
oder lediglich angezeigt. Der Kontakt zu den Satelliten wird über eine einprogrammierte Liste
von bekannten Satelliten hergestellt, die als Grundlage für das Auffinden der aktiven Satelliten
dient. Die Liste wird während des Bootvorganges aus dem Systemspeicher geladen und vor
Abschalten des Systems aktualisiert zurückgeschrieben.

knsAs Satellite
0..* KnownSatellite
ControlUnit
Battery sysBattery satelliteID : int
knownSatellites
speed : double
power : int {ordered}
Date
batAs functionMode : int
day : int lastContactDate
systemState : int dasAs
month : int
bootSystem() : boolean year : int
dakAs active : boolean
sysDate absoluteDays : int
shutDownSystem() : boolean
0..*
sysTravelRoute traAs calculatePosition() : boolean knmAs knownSatellites
Memory
updateTravelRoute() : void memAs
TravelRoute ready : boolean
loadSatelliteList() : void
avSpeed : double sysMemory
saveSatelliteList() : void ActiveSatellite
start : EarthPosition acsAs
0..*
destination : EarthPosition getUserInput() : int
activeSatellites
evaluateSatellites() : void
{ordered}

tisAs
sysTime owner
sigAs
epoAs satelliteSignal
pocAs
Time
waypointPositions Signal
sysPosition hour : int
{ordered}
1..* minute : int signalTime strength : int
second : int valid : boolean
EarthPosition
absoluteSeconds : int
globalX : int tisAs

globalY : int
tipAs
globalZ : int
calculationTime

Position SpacePosition

relX : int absX : int signalPosition posAs


relY : int absY : int
relZ : int absZ : int

Abbildung 1: GPS-Steuerungsoftware

Das Klassendiagramm in Abbildung 1 enthält Informationen über die einzelnen Bestandteile


des Systems (Steuereinheit, Speicher, Batterie), die verwalteten Datentypen (Position, Reise-
route, Zeit und Satelliten) sowie deren Operationen und Zusammenhänge. Es wird jedoch nicht
überprüft ob die Daten des Systems konsistent sind (z.B. sollte eine Geschwindigkeit immer po-
sitiv sein) oder Operationen korrekt arbeiten. Um solche Überprüfungen zu ergänzen, wird das
Klassendiagramm um eine textuelle OCL-Beschreibung erweitert (siehe auch Abschnitt 4.1).
2 KURZE EINFÜHRUNG IN DIE OCL SYNTAX 5

2.2 Aufbau eines OCL-Constraints

OCL-Constraints für ein komplettes UML Diagramm können theoretisch in einer einzigen Text-
datei gespeichert werden. Um die Klassenzugehörigkeit festzulegen, muss daher jeder Befehl mit
dem entsprechenden Kontext versehen werden, was zu der folgenden Grundstruktur führt:

context Klassenname::evtl. Methodenname/Variablenname ...


OCL-Constraint mit Argumenten

2.3 Invariants

Invariants sind die einfachsten Constraints, sie müssen zu jedem Zeitpunkt gültig sein und werden
häufig zur Definition von Wertebereichen für Variablen eingesetzt. Eine Invariant besitzt einen
Kontext und einen boolean Ausdruck, der die Beschränkung beschreibt.

context ControlUnit
inv checkSpeed : speed >= 0

context ControlUnit
inv checkFunctionMode : ( functionMode = 1 ) or (functionMode = 2 )

Invariant 1 definiert, das jede Geschwindigkeit einen positiven Wert haben muss. Invariant 2
legt fest welche Zahlen gültige Funktionsmodi repräsentieren (z.B. nur Position feststellen oder
Route dokumentieren).

2.4 Collections

OCL besitzt gleich mehrere Möglichkeiten auf multiple Klasseninstanzen zuzugreifen, auch über
Assoziationen hinweg. Ein normaler Operationszugriff im Rahmen einer Klasseninstanz erfolgt
über Klassenname.Operationsname. Soll jedoch auf eine Menge (Collection) von Klassenin-
stanzen zugegriffen werden, wird nicht mehr der Punkt(.) sondern ein Pfeil(->) als Adressie-
rungsoperator verwendet. Rechts vom Pfeil steht die Menge, links die Operation. Will man z.B.
festlegen, dass die Menge der aktiven Satelliten eine Untermenge der bekannten Satelliten sein
muss, reicht dazu folgender OCL-Constraint:

context ControlUnit
inv checkSatelliteSets: knownSatellites->
includesAll(activeSatellites)

Auf die Menge kownSatellites wird hierbei die Operation includesAll angewendet, die true
liefert, falls die Menge activeSatellites in kownSatellites enthalten ist.
2 KURZE EINFÜHRUNG IN DIE OCL SYNTAX 6

2.5 Pre- und Postconditions

Eines der stärksten Features von OCL sind Pre- und Postconditions. Sie beschreiben die Ausfüh-
rungsbedingungen und Resultate von Methoden, ohne jedoch die Implementierung festzulegen.
Will man zum Beispiel gewährleisten, dass das GPS-System nur bootet, wenn die Batterie noch
genügend Energie hat, um zumindest das Booten und einen geregelten Shutdown zu versorgen,
könnte man folgende OCL-Constraints verwenden:

context ControlUnit :: bootSystem ( )


pre allowBoot : (sysBattery.power >10) and (systemState = 0)

context ControlUnit :: bootSystem ( )


post evalOutput : result = (systemState = 1)

Der Kontext der beiden Befehle ist die Operation bootSystem() der Klasse ControlUnit. Die-
se Operation wird nur dann ausgeführt, wenn die Systembatterie genügend Energie enthält
(sysBattery.power>10) und wenn sich das System im Aus-Zustand befindet (systemState = 0).
Desweiteren wird festgelegt, dass der Rückgabewert der Methode result der gleiche wie der
boolsche Ausdruck systemState = 1 ist, d.h. die Methode muss false zurückgeben, wenn das
Booten scheitert.
3 OCL TOOLKIT AUS DRESDEN 7

3 OCL Toolkit aus Dresden


Auch wenn OCL Modelle exakt beschreibt, schützt es doch nicht vor Fehlern in der Implemen-
tierung dieser Modelle. Um diese Implementierungsfehler zu minimieren und so die zur Code-
erzeugung benötigte Zeit stark zu reduzieren, wurde an der TU-Dresden im Rahmen mehrerer
Diplomarbeiten ein OCL-Toolkit entwickelt (siehe [Dres04]).

3.1 Modulare Struktur

Im Folgenden soll ein grober Überblick über die modulare Struktur des Toolkits gegeben wer-
den. Abbildung 2 (Quelle [Fing00] S. 16) zeigt die Beziehungen zwischen den einzelnen Modulen.
Nähere Details sind in [Fing00] (Kapitel 3-6) ausführlich beschrieben.

Parsermodul, das die Codegenerator, der die


OCL-Quellen ausliest und Typecheckermodul zur Modul zur Vereinheitlichung der im Befehlsbaum vorliegenden
auf syntaktische Fehler semantischen Überprüfung Schreibweise der OCL Befehle Constraints in Java Befehle übersetzt
überprüft

codegen
parser check normalize

lib

enthält die OCL


Befehlsspezifikation in Java

Abbildung 2: Paketstruktur des Toolkits

Das Parsermodul analysiert die eingegebenen OCL Befehle auf ihre syntaktische Korrektheit.
Ist dies geschehen wird die Semantik überprüft und anschließend die Schreibweise der OCL-
Constraints unter Verwendung des Normalizer Moduls vereinheitlicht. Nach diesem Durchlauf
stehen die OCL-Constraints leicht zugänglichen Befehlsbaum zur Verfügung, der nun vom Co-
degenerator benutzt werden kann. Der Codegenerator übersetzt den erzeugten Befehlsbaum in
ausführbaren Code, der bereits erstellte Programmdateien um Kontrollroutinen ergänzt und da-
mit deren automatische Überprüfung ermöglicht.
Als Basis für diese Operationen dient eine OCL-Bibliothek, die die vom Toolkit unterstützte
OCL-Befehlsmenge festlegt. Sie stimmt bis auf wenige Ausnahmen mit der Spezifikation von
OCL 1.3 überein, eine OCL 2.0 konforme Version wird entwickelt, ist allerdings noch nicht
verfügbar (vgl. [Dres04] Diskussionsforum, Beitrag von Ralf Wiebicke).
3 OCL TOOLKIT AUS DRESDEN 8

3.2 Schnittstellen des Toolkits

Am Anfang der Codeerzeugung stehen das UML-Klassenmodell und die OCL-Constraints in


Textform. Diese können über Interfaces, für die bereits verschiedene Implementierungen beste-
hen, an die weiteren Module übergeben werden.

3.2.1 UML-Modellinformation

Das Klassenmodell wird über das Interface ModelFacade realisiert (vgl. [Fing00] Kapitel 5.3.3).
Die einzige funktionsfähige Implementierung basiert auf Java Reflection, einem Java Packa-
ge, das UML-Diagramme aus Java Code generiert (siehe [Java04]). Diese Diagramme werden
dann als Modellbasis für die Constraints benutzt. Generell muss erwähnt werden, dass einige
Einschränkungen in UML-Diagrammen nötig sind, um sie als Modell benutzen zu können. So
dürfen z.B. gewisse OCL-Schlüsselwörter nicht als UML-Objektnamen verwendet werden (vgl.
[Fing00] Kapitel 2).

3.2.2 OCL-Constraints Eingabe

Die Constraints können zum einen als separates Textfile vorliegen, zum anderen ist auch die
Übergabe direkt im Javacode der z.B. durch ein CASE-Tool generierten Java-Dateien möglich.
In denselben Dateien, aus denen auch mittels Java Reflection das Klassen-Modell erstellt wird,
werden die OCL-Constraints als Java-Kommentare gemäß einem festgelegten Schema eingefügt.
Welche Strukturen im Einzelnen für das Auslesen der OCL-Constraints verwendet werden, wird
am ehesten aus dem Sourcecode der Klasse \tudresden\ocl\injection\ocl\Main.java er-
sichtlich, der über [Dres04] erhältlich ist. Für die Form der Java-Kommentare kann man sich an
der aktuellen Version von ArgoUML orientieren (Bezug über [Argo04]). Die von diesem CASE-
Tool generierten Kommentare sind bis auf eine Ausnahme mit der Spezifikation des Toolkits
kompatibel (siehe Abschnitt 4).

3.2.3 Ausgabe des Codegenerators

Ist die Eingabe des Modells und der Constraints erfolgreich, beginnt der Weg durch die einzelnen
Module an dessen Ende der Codegenerator steht. Dieser übersetzt die im Befehlsbaum geliefer-
ten OCL-Constraints in ausführbare Codefragmente. Der im Rahmen des Toolkits verfügbare
Java-Generator nutzt dabei die integrierte OCL-Bibliothek, die zu jedem unterstützten OCL-
Constraint eine Äquivalenz in Java enthält.

3.2.4 Integration des erzeugten Codes in die Modelldateien

Die nun vorhandenen Java-Fragmente müssen in den Javacode der Modelldateien integriert wer-
den und das möglichst so, dass eine Rücktransformation der modifizierten Dateien möglich ist.
4 EINSATZ DES TOOLKITS 9

Zudem muss zur Überprüfung von pre- und postconditions einer Methode der Zustand direkt
vor und direkt nach dem Methodenaufruf überprüft werden. Dies wird möglich, indem jede OCL-
Constraint an zwei Stellen den ursprünglichen Methoden-Code verändert: Die ursprüngliche
Methode wird umbenannt, bleibt aber in ihrem Rumpf unverändert. Die vom Programm auf-
gerufene Methoden befinden sich in am Dateiende eingefügten ”Wrappern”. Diese enthalten
jeweils die Methoden mit dem ursprünglichen Namen, allerdings um den Code zur Realisierung
der OCL-Constraints erweitert. Jede Wrappermethode ruft wiederum, nach Überprüfung evtl.
vorhandener preconditions, die umbenannte Methode auf, die den ursprünglichen Programm-
code enthält. Ist diese Methode beendet wird im unteren Teil des ”Wrappers”die postcondition
überprüft. Weitere Details zum Aufbau der ”Wrapperblöcke”können [Wieb00] Kapitel 3.3 ent-
nommen werden.

4 Einsatz des Toolkits


Das Toolkit ist dank einer GUI (dresden-ocl-demo.jar auf [Dres04]) als alleinstehende An-
wendung benutzbar, jedoch nur für ein ganz bestimmtes Modellbeispiel (Royals and Loyals vgl.
[WaKl99]). Die einfachste Benutzung über das Demo-Beispiel hinaus gelingt per Kommandozei-
le unter Verwendung des packages dresden-ocl-injector.jar, im Folgenden Injector genannt
(Bezug über [Dres04]). Bei Aufruf des Injectors wird aus den gegeben Java-Dateien ein Klassen-
modell erstellt und die OCL-Constraints extrahiert. Dann erfolgt die Ergänzung der Quelldateien
um die Java Pendants der OCL-Strukturen. Sollen die Änderungen rückgängig gemacht werden
genügt ein weiterer Aufruf, und man erhält wieder den ursprünglichen Code.
Der komplette Ablauf einer Benutzung des Injectors soll nun anhand des Beispiels der GPS-
Steuerungssoftware demonstriert werden. Zur Generierung des UML-Modells der Steuerungssoft-
ware wurde ArgoUML 0.14 verwendet (Bezug und Informationen: [Argo04]). Dieses OpenSource-
Programm liefert die OCL-Constraints in dem benötigten Javadoc-Format und fügt zudem für
den Injector wichtige Typenangaben zu generischen Datentypen wie Vektoren hinzu. Ein wich-
tiges Detail scheint jedoch nicht zu passen: Die Javadoc-Kommentare enthalten genau einen
Stern(*) zu wenig vor jeder OCL-Befehlsliste, was dazu führt, dass jeder erste OCL-Befehl
übersprungen wird, wenn man keine Änderung vornimmt.

4.1 OCL-Constraints der GPS-Software

Zum Testen des Modells wurden, neben den bereits erwähnten, folgende OCL-Constraints im-
plementiert:

context ControlUnit::calculatePosition( )
pre checkSatellites: ( activeSatellites -> forAll (active))
post evalOutput: result = (activeSatellites.satelliteSignal->
4 EINSATZ DES TOOLKITS 10

select(strength > 10)->size > 3)

Alle Satelliten zur Positionsbestimmung sind aktiv. Die Operation ist nur dann erfolgreich, wenn
mindestens 4 Satelliten ein Signal senden, das stark genug ist.

context ControlUnit :: evaluateSatellites ( )


pre checkTrigger: knownSatellites ->
select(active=true)->size <> activeSatellites->size
post checkResult: knownSatellites ->
select(active=true)->size = activeSatellites->size

Die Operation wird ausgeführt, wenn nicht mehr alle aktiven Satelliten in der activeSatellites-
Liste sind. Danach muss dies wieder der Fall sein.

context ControlUnit :: updateTravelRoute ( )


pre checkTrigger: sysTravelRoute.waypointPositions->
exists (calculationTime.absoluteSeconds -
self.sysTime.absoluteSeconds > 5000)
post checkResult: sysTravelRoute.waypointPositions ->
forAll (calculationTime.absoluteSeconds -
self.sysTime.absoluteSeconds < 100)

Die Reiseroute wird alle 5000 Sekunden aktualisiert. Nach der Aktualisierung darf die Zeitdiffe-
renz der letzten Position nur 100 Sekunden zur aktuellen Zeit betragen.

4.2 Ablauf der Modifikationen

Auszug aus ControlUnit.java von ArgoUML generiert:

01 package test;
02 import java.util.Vector;
03 public class ControlUnit {
04 /* {src_lang=Java}*/
...
38 /**
39 *
40 * @precondition allowBoot: ( sysBattery . power > 10 ) and
( systemState = 0 )
4 EINSATZ DES TOOLKITS 11

41 * @postcondition evalOutput: result = (systemState = 1)


42 */
43 public boolean bootSystem() {
44 int systemState = 0;
45 return true;
46 }
...
55 }
56 /**
57 *
58 * @precondition checkSatellites: (activeSatellites->forAll(active))
59 * @postcondition evalOutput: result = (activeSatellites. ....
60 */
...

In Linie 39 und 57 fehlen je ein *, der von Hand ergänzt werden muss!!!

01 package test;
02 import java.util.Vector;
03 public class ControlUnit {
04 /* {src_lang=Java}*/
...
38 /**
39 *
40 *
41 * @precondition allowBoot: ( sysBattery . power > 10 ) and
( systemState = 0 )
42 * @postcondition evalOutput: result = (systemState = 1)
43 */
44 public boolean bootSystem() {
45 int systemState = 0;
46 return true;
47 }
...
56 }
57 /**
58 *
59 *
4 EINSATZ DES TOOLKITS 12

60 * @precondition checkSatellites: (activeSatellites->forAll(active))


61 * @postcondition evalOutput: result = (activeSatellites. ....
62 */
...

Aufruf des Injectors: dresden-ocl-injector.jar muss sich im selben Verzeichnis wie das
Package (in diesem Fall test) befinden. Der erste Compilerlauf ist notwendig, damit die ver-
wendeten Hilfsklassen bereits zur Verfügung stehen.

javac -classpath . test/*.java


java -jar dresden-ocl-injector.jar -m -r test test/*.java
javac -classpath dresden-ocl-injector.jar test/*.java
java -classpath dresden-ocl-injector.jar test/ControlUnit

Auszug aus ControlUnit.java nach der Modifizierung, man sieht die veränderten Namen der
Methoden und im unteren Teil den Beginn des Wrapperabschnitts, der den eigentlichen OCL-
Code enthält:

001 package test;


002 import java.util.Vector;
003 public class ControlUnit {
004 /* {src_lang=Java}*/
...
045 public boolean bootSystem_wrappedbyocl_test_ControlUnit() {
046 int systemState = 0;
047 return true;
046 }
...
050 public boolean shutDownSystem_wrappedbyocl_test_ControlUnit() {
051 return false;
052 }
...
102 /**
103 A wrapper for injection. Generated automatically, DO NOT CHANGE!
104 @author ocl_injector
105 @see #bootSystem_wrappedbyocl_test_ControlUnit()
106 */public boolean bootSystem(){
4 EINSATZ DES TOOLKITS 13

107 boolean result;


108 if(tudresden.ocl.injection.ocl.lib.Invariant.checking_flag)
109 result=bootSystem_wrappedbyocl_test_ControlUnit();
110 else{
111 checkForChangedFeatures();
112 try{tudresden.ocl.injection.ocl.lib.Invariant.checking_flag=true;
113 tudresden.ocl.injection.ocl.lib.Invariant.checkVacantInvariants();
114 }finally{tudresden.ocl.injection.ocl.lib.Invariant.checking_flag=false;}
115 result=bootSystem_wrappedbyocl_test_ControlUnit();
116 checkForChangedFeatures();
117 ...

Zum Test wurden gezielt die invariants checkSpeed, checkFunctionMode, sowie die Pre- und
Postconditions von bootSystem verletzt (speed=-5, functionMode=3 , systemstate=5), was
zu folgender Konsolenausgabe führte:

Checking method bootSystem ()


Checking method calculatePosition ()
Checking method updateTravelRoute ()
Checking method evaluateSatellites ()
violated ocl invariant ’checkSpeed’ on object
’test.ControlUnit@1befab0’.
violated ocl invariant ’checkFunctionMode’ on object
’test.ControlUnit@1befab0’.
violated ocl precondition ’allowBoot’ on object
’test.ControlUnit@1befab0’operation ’bootSystem()’.
violated ocl postcondition ’evalOutput’ on object
’test.ControlUnit@1befab0’operation ’bootSystem()’.

Wie man an der Ausgabe sieht, werden die verletzten Constraints erkannt. Leider wird weder
angezeigt, wo die jeweilige Bedingung verletzt wurde, noch mit welchem Wert sie verletzt wurde.
Dies könnte bei großen Programmen zu Schwierigkeiten führen, da die Fehlersuche sehr viel Zeit
in Anspruch nehmen würde. Ein wünschenswerteres Verhalten wäre die Anzeige der Variablen-
inhalte zum Zeitpunkt der Constraintverletzung oder noch besser die Anzeige der Codezeile.
5 ERWEITERUNGSMÖGLICHKEITEN 14

5 Erweiterungsmöglichkeiten
Das obige Beispiel hat bereits gezeigt, dass das Toolkit noch viel Spielraum für Weiterentwick-
lungen bietet. Einige dieser Verbesserungsmöglichkeiten, die sich auch zum Teil bereits in der
Umsetzung befinden, sollen in diesem Abschnitt erläutert werden.

5.1 Interpreter anstatt Compiler

Anstatt der Integration von OCL in vorhandenen Code mittels Compiler wäre es viel effektiver,
OCL als eine zur Laufzeit interpretierte Sprache zu implementieren. So würden Laufzeitfeh-
ler erkannt, was derzeit nicht möglich ist, und man könnte die OCL-Constraints während der
Programmausführung anpassen. Zu diesem Thema existiert bereits eine Realisierung, die von
Nikolai Krambrock im Rahmen einer Diplomarbeit an der RWTH Aachen erstellt wird. Der
Interpreter ist über den CVS-Bereich des OCL-Toolkits auf [CVS04] zugänglich, allerdings sind
keine weiteren Informationen bezüglich der Implementierung verfügbar.

5.2 Support von XMI

Obwohl die Verwendung von Java Reflections ein sehr komfortables Mittel der Modelldefinition
darstellt, hat sie einige entscheidende Nachteile: Zum einen handelt es sich um ein anhand von
Java-Code erstelltes Modell, was jeden Anspruch von UML auf Unabhängigkeit von der Program-
miersprache zunichte macht, zum anderen sind, aufgrund der von Java verwendeten generischen
Datentypen (z.B. Vektoren), bestimmte UML-Details nicht eindeutig am Code identifizierbar,
was zu Mehrdeutigkeiten im Modell führen kann (vgl. [Fing00] chapter 5.3.3). Die GUI des Tool-
kits enthält bereits eine Schnittstelle, die die Modellübergabe in Form einer Extensible Markup
Language Metadata Interchange Datei ermöglicht(siehe XMI [XMI04]). Diese ist jedoch nicht
funktionsfähig. Die Implementierung einer solchen Schnittstelle würde die genannten Proble-
me lösen, ist allerdings zur Zeit nicht geplant (vgl. [Dres04]Diskussionsforum, Beitrag von Dr.
Heinrich Hussmann).

5.3 Erweiterung auf UML 2.0

Die derzeit aktuelle UML-Version 2.0 bietet viele Erweiterungen der OCL-Syntax, die der Spra-
che bedeutend mehr Möglichkeiten verleihen. Um eine Implementierung von OCL 2.0 zu errei-
chen, müsste die OCL-Typen Bibliothek in weiten Teilen neu geschrieben werden, zudem werden
neue Inkompatibilitäten Änderungen an den Parser und TypeChecker Modulen unabdingbar ma-
chen . An der Weiterentwicklung des Toolkits mit Anpassung auf die neuen Befehle wird bereits
gearbeitet allerdings ist noch kein endgültiges Release verfügbar. Auch ein Erscheinungsdatum
steht noch nicht fest. (vgl. [Dres04] Diskussionsforum, Beitrag von Ralf Wiebicke).
6 FAZIT 15

6 Fazit
Das OCL-Toolkit zeigt das Potential von automatisch generierten Testroutinen aber auch ih-
re noch vorhandenen Schwächen. Die Implementierung des Beispiels hat gezeigt, wie gering
der Aufwand zur Generierung von Testszenarien in kleineren Programmen sein kann. Zweizei-
lige OCL-Constraints erfüllen selbst komplexe Such- und Vergleichsroutinen auf Vektoren und
verkürzen so den Aufwand der Testphase. Eine Testgenerierung für größere Projekte scheitert
noch an der stark eingeschränkten Befehlsmenge von OCL 1.3 und der Fülle der Syntaxbe-
schränkungen. Für den Gebrauch in der professionellen Software-Entwicklung ist das Toolkit in
der derzeitigen Form daher nur beschränkt einsetzbar, zu große Anpassungen im Entwicklungs-
prozess wären nötig. Vielmehr ermöglicht der modulare Aufbau des Toolkits die Integration von
Teilen des Gesamtpakets in CASE-Tools und andere Entwicklungsumgebungen. Modifikationen
an den verwendeten Bibliotheken könnten mit wenig Arbeitsaufwand zu einer leistungsstarken
Testplattform führen, die einen weiteren wichtigen Schritt in Richtung einer vollständig modell-
basierten Softwareentwicklung bedeuten würde.
LITERATUR 16

Literatur
[Fing00] Frank Finger: Design and Implementation of a Modular OCL Compiler, Technische
Universität Dresden, 2000

[Wieb00] Ralf Wiebicke: Utility Support for Checking OCL Business Rules in Java Programs,
Technische Universität Dresden, 2000

[WaKl99] Jos Warmer;Anneke Kleppe: The Object Constraint Language, Precise Modelling with
UML, Addison-Wesley, 1999

[WaKl03] Jos Warmer and Anneke Kleppe: The Object Constraint Language Second Edition,
Getting Your Models Ready For MDA, Addison-Wesley, 2003

[Schä04] Christian Schäfer: OCL - Grundlagen,Seminar Software-Systemtechnik des Fachgebiets


Echtzeitsysteme, Technische Universität Darmstadt,2004

[OMG04] Object Management Group (OMG): Introduction to OMG’s Unified Moedling Lan-
guage (UML),2004
http://www.omg.org/gettingstarted/what_is_uml.htm, (Zugriff: 10.06.2004)

[XMI04] Object Management Group (OMG): XML Metadata Interchange (XMI),2004


http://www.omg.org/technology/documents/formal/xmi.htm, (Zugriff: 10.06.2004)

[Dres04] Dresden OCL Toolkit: Modular Toolkit for the Object Constraint Language (OCL),2004
http://dresden-ocl.sourceforge.net/, (Zugriff: 18.06.2004)

[CVS04] Dresden OCL Toolkit CVS: Concurrent Version System, OCL-Grammar,2004


http://cvs.sourceforge.net/viewcvs.py/dresden-ocl/, (Zugriff: 19.06.2004)

[Argo04] Argo UML: Argo UML Quick Guide,2004


http://argouml.tigris.org/, (Zugriff: 08.06.2004)

[Java04] Java Reflections: The Java Reflection API,2004


http://java.sun.com/docs/books/tutorial/reflect, (Zugriff: 14.06.2004)