Referat - fldit- · Teil B: OCL 1) Einleitung S. 17 2) Was ist OCL (Seiteneffekte, warum OCL...
Transcript of Referat - fldit- · Teil B: OCL 1) Einleitung S. 17 2) Was ist OCL (Seiteneffekte, warum OCL...
Referat
UML + OCL
Referenten:
Achour ElmrabtiBritta Porsche
1
Inhaltsübersicht
Teil A: UML1) Einleitung S. 3
2) Entwicklungsprozeß S. 4
3) Anwendungsfälle S. 5/6
4) Klassendiagramme S. 7/8
5) Interaktionsdiagramme (Sequenzdiagramme,Kollarborationsdiagramme)
S. 9-11
6) Pakete S. 12
7) Zustandsdiagramme S. 13/14
8) Aktivitätsdiagramme S. 15/16
Teil B: OCL1) Einleitung S. 17
2) Was ist OCL (Seiteneffekte, warum OCL einsetzen, OCL Syntax) S.18/19
3) Kontext und Stereotypen (Syntax und Constraints, Vor- undNachbedingungen, Invarianten)
S. 20-22
4) Definitionen S. 23
5) Datentypen S. 24
6) Let- Ausdrücke S. 25
7) Enumeration S. 25
8) Collections (Sets, Sequenzen, Bags) S. 26/27
9) Operationen für Collections (Konformität der Typen „castings“, IF-Then- Else)
S. 28/29
10) Navigation S. 30
11) Attribut und Methoden der Kontext- Instanz S. 31
12) Zugriff auf assozierte Instanzen S. 32
13) Assoziationsklassen S. 33
14) Perspektiven (Formale Semantik) S. 34
15) Integration in das objektorientierte Modell (Zugriffsrechte, Vererbungund Interfaces, Verhaltensmodellierung)
S. 35/36
16) Spezifikation von Operationen (Logik und undefinierte Werte) S. 37
Literaturverzeichnis S. 38
2
Teil A: UML
1) Einleitung
In den späten 80er und frühen 90er Jahren kam eine Welle von objektorientierten
Analyse- und Entwurfsmethoden auf. UML (Unified Modeling Language) gehört zu einer
dieser Methoden. Sie wird aber dennoch als Modellierungssprache und nicht als eine
Methode angesehen. Eine Modellierungssprache ist eine Notation, die im wesentlichen
dazu verwendet wird, Entwürfe auszudrücken. Geleitet wird dies durch einen Prozeß der
bestimmt welche Entwürfe durchgeführt werden.
Der heutige UML Standard definiert eine Notation und ein Metamodell. Die Notation
besteht aus den grafischen Elementen, die man in Modellen sieht. Sie ist die Syntax der
Modellierungssprachen. Die Modelle mit den grafischen Elementen können aber dennoch
sehr ungenau sein. Methodenentwickler haben nach genaueren Modellen gesucht ohne
die eigentliche Nützlichkeit einzuschränken. Sie haben ein Metamodell entwickelt. Das
Metamodell ist ein syntaktisch korrektes Modell, das Beziehungen zwischen
Assoziationen zeigt.
In der Softwareentwicklung wird UML sehr oft genutzt, weil es die Kommunikation fördert.
Man kann durch die UML Modelle bestimmte Konzepte viel klarer darstellen, als wenn
man sie mit der natürlichen Sprache erklärt. Die natürliche Sprache ist oft sehr unpräzise
und kann zu Unklarheiten führen.
In der UML Modellierung wird nicht sofort der Programmcode angefertigt, da dieser sehr
oft zu detailliert ist. In einem UML Modell hingegen werden auch wichtige Details
hervorgehoben aber noch nicht so detailliert beschrieben wie es in einem Programmcode
der Fall ist.
3
2) Entwicklungsprozeß
UML basiert immer auf einem Entwicklungsprozeß. Man kann UML mit jedem beliebigen
Entwicklungsprozeß benutzen, da UML unabhängig vom Prozeß ist. Die folgende Skizze
zeigt einen Entwicklungsprozeß in grober Form.
Dieser Prozeß ist in sehr viele kleinere Schritte unterteilt, d.h. Die fertige Software
entsteht nicht auf einen Schlag sondern sie entwickelt sich mit der Zeit. In der 1. Phase,
dem Einstieg, werden die geschäftlichen Absichten für das Projekt begründet. Man
entscheidet hier genau welchen Bereich das zu bearbeitende Projekt abdecken soll und
legt somit im groben Rahmen die eigentliche Größe des Projektes fest. Es sollte hier auch
schon eine grobe Einschätzung der Kosten und des Nutzens abgegeben werden. Da die
Einstiegsphase nicht die relevanteste Aufgabe ist, sollte der Zeitaufwand nicht länger als
einige Tage umfassen. Die nächste Phase, die Ausarbeitung, sollte etwas umfangreicher
sein, was aber nicht unbedingt besagt, daß man mehr Informationen über das Projekt
erhält. Die Ausarbeitungsphase sollte ca. ein Fünftel der gesamten Projektdauer
ausmachen. In dieser Phase sammelt man detaillierte Anforderungen und führt den
Entwurf und die Analyse nochmals mit den neu gewonnenen Anforderungen durch. Es
werden zu diesem Zeitpunkt oft die Fragen gestellt: Was soll tatsächlich erstellt werden ?
Wie ist es zu erstellen? In der Ausarbeitungsphase wird auch ein genauer Plan für die
Konstruktionsphase erstellt. Die Konstruktionsphase besteht aus mehreren Teilen
(Iterationen) aus denen am Ende ein fertiges System entstehen soll. Für jede Iteration
wird eine geeignete Software entworfen und getestet, ob sie den jeweiligen
Anforderungen entspricht. Man beendet jede einzelne Interaktion dadurch, daß man sie
dem Kunden demonstriert und einen Systemtest durchführt. Der Kunde soll dann
bestätigen, daß der Anwendungsfall korrekt interpretiert worden ist. In der letzten Phase,
der Überleitung, werden nochmal Betatests durchgeführt um die bereits vorhandene
Software eventuell zu verbessern. In dieser Phase gibt es eigentlich kein Hinzufügen von
Funktionalitäten mehr; es werden nur noch Fehlerkorrekturen vorgenommen. Zu dieser
Phase des Entwicklungsprozeß gehört unter anderem auch ein Benutzertraining.
4
3) Anwendungsfälle
Ivar Jacobson entwickelte die Anwendungsfälle und machte sie zu einem primären
Element der Projektentwicklung.
Ein Anwendungsfall (Use case) ist eine Menge von Interaktionen zwischen einem
Benutzer und einem System, die durch ein gemeinsames Benutzerziel verbunden sind.
Wie ausführlich ein Anwendungsfall beschrieben werden muß hängt sehr oft von der
Schwierigkeit des Problems ab.
Als zusätzliche Unterstützung werden oft auch Anwendungsfalldiagramme gezeichnet
(Use case diagramm), die zur Visualisierung der Anwendungsfälle führen. Ein
Anwendungsfalldiagramm kann aus einem oder auch mehreren Akteuren bestehen. Ein
Akteur ist eine vom Anwender in Bezug auf das System eingenommene Rolle. Akteure
führen die einzelnen Anwendungsfälle durch, wobei ein Akteur mehrere Anwendungsfälle
durchführen kann und ein Anwendungsfall auch von mehreren Akteuren ausgeführt
werden kann. Es ist nützlich in einem Anwendungsfalldiagramm Akteure zu realisieren,
wenn das System auf verschiedenen Anwendungstypen konfiguriert werden soll.
Dennoch ist es aber nicht unbedingt notwendig, daß Anwendungsfalldiagramme Akteure
enthalten.
In einem Anwendungsfalldiagramm gibt es nicht nur Beziehungen zwischen Akteuren und
Anwendunsfällen sondern auch Beziehungen zwischen Anwendungsfällen untereinander.
Eine davon ist z.B.: die Enthält- (include) Beziehung. Diese Beziehung tritt auf, wenn ein
Verhalten in mehreren Anwendungsfällen ähnlich ist und dessen Beschreibung nicht
überall hineinkopiert werden soll. Diese Beziehung wird also verwendet wenn sich
mehrere Anwendungsfälle wiederholen. Desweiteren gibt es noch die Erweitert- (extends)
Beziehung. Mit dieser Beziehung kann das Verhalten des Anwendungsfall erweitert und
zum Basis Anwendungsfall hinzufügen werden.
In dem folgenden Anwendungsfalldiagramm wird nocheinmal verdeutlicht wie die Akteure
und die Beziehungen in einem Diagramm realisiert werden. Außer der uns nun schon
bekannten Enthältbeziehung ist in diesem Diagramm noch die Verallgemeinerung
dargestellt. Die Verallgemeinerung ist eine Spezialisierung und Generalisierung. In
unserem speziellen Fall bedeutet das, daß der Anwendungsfall „Handel festmachen“ die
Oberklasse (Generalisierung) ist. „Grenzen überschreiten“ ist die Unterklasse
(Spezialisierung) und erbt alle Methoden und Attribute der Oberklasse. Zusätzlich kann
dieser Anwendungsfall aber auch noch eigene Methoden und Attribute haben, die die
5
Oberklasse nicht besitzt.
Anwendungsfalldiagramm
6
4) Klassendiagramme
Klassendiagramme sind innerhalb der objektorientierten Methoden eine zentrale Technik.
Sie beschreiben die verschiedenen Typen von Objekten in einem System und deren
Beziehungen untereinander. Es gibt zwei verschiedene Arten dieser „statischen“
Beziehungen, die Assoziationen und die Untertypen (Generalisierung).
Klassendiagramme zeigen unter anderem auch Methoden (Operationen) und Attribute.
Im folgenden betrachten wir nun die Assoziationen etwas näher: Assoziationen
repräsentieren Beziehungen zwischen Instanzen (Objekten) von Klassen. Diese
Beziehung zwischen den Objekten ist dauerhaft, sie existieren also während der
gesamten Lebensdauer der Objekte, obwohl die miteinander verbundenen Instanzen sich
auch ändern können. Eine Assoziationen hat zwei Assoziationsenden, die mit der
Multiplizität gekennzeichnet werden. Die Multiplizität besagt wie viele Objekte an der
Beziehung beteiligt sein können. Bei dieser Kennzeichnung bedeutet ein (*), daß
unendliche viele Objekte beteiligt sein können und eine (1), daß nur ein Objekt beteiligt
sein kann. Wenn eine Assoziationsende mit 0..1 gekennzeichnet ist bedeutet dies, daß
entweder 1 oder kein Objekt in Frage kommt. Die Multiplizitäten geben demnach also eine
obere bzw. untere Schranke an.
In einem Klassendiagramm werden auch Attribute dargestellt. Attribute sind
Assoziationen sehr ähnlich. Mit Attributen legt man den Attributnamen, den Typ und den
voreingestellten Wert fest.
Operationen sind die Prozesse, die eine Klasse ausführen kann. Sie sind gleichzusetzen
mit den uns bekannten Methoden einer Klasse. Bei Methoden kann man die Sichtbarkeit
durch ein (+) öffentlich bzw. (-) privat festlegen. Öffentlich bedeutet, daß diese Methode
auch von anderen Klassen „gesehen“ wird und auch benutzt werden darf. Private
Methoden sind nur in der eigenen Klasse sichtbar. Bei Methoden einer Klasse wird auch
festgelegt von welchem Typ sie sind (z.B. integer) und man kann einen
Rückgabetypausdruck bestimmen.
Ein noch typische Beispiel in einem Klassendiagramm ist die Generalisierung.
Generalisierung bedeutet, daß es eine Oberklasse gibt von denen mehrere Unterklassen
erben. Die Unterklassen besitzen alle Methoden und Attribute die auch die Oberklasse
besitzt. Sie können aber auch zu dem noch eigenen Attribute und Methoden haben. Die
Oberklasse ist demnach die Generalisierung und die Unterklassen sind die
Spezialisierung. In einem Klassendiagramm wird diese Art von Beziehungen durch einen
7
nicht ausgefüllten Pfeil gekennzeichnet.
Im folgenden Klassendiagramm sind die verschiedenen Beziehungen zwischen den
einzelnen Klassen nochmals verdeutlicht. Man kann in dem vorliegenden Diagramm sehr
gut die Multiplizitäten der einzelnen Klassen erkennen. Auch die Generalisierung
zwischen den Klassen Kunde, Privatkunde und Firmenkunde ist gut sichtbar. Die
Einschränkung, die zu der Klasse Auftrag gehört, besagt, daß die Methoden nur
ausgeführt werden wenn die Einschränkung true ist.
Klassendiagramm
8
5) Interaktionsdiagramme
Interaktionsdiagramme beschreiben, mit welchem Verhalten Gruppen von Objekten
zusammenarbeiten. In Interaktionsdiagrammen wird die Anzahl der Objekte die man für
das System benötigt festgelegt. Es wird genau beschrieben wie diese Objekte
miteinander kommunizieren bzw. Nachrichten austauschen. Interaktionsdiagramme sind
gut geeignet um die Zusammenarbeit zwischen verschiedenen Objekten zu zeigen. Sie
eignen sich aber nicht für Verhaltensdefinitionen. Die Interaktionsdiagramme werden in
zwei Arten aufgeteilt, die Sequenzdiagramme und die Kollaborationsdiagramme.
a) Sepuenzdiagramme
In Sequenzdiagramme wird ein Objekt als ein Kasten dargestellt von diesem Kasten aus
geht eine vertikale Linie nach unten. Die vertikale Linie wird als Lebenslinie des Objektes
bezeichnet. Nachrichten die zwischen Objekten ausgetauscht werden erkennt man durch
einen Pfeil der von einer Lebenslinie auf eine andere Lebenslinie gerichtet ist. Der Pfeil
wird zusätzlich noch mit einem Namen markiert damit der Betrachter erkennt wie die
Objekte miteinander kommunizieren. Es gibt auch den Selbstaufruf, was bedeutet, daß
ein Objekt eine Nachricht an sich selbst sendet. Bei dem Selbstaufruf zeigt der Pfeil
zurück auf die gleiche Lebenslinie von der er aus gestartet ist.
Bei einem Nachrichtenaustausch zwischen Objekten können auch Einschränkungen
vorgenommen werden. Die Bedingung wird dann nur erfüllt wenn die Einschränkung den
Wert „wahr“ erhält. Wenn die Einschränkung den Wert „falsch“ erhält wird sie nicht weiter
beachtet.
In manchen, wichtigen, Fällen ist es sinnvoll ein Sequenzdiagramm mit einer Rückgabe
zu versehen. Eine Rückgabe wird durch eine gestrichelte Linie dargestellt und kann somit
nicht mit der eigentlichen Nachricht vertauscht werden. Rückgabepfeile sind nur sinnvoll
wenn sie zur Klarheit und zum Verständnis beitragen, sie sind nicht unbedingt notwendig
in einem Sequenzdiagramm.
Asynchrone Nachrichten werden in Sequenzdiagrammen mit einer halben Pfeilspitze
dargestellt. Eine asynchrone Nachricht beeinflusst den Aufrufenden nicht. Solche Art von
Nachrichten haben den Vorteil, daß sie neue Objekte erzeugen können. Das Löschen
eines Objektes wird durch ein „X“ dargestellt. Objekte können sich selber löschen oder
9
auch von anderen Objekten die Nachrichten senden gelöscht werden.
Sequenzdiagramm
10
b) Kollaborationsdiagramme
In Kollaborationsdiagrammen werden Objekte als Sinnbilder dargestellt. Die Nachrichten
die zwischen den einzelnen Objekten ausgetauscht werden, werden genauso wie bei
Sequenzdiagrammen auch durch Pfeile dargestellt. Dennoch aber gibt es einen
Unterschiede zwischen den beiden Diagrammen. In Kollaborationsdiagrammen werden
die ausgetauschten Nachrichten mit Nummern versehen, so daß man weiß in welcher
Reihenfolge die Nachrichten übergeben werden sollen. In Sequenzdiagrammen werden
die Nachrichtenpfeile untereinander gezeichnet und somit die zeitliche Abfolge bestimmt.
Welche Art von Diagrammen der Softwareentwickler nutzt sollte er für sich selbst
entscheiden. Man kann nicht sagen, daß eine Art von Diagrammen gut und die andere
schlecht ist. Der Vorteil bei Sequenzdiagrammen ist, daß man den Zeitlichen Ablauf
besser erkennt und der Vorteil bei Kollaborationsdiagrammen ist, daß man das Layout
verwenden kann, um anzuzeigen, wie Objekte statisch verbunden werden.
11
6) Pakete
Pakete haben die Aufgabe, große unübersichtliche Diagramme in kleine übersichtliche
Diagramme zu zerlegen. Pakete sind ein wesentliches Werkzeug in UML um überhaupt
die Kontrolle über die Gesamtstruktur eines Systems zu behalten. In einem Paket
befinden sich in der Regel mehrere Klassen die in einer gewissen Abhängigkeit
zueinander stehen. Wenn diese Klassen alle einzeln gezeichnet werden müssten, würde
das vorliegende Diagramm unendlich groß und unübersichtlich. Pakete sind also streng
genommen Klassendiagramme, bei denen Klassen die abhängig voneinander sind
zusammengefasst wurden. Eine Abhängigkeit zwischen zwei Klassen besteht wenn man
Änderungen an der Definition eines Elementes einer Klasse vornimmt und sich dadurch
auch Änderungen in einer anderen Klasse ergeben. Wenn zwei Klassen die sich in
unterschiedlichen Paketen befinden voneinander abhängig sind, so sind die Pakete auch
automatisch voneinander abhängig.
Klassen in Paketen können öffentlich oder geschützt (privat) sein. Dies liegt daran wie die
Methoden in der jeweiligen Klasse deklariert werden. Wenn eine Klasse in einem Paket
privat ist, kann eine weitere Klasse aus einem anderen Paket nicht auf diese Klasse
zugreifen.
Bsp.: Pakete
12
7) Zustandsdiagramme
Zustandsdiagramme dienen dazu das Verhalten eines Systems zu beschreiben. Sie
beschreiben alle möglichen Zustände die ein Objekt annehmen kann und zeigen wie sich
der Zustand verändert wenn bestimmte Ereignisse durchgeführt werden.
Zustandsdiagramme sind nicht sehr geeignet dazu, das Verhalten einer Gruppe von
Objekten und deren Zusammenarbeit darzustellen. In einem System sollten nicht für jede
Klasse Zustandsdiagramme gezeichnet werden. Der Entwickler sollte sich vorher darüber
im Klaren sein an welchen Stellen das Erstellen von Zustandsdiagrammen wirklich hilft
und wo es nur irreführend ist.
Bei einem Zustandsdiagramm wird bei dem Startpunkt, der durch einen ausgefüllten
schwarzen Punkt dargestellt wird, begonnen. Es wird dann eine Anfangstransition, die
mit dem Startpunkt und mit einem Zustand verbunden ist, gezeichnet. Die Transition wird
durch einen Pfeil dargestellt. Der Zustand wird durch ein Kästchen mit runden Ecken
dargestellt. Die Transition wird mit einer Aktion beschriftet, die ausgeführt wird wenn man
diesen Transitionspfeil erreicht. In dem Zustandskästchen kann zusätzlich eine Aktivität
stehen. Diese Aktivität wird abgearbeitet wenn die vorherige Transition erledigt worden
ist. Bei der Unterscheidung zwischen Aktionen und Aktivitäten ist darauf zu achten, daß
Aktionen mit Transitionen assoziiert werden und als kurzzeitige und nichtunterbrechbare
Prozesse betrachtet werden. Aktivitäten sind mit Zuständen assoziiert und können länger
andauern. Eine Aktivität kann durch ein Ereignis unterbrochen werden.
Transitionspfeile werden sehr oft mit einer Bedingung versehen die entweder wahr oder
falsch sein kann. Die Transition findet nur statt wenn die Bedingung wahr ist. Wenn die
Bedingung falsch ist wird im vorherigen Zustand gewartet, bis die Bedingung wahr wird.
Falls ein Zustand keine zusätzliche Aktivität besitzt wird solange in diesem Zustand
verharrt bis ein Ereignis eintritt.
Im folgenden Zustandsdiagramm werden nochmals verschiedene Situationen, die
eintreffen können demonstriert. Das Zustandsdiagramm wird dadurch, daß sehr viele
Einschränkungen vorgenommen werden sehr unübersichtlich. Gut zu erkennen ist aber
dennoch in dem Zustand warte die Transitionsschleiße, die anzeigt, daß man längere Zeit
in diesem Zustand verharren kann.
13
Zustandsdiagramm
14
8) Aktivitätsdiagramme
Aktivitätsdiagramme sind nützlich um das Verhalten von parallel laufenden Ereignissen zu
zeigen. Dies macht sie zu einem guten Werkzeug für die Modellierung von
Geschäftsabläufen. Geschäftsabläufe haben oft eine unnötige Reihenfolgevorschrift. In
Aktivitätsdiagrammen ist die Reihenfolge egal denn es gibt sehr viele
Parallelisierungsmöglichkeiten. Ein großer Nachteil eines Aktivitätsdiagrammes ist, daß
es keine klaren Verbindungen zwischen Objekten und Aktionen gibt. Aktivitätsdiagramme
zeigen auch nicht welche Person was tut, was wiederum bedeutet, daß man nicht genau
weiß welche Klasse für welche Aktivität zuständig ist.
Ein Aktivitätsdiagramm beschreibt die Reihenfolge der Aktivitäten. Dabei können sowohl
bedingte als auch parallele Verhaltensweisen beschrieben werden. Bedingtes Verhalten
wird von Verzweigungen und Zusammenführungen eingerahmt. Eine Verzweigung
besteht aus einer einzelnen Eingangstransition und mehreren Ausgangstransitionen.
Genau eine der Ausgangstransitionen wird genommen und deren Verlauf weiterverfolgt.
Eine Zusammenführung besitzt mehrere Eingangstransitionen und eine einzelne
Ausgangstransition. Eine Zusammenführung markiert das Ende eines durch die
Verzweigung eingeleiteten Verhaltens. Zusammenführungen und Verzweigungen werden
durch eine Raute dargestellt.
Paralleles Verhalten hingegen wird mit Forks bzw. Joins gekennzeichnet. Eine
Aufspaltung (Fork) besitzt einen Eingang und mehrere Ausgänge. Wird die
Eingangstransition ausgelöst, werden alle Ausgangstransition gleichzeitig verfolgt. Es
wird dadurch also ausgesagt, daß diese Aktivitäten parallel stattfinden und die
Reihenfolge unwichtig ist. Das Ende einer Parallelisierung ist die Zusammenführung
(Join). Bei einem Join wird die Ausgangstransition nur beschritten, wenn alle Zustände an
den Eingangstransition ihre Aktivitäten abgeschlossen haben.
Aufspaltung und Zusammenführung müssen paarweise auftreten, d.h. Alle Aufspaltungen
müssen auch irgendwann wieder zusammengefügt werden.
Befindet sich an der Aktivität ein Multiplizitätskennzeichen (*) gibt das an, dass diese
Aktivität mehrfach durchlaufen werden kann.
15
Aktivitätsdiagramm
16
Teil B: OCL
1) Einleitung
UML bemüht sich eine ausdrucksfähige Modellierungssprache für Entwicklung und
Austausch aussagekräftiger Modelle zu sein. Um die Anschaulichkeit komplexer Modelle
zu verbessern, basiert UML auf einer Reihe graphischer Notationen, die verschiedene
statische und dynamische Aspekte eines Softwaresystems beschreiben können .
Die Aussagekraft dieser vorgefertigten Notationen ist jedoch von Natur aus beschränkt.
Öfters ist es so, dass viele - für die Spezifikation relevante- Eigenschaften eines System
nicht ohne eine mächtigere Sprache auszudrücken sind. Dies gilt insbesondere für
Klassen und Operationen, dessen beabsichtigte Wirkung nur in den einfachsten Fällen
von den grafischen Notationen eindeutig ablesbar ist.
Die Object Constraint Language OCL ist ein Verfahren um in einem modellierten System
Einschränkungen und Zusicherungen zu definieren. Sie ist eine optionale Erweiterung
der UML, mit der man das Verhalten seiner Objekte besser definieren kann. Mit der OCL
kann man Attribute (beispielsweise: Minima, Maxima,Standardwerte und Wertebereiche)
für die Daten definieren die das System verwenden soll.
17
2) Was ist die OCL?
Was genau ist also die Objekt Constraint Language? Das Wort Objekt steht für eine
Komponente eines System die genauer definiert werden soll. Das Wort Constraint steht
für eine Einschränkung wie z.B.: Das Alter eines Attribut darf nicht größer als 18 sein. Das
Wort language steht für eine weniger formale Sprache, die auf jede Implementierung
angewendet werden kann.
OCL ist ein Versuch die „Lücke zu füllen„ wie der Standard es ausdrückt. Diese Sprache
bestrebt sich also einer formalen Sprache zur Spezifikation von Constraint –
Restriktionen- zu sein, die aber leicht verständlich und standardisierter Bestandteil von
UML sind .
Die OCL hat keine Kontrolle über andere Komponente eines UML-Diagramms, sondern
gibt einfach einen Wert zurück wenn sie benutzt wird. Der Entwickler ist dafür
verantwortlich, anhand des Rückgabewerts einer OCL Anweisung den passenden Code
in die Programme einzufügen. Anders ausgedrückt: Mit der OCL kann man den Zustand
eines Objekt nicht ändern man kann nur anzeigen wann der Zustand geändert wird .
a) Seiteneffekte
Mit OCL können nur Restriktionen ausgedrückt werden die für das modellierte System im
bestimmten Kontext gelten. OCL Ausdrücke sind immer frei von Seiteneffekten, das heißt
man kann weder den Zustand des Systems noch ihr unterliegendes Modell beeinflussen
(obwohl sie ein Zustandsübergang des Systems spezifizieren können). OCL bietet
dementsprechend keinerlei Konstrukte zur Programmablauf-Steuerung.
b) Warum wir die OCL einsetzen
Mit der OCL kann man für Funktionen in einem System Vor- und Nachbedingung
definieren. Man kann damit auch Wächterbedingung formulieren die in Diagrammen oder
bei Übergängen von einem Objekt zu einem anderen Objekt in einem anderen Diagramm
verwendet werden sollen. Mit der OCL kann man auch die Invarianten eines System
beschreiben. Dies sind Eigenschaften, die während der Lebenszeit eines System
unverändert bleiben müssen .
18
Die OCL wurde aus dem selben Grund definiert wie die UML: Sie soll dazu beitragen ein
Modell, genauer die Einschränkungen in einem Modell, klarer zu repräsentieren.
c) OCL Syntax
Die OCL schreibt vor, dass jede Einschränkung einen Kontext haben muss. Der Kontext
zeigt an welches Element eingeschränkt wird.
Die Einschränkung funktioniert wie ein Ausdruck, der einen speziellen Typ ergibt
(beispielsweise eine Zahl oder einen Wahrheitswert True oder False).
Alle OCL Ausdrücke sind im Kontext einer Instanz eines vom Modell definierten Typs.
19
3) Kontext und Stereotypen
Der Kontext einer Einschränkung in der OCL kann eine Klasse oder eine Operation sein.
Nachdem man den Kontext einer Einschränkung kennt muss man den Stereotyp der
Einschränkung festlegen. Dabei kann man einen von drei Typen wählen :
• Vorbedingung
• Nachbedingung
• Invariante
Vor- und Nachbedingung werden bei Operationen verwendet, während Invarianten bei
Klassen angewendet werden. Stereotypen müssen immer in französischen
Anführungszeichen (Guillemets) eingeschlossen werden .
a) Syntax der Constraints
Kommentare beginnen immer mit --- und enden mit dem Zeilenumbruch.
Die wichtigsten Referenzmethoden sind einfach und werden hier aufgelistet:
. die dem Ausdruck zugeordnete Instanz/ (Kontext):
self --- kann i.d.R. ausgelassen werden
. Attribut Attribute der Instanz/Klasse i
i.attribut
. Methode methode der Instanz /Klasse i
i.methode
. Klasse class des Pakets Package
Package::class
b) Vor- und Nachbedingungen
Ein Vorbedingung ist ein Wert der True sein muss bevor der Kontext einer Einschränkung
realisiert werden kann. Eine Nachbedingung ist ein Wert der True sein muss bevor der
Kontext einer Einschränkung als abgeschlossen betrachtet werden kann.
Context <Klassenname>::< Methodenname >(p1: Typ1 , P2: Typ2 , ..): Typ
pre : <OCL-Ausdruck>
20
post : <OCL-Ausdruck>
z.B. context Sozialkundelehrer::Fachhinzufügen(Fach ,Punktzahl) : Success
pre: Punktzahl >= 9
pre : Punktzahl <= 12
post : Faecher.includes(Fach)
In diesem Beispiel muss der Parameter Fach zwei Vorbedingung erfüllen. Ein Entwickler
sollte diese Aussage interpretieren und den entsprechenden Code zur Prüfung der
Bedingung erstellen damit das Programm sofort erkennt, ob die Punktzahl korrekt ist oder
die Operation abgebrochen werden sollte.
Wenn die Punktzahl korrekt ist und die Operation ausgeführt wird, wird das angegebene
Fach in die Fächer –Collection dieses Lehrers eingefügt.
Um eine Einschränkung für eine Operation zu repräsentieren, können wir den Kontextwert
durch den Namen und die vollständige Parameterliste der Operation ersetzen. Dies ist
erforderlich, weil Operationen überladen werden können, und nur eindeutig werden, wenn
ihre Parameterliste ebenfalls angegeben wird.
Ein Ausdruck, der in der Nachbedingung vor der Ausführung ausgewertet werden soll,
wird durch <Ausdruck>@pre angegeben
z.B.:
Die Variable result steht immer für den zurückgegebenen Wert der Operation. Beispiel:
context Acount :: getbalance() : integer
pre : true --- kann auch ausgelassen werden
post : result = balance@pre
bei verschachtelten Referenzen in der Nachbedingung muss @pre ggf. mehrmals
angewendet werden:
post : object.string@pre --- alter wert des Attributs String
post : Object@ pre.string --- neuer Wert von String des alten Objekt
post : object @pre.string@pre --- alter Wert ,alter Objekt
c) Invarianten
Eine Invariante ist ein Wert der während der gesamten Lebenszeit des Kontexts true sein
muss .
Invarianten sind immer einem Objekt des UML Modells zugeordnet
z.B.: context Schüler inv:
21
NotenSchnitt < 4.0
Diese OCL Anweisung fordert, dass das Notenschnitt-Attribut der Schülerklasse immer
kleiner als 4.0 sein muss.
Wenn die Klasse, die als Kontext einer Einschränkung vorgegeben wird, zu einem
Paket gehört, kann dieses folgendermaßen angegeben werden:
Context Lehrer:: SozialkundeLehrer inv :
ZugewieseneFächer -> umfasst (globaleStudien)
22
4) Definitionen
Manchmal ist es nützlich einen OCL Ausdruck an einem Platz zu definieren und dann
mehrmals zu nutzen. Dazu bietet sich diese Constraint Art an. Syntax :
Context Account
Def: let specialClient :Boolean
= balance > 10000
def : let toDollars(rate: Integer ) : Integer
= balance * rate
def : let couldpay (amount : Integer): Boolean
= balance >= amount
Die so angegebenen Identifikatoren können von beliebigen constraints (mit
entsprechenden Pfadangabe auch außerhalb des Kontexts ) benutzt werden.
23
5) Datentypen
OCL ist eine typisierte Sprache. Das heißt, dass die Datentypen von Attributen,
Parametern und Rückgabewerten bei der Formulierung von OCL Ausdrücken eine
wichtige Rolle spielen. Die OCL umfasst vier grundlegende Datentypen:
•••• Integer
•••• Real
•••• String
•••• Boolean
Die Operationen die auf diese vier Typen angewendet werden können:
. =,< ,>,<> ,<=,>=,+,-,*,/, max() oder min() kann auf zwei Integer- oder Realwerte
angewendet werden.
Mod() und div() können nur auf zwei Integerwerte angewendet werden .
Abs, round und floor können nur auf einen Integer- oder Realwert angewendet werden .
Für boolean sind die typischen boolschen Operatoren definiert : or, xor, and, not, und
implies. Boolsche Werte werden mit den Schlüsselwörtern true und false angegeben.
String in OCL repräsentieren ASCII-Zeichenketten. Der = Operator und die Methoden
concat (string:) : String zur Konkatenation und size() : Integer zur Längenbestimmung
sind in OCL vordefiniert concat(),= oder < > kann auf zwei Strings angewendet werden.
Size(), toLower, toUpper kann auf einen Stringwert angewendet werden .
Ein Typ muss nicht immer einer der vier Standardtypen der OCL sein. Auch die
Operationen die man auf andere Typen anwendet, müssen nicht in der OCL definiert sein
ein Modell kann zusätzliche Typen enthalten, die Attribute und Klassen umfassen können.
Klassen können ihrerseits zusätzliche Operationen definieren die man bei der
Modellierung mit der OCL verwenden kann.
Das folgende Beispiel zeigt, dass die Klasse SozialkundeLehrer über eine invariante
Bedingung verfügt die bedeutet, daß ein Lehrer (in Abhängigkeit von seinem Fach)
maximal acht Stunden arbeiten darf. „gesamtArbeitsStunden“ muss eine Funktion der
Klasse SozialkundeLehrer sein und einen Integer- oder einen Realwert zurückgeben
context SozialkundeLehrer inv :
Self.gesamtArbeitsStunden(Fächer ) <= 8
24
6) Let – Ausdrücke
Der Constraint „let“ kann in beliebigen Constraints auftauchen. In diesem Fall sind die
definierten Identifikatoren jedoch nur in den jeweiligen Constraints gültig. Die let
Konstrukte werden durch das Schlüsselwort „in“ von den restlichen Constraints getrennt:
Beispiel : context Account
def : let specialClient : boolean
=balance >100000
7) Enumeration
Enumerationen im UML Modell sind in OCL direkt als Typ benutzbar. Die Zugriffssyntax
für Elemente der Enumeration ist:
<Enumname >::<element>
25
8) Collections
Collection ist eine Gruppe von Elementen die in irgendeiner Weise verwandt sind.
Collections können sortiert und geordnet sein. Möglicherweise sind sie auch mit
Geschäftsregeln verbunden, um sicherzustellen, daß nur Elemente bestimmter Typen in
der Collection vorhanden sind. Collections können mit Operationen manipuliert werden
die ihren Inhalt verändern oder ausgeben.
Es gibt nur drei Möglichkeiten eine OCL- Sammlung zu erhalten:
1- durch literal
2- als Navigationsresultat
3- Operationen an Sammlungen können wiederum Sammlungen resultieren .
In OCL existieren keine verschachtelten Sammlungen.
In der OCL gibt es drei Typen von Collections SETS, SEQUENZEN und BAGS. Sie
unterscheiden sich in ihren Inhalten und in ihrem Verhalten wenn die OCL-Collection-
Operationen auf sie angewendet werden .
a) Sets
Ein Set (eine Menge) ist eine ungeordnete Liste unterschiedlicher Elemente. Ein Set wird
mit der folgenden Notation beschrieben:
Set {Elemente in dem Set}
z.B. set {1 , 9 , 4 ,-1, 0}
Eine Menge von Stringwerten könnte folgendermaßen aussehen
Set {`Bücher` , `Hefte` , `Kugelschreiber`}
Wir können mit der Operation including ein neues Element in die Menge einfügen, falls
dieses Element noch nicht in der Menge enthalten ist
Collection ->including (` Schreibetui `) = set {` Bücher ` , `Hefte ` , `Kulis` , ` Schreibetui `}
Mit der excluding Operation kann man ein Element aus der Menge entfernen falls es in
der Menge enthalten ist .
Collection->excluding (`Hefte`)= set {`Bücher ` , `Kulis` , `Schreibetui`}
Manchmal ergibt eine Operation die auf eine Collection angewendet wird einen anderen
Typ von Collection. Beispielsweise fügt die Union-Operation alle Elemente die in einer
Menge vorhanden sind zu den Elementen in einer anderen Menge hinzu. Weil ein
Element in beiden Mengen enthalten sein kann, kann das Ergebnis Elemente mehrfach
enthalten. Dann handelt es sich nicht mehr um eine Menge, sondern um ein Bag, also um
26
eine ungeordnete Liste von Elementen die auch mehrfach vorkommen dürfen .
set{`a` , `b`}->union(set{`b` , `d`})= bag{`a` , `b` , `b` , ` d`}
b) Sequenzen
Sequenz ist eine geordnete Liste von Elementen die mehrfach vorkommen können.
Sequenzen werden ähnlich wie Mengen geschrieben:
sequence {Elemente in der Sequenz}
Die Elemente in der Sequenz enthalten keinen Hinweis darauf, dass ihre Reihenfolge
wichtig ist. Dies ist die Aufgabe des Wortes Sequenz.
Weil die Sequenz die einzige Collection ist, bei der die Reihenfolge der Elemente eine
Rolle spielt, können einige Operationen nur auf Sequenzen angewendet werden:
(sequence {4 , 9 , 2, 0 , 1 , -23 , 2}) ->first = 4.
(sequence {4, 9, 2 , 0 , 1 , -23 , 2 })->last =2.
Mit der Operationen append und prepend kann man neue Daten am Ende und am Anfang
einer Sequenz einfügen:
(sequence{4 , 2, 1 , 3 }->append(0) = sequence {0 , 4 , 2 , 1 , 3 } )
(sequence{4 , 2, 1 , 3 }->prepend(0) = sequence { 4 , 2 , 1 , 3 , 0 } )
c) Bags
Ein bag ist eine ungeordnete Liste von Elementen die mehrfach vorkommen können. Ein
bag wird ähnlich wie die anderen beiden Collections geschrieben:
Bag {1 , 2 , 3 , 4 }
(bag{1 , 2 , 3 , 4 }) union (bag{ 3 , 3 , 3 , 3} ) = bag{ 1 , 2 , 3 , 3 , 3 , 3 , 3 , 4 }
Mit der intersection-operation kann man die Elemente ermitteln, die in zwei Bags
gemeinsam sind. Das Ergebnis ist eine Menge das heißt, jedes Element kommt nur
einmal vor.
(Bag{1 , 2 , 3 , 4 } intersection (bag {3, 3, 3 ,3 }) = set {3}
mit der asSet –Operation kann man ein Bag als eine Menge zurückgeben, das heißt die
Duplikate entfernen:
(bag{ 1, 1 , 2 , 2 , 3 , 3 }) asSet = set {1, 2, 3 }
27
9) Operationen für Collections
Die Operationen können die unterliegende Sammlung nicht beeinflussen sie sind
seiteneffektfrei. In der folgenden Tabelle werden als Beispiel einige für alle Sammlungen
definierten Methoden und die Bedeutung ihrer Werte aufgelistet
size() : integer die Anzahl der Elemente der Sammlung
includes (<object>): boolean true falls die Sammlung <object> enthält
includesall(<collection>)
true falls die Sammlung alle Elemente von
<collection> enthält
isEmpty():boolean true falls size()=0
Cont(<object>) : integer Wieviele Male ist <object> in der Sammlung enthalten
Sum () : T summiert alle Elemente der Sammlung. Für alle Elemente muss der Operator
+ definiert sein. Der Resultat vom Typ T hat den selben Typ wie die Elemente der
Sammlung
exists (<expression >) : boolean liefert true falls < expression > für mindestens eines der
Elementen true ist .
a) Konformität der Typen „ casting“
Wie oben erwähnt sind die Typen von OCL in eine Hierarchie angeordnet. Die Regeln für
Konformität sind in OCL genauso wie in UML (und üblichen objektorientierten
Programmiersprachen) definiert.
Um den syntaktischen Typ eines Ausdruckes zu verändern, können so genannte Casts
angegeben werden. Diese sind nur gültig, falls der direkte Typ des Ausdrucks mit dem
Typ des Casts konformant ist.
Die Syntax lautet:
<expression> oclASType (type2) --- ergibt einen Objekt vom Typ Type 2
28
b) If-Then-Else:
Der if-then-else ist in OCL ein Ausdruck. Die Syntax ist:
If <BooleanExpression>
Then <Expression1>
Else <Expression2>
Endif
Falls <BooleanExpressio> true ist, wird der erste Ausdruck zurück gegeben, andernfalls
der zweite.
Es ist zu beachten, dass der Typ des Ausdrucks eindeutig definiert sein muss: Die
Klassen von Expression1 und expression2 müssen eine gemeinsame Klasse besitzen,
d.h. sie müssen eine der folgenden Eigenschaften erfüllen.
• gleich sein
• in eine (direkte/ indirekte) Generalisierungsbeziehung stehen
• eine gemeinsame Oberklasse besitzen
Der Typ des if-then-else-Ausdruckes wird als die am meisten spezifische gemeinsame
zuweisbare Klasse festgelegt.
29
10) Navigation
Die Navigationstechniken von OCL werden anhand eines Beispiels erläutert. Dabei
werden auch die in obigen Abschnitten beschriebenen Konzepte und Syntaxen
demonstriert.
Abb. 1 zeigt den Beispiel-Model.
Abbildung: Beispiel –UML - Modell
30
Customer#name :String#custNo : Integer#address : String#phone :String+getCustNo():Integer~SetcustNo(custNo:Integer)+getName: String~setName(name:String)…
Account#accNo : integer#balance : integer~getbalance : integer ~getAcctNo() : Integer
11) Attribute und Methoden der Kontext-Instanz
Attribute und Methoden der Instanz self können ohne weitere Qualifizierung benutzt
werden.
Beispiel:
Context: Account
Inv: getBalance ( ) >0
Damit das ein gültiger OCL-Ausdruck wird, muss die Methode getBalance ( ) natürlich
seiteneffektfrei sein. D.h. das Attribut isQuery der Methode im UML- Modell muss true
sein.
Dies wurde in der Abbildung ausgelassen, da die Namen der Methoden in diesem Fall für
die Klassifikation genügen.
31
12) Zugriff auf assoziierte Instanzen
Dieser wird im Allgemeinen durch Angaben des Rollennamens ermöglicht. Falls keine
Mehrdeutigkeit existiert, kann auch der Klassennamen (mit kleingeschriebenem ersten
Buchstaben) benutzt werden.
Beispiel:
Context Account
Inv: not owner.adress = “ - - - Rolle wird benutzt
Legt fest, dass eine Adresse für den Kontoinhaber immer vorhanden sein muss.
Beispiel:
context Costumer
def: let totalBalance : interger
= account getBalance ( ) - > sum ( )
-- - Klassenname wird benutzt
Hier werden alle Kontostände eines Kunden zusammengerechnet. Da account ein
Assoziationsende mit Multiplizität > 1 darstellt, wird es nicht als eine Referenz vom Typ
Account, sondern als ein Bag (Account) ausgewertet, der alle Accounts des
Kontoinhabers beinhaltet. Darüber hinaus ist collect ( ) die default-Aktion für Collections.
D.h. der obige Ausdruck nach dem Gleichheitszeichen wird wie
Account - > Collect (getBalanace ( ) ) - > sum ( ) ausgewertet. Mittels collect ( ) wird also
ein Bag (Integer) erstellt, der alle Kontostände des Kontoinhabers enthält. Die Methode
sum ( ) liefert schließlich das Ergebnis.
Beispiel:
Context Costumer
Inv: account - > notEmpty ( ) implies
Account.getBalance ( ) - > sum ( ) > 0
Legt fest, falls ein Kunde offeneKonten hat, der Gesamtkontostand > 0 sein muss. Einfach
Account.get Balance ( ) > sum ( ) > 0
Dies als Invariante zu benutzen wäre hier problematisch, da der Ausdruck nicht immer
definiert ist.²
_________________________
² genauer genommen, ist die Semantik von OCL in keinen der Fälle wirklich definiert
doch dies wird sich möglicherweise ändern.
32
13) Assoziationsklassen
Assoziationsklassen werden auch mittels “.“ navigiert. Da sie keine „Rolle“ im UML-Modell
besitzen, wird einfach der Klassenname, mit Kleinbuchstaben angefangen, benutzt.
Self.<associationClass> - - - Zugriff der Assoziations
- - - klasse AssiciationsClass
Falls die Assoziationsklasse mehrmals mit einer Klasse verbunden ist, müssen im UML-
Modell Rollen angegeben werden. Nur so lässt sich ein eindeutiger OCL-Ausdruck bilden:
der Rollnename wird in eckigen Klammern angegeben:
Self.<associationClass>[<roleName>]
33
14) Perspektiven
In den vorigen Abschnitten wurde ein Überblick über die Sprache OCL verschafft. Hier
werden einige Probleme der Sprache angesprochen, die einen seriösen Einsatz
verhindern und einige Vorschläge zur Erweiterung gemacht.
a) Formale Semantik
Der UML-Standard beschreibt die Syntax von OCL auf eine formale Weise. Die Semantik
wird jedoch anhand von Beispielen und natürlicher Sprache „erklärt“. Man kann
dementsprechend bei OCL nicht wirklich von einer formalen Sprache reden.
Wie bereits vorher angedeutet, ist eine explizit angegebene semantische Abbildung der
Syntax zu einer bekannten Semantik von Bedeutung, falls Beweise der Korrektheit und
Erfüllbarkeit ermöglicht werden sollen.
Die inhärente Mehrdeutigkeit der OCL-Spezifikation behindert auch die Benutzung und
Entwicklung von Werkzeugen, die eine formale Spezifikationssprache voll ausnutzen
können.
34
15) Integration in das objektorientierte Modell
a) Zugriffsrechte
In OCL sind keinerlei Zugriffsbeschränkungen eingeführt. Das kann für eine
Spezifikationssprache in bestimmten Fällen nützlich sein. Bestimmte Konstrukte sind aber
semantisch sehr schwach zu deuten und bringen nur unnötige Komplexität mit sich. Als
Beispiel sei die Methode allInstances ( ) gegeben, die die Menge aller Instanzen einer
Klasse zurückgibt.
Mit Context Aclass inv
... Another Package: : AnotherClass.allInstances ( ) ..
kann innerhalb von aClass eine Invariante für die Klasse AnotherClass, die sich
möglicherweise sogar in einem anderen Paket befindet, spezifiziert werden.
Überhaupt ist die Bedeutung von allInstances ( ) wohl auch den OCL-Entwicklern unklar,
die beispielsweise Integer.allInstances ( ) Als�
definieren, da unendlich viele Zahlen
existieren, aber trotzdem bekennen, dass auch für allInstances auf jeden Fall ein Kontext
definiert sein muss, sei es auch ein allgemeiner Kontext (was in OCL nicht getan wird).
Auf jeden Fall wäre aber eine Beschränkung auf navigierbaren Referenzen (also das
Abschaffen von allInstances ( ), etc) angesichts der in Version 1.4 des Standards
eingeführten Spracherweiterungen³ nur von Nutzen.
b) Vererbung und Interfaces
In der Spezifikation wird nichts über die Vererbung der constraints gesagt. Die mögliche
Spezifikation von Invarianten für Interfaces wird auch nicht angesprochen. Beide Themen
bringen eine gewisse Komplexität mit sich, die Konzepte könnten sich dadurch als
nützlich erweisen.
Auf jeden Fall darf die Angelegenheit von einen Standard nicht einfach ignoriert werden.
c) Verhaltensmodellierung
Obwohl UML auf die Modellierung dynamischer Systemaspekte einen besonderen Akzent
setzt, kann OCL nur zur Spezifikation von strukturellen, statischen Vorgaben benutzt
35
werden (dies schließt permanente constraints für den Zustand (Inavarianten) als auch
constraints für den Zustand vor/ nach einer Operation ein).
Was nicht ausgedrückt werden kann, sind dynamische Abhängigkeiten zwischen Werten
und Aufrufen. In OCL kann der Aufruf einer Methode (z.B. in Abhängigkeit mit einer
Wertänderung oder einem anderen Aufruf) überhaupt nicht spezifiziert werden.
Des Weitren bleibt die Parallelität von OCL völlig unberührt, auch wenn diese gerade in
komplexen Systemen, die von einer mächtigen, graphisch-orientierten
Modellierungssprache am meisten profitieren würden, sehr oft vorhanden ist.
__________________________
³ Diese Spracherweiterung führen eine Methode, mit der in der Nachbedingung überprüft
werden kann, ob ein neues Objekt instanziiert wurde.
36
16) Spezifikation von Operationen
Bei der Behandlung der Vor- und Nachbedingungen in OCL, ist dem Leser vielleicht
aufgefallen, dass wir keine syntaktischen Vereinbarungen zur Angabe der Lese/
Schreibrechte vereinbart haben.
OCL-Ausdrücke haben aber wie oben erwähnt, nicht nur die Möglichkeit ihren Kontext
sondern auch das gesamte System zu betrachten. Darüber hinaus sind sie im Stande
Zustandsänderungen zu spezifizieren, und es gibt auch keine explizite Sperre für die
Wirkung einer Funktion außerhalb der beabsichtigten Zustandselemente.
Wir können also eine Operation Ø programmieren, die im Sinne der Vor- und
Nachbedingungen (und Klassenvarianten) die Spezifikation einer gegebenen Operation f
erfüllt aber auch beliebige weitere Teile des Zustandes verändert. Die Spezifikation von f
könnte sogar eine seiteneffektfreie Funktion beabsichtigt haben. Es gibt keinen Weg dies
auszudrücken.
OCL kann dementsprechend nicht dazu benutzt werden, die wesentlichen Eigenschaften
von Operationen zu modellieren, was die Sprache für bestimmte Spezifikationszwecke
nutzlos macht.
a) Logik und undefinierte Werte
Aus dem Standard ist erkennbar, dass OCL sich einer dreiwertigen Logik bedient. Die
Vorstellung der Autoren für die Behandlung von�
- Werte ist aber nirgendwo nach zu
lesen.
Alle OCL-Ausdrücke die�
enthalten müssen zwingend auch�
als Wert einnehmen. Eine
Ausnahme wird nur für die Operatoren or und and gemacht die, wie üblich monoton, im
Sinne des Wissensgrades, erweitert werden. Da OCL seine logischen Operatoren nicht
aufeinander aufbaut, bedeutet dies aber, dass if-then-else und implies Ausdrücke�
ergeben, sofern auch nur einer der Argumente�
ist. Dies macht nicht nur einige unserer
Beispiele ungültig sondern auch diese des Standards!
Eine viel genauere Betrachtung der Logik in OCL (und vielleicht ein Überdenken des
traditionellen Einsatzes der dreiwertigen Logik) ist nötig, um die Operatoren sinnvoll auf
zu bauen und eine sinnvolle Semantik der Sprache festlegen zu können.
37
Literaturverzeichnis:
� UML konzentriert: Martin Fowler, Kendall Scott� UML@work: Martin Hitz, Gerti Kappel� Objektorientierte Softwareentwicklung: Bernd Östereicher� www-4.ibm.com/software/ad/standards/ocl.html
38