Object Constraint Language (OCL)
Object Constraint Language (OCL)
Object Constraint Language (OCL)
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
© 2004-2007, Rainer Schmidberger, ISTE<br />
<strong>Object</strong> <strong>Constraint</strong><br />
<strong>Language</strong> (<strong>OCL</strong>)<br />
Rainer Schmidberger<br />
rainer.schmidberger@informatik.uni-stuttgart.de<br />
se<br />
© 2004-2007, Rainer Schmidberger, ISTE<br />
11.01.2007<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
<strong>OCL</strong><br />
Die <strong>Object</strong> <strong>Constraint</strong> <strong>Language</strong> ist Teil von UML 2.0<br />
<strong>OCL</strong> ist eine formale, prädikatenlogikbasierte Sprache<br />
zur ergänzenden Spezifizierung von UML-Modellen<br />
<strong>OCL</strong> Ausdrücke sind leicht zu lesen (leichter als<br />
beispielsweise die von Z oder die Prädikatenlogik)<br />
<strong>OCL</strong> Ausdrücke sind deklarativ, d.h. sie ändern den<br />
Systemzustand nicht<br />
Dient zur Formulierung von Zusicherungen<br />
Invarianten von Klassen<br />
Vor- und Nachbedingungen von Methoden<br />
Nutzen von <strong>OCL</strong><br />
se<br />
Die UML-Modelle können präziser beschrieben werden<br />
Programmcode kann generiert werden<br />
Folie 104<br />
1
© 2004-2007, Rainer Schmidberger, ISTE<br />
11.01.2007<br />
<strong>OCL</strong> <strong>Constraint</strong>s (1)<br />
<strong>OCL</strong> constraints werden relativ zu einem Systemzustand<br />
S ausgewertet<br />
<strong>OCL</strong> constraints sind vom Typ Boolean; sie sind wahr<br />
oder falsch bezüglich S<br />
<strong>OCL</strong> constraints beschränken die erlaubten<br />
Systemzustände eines UML Klassendiagramms<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
se<br />
Folie 105<br />
© 2004-2007, Rainer Schmidberger, ISTE<br />
11.01.2007<br />
<strong>OCL</strong> <strong>Constraint</strong>s (2)<br />
Invarianten:<br />
Eine Invariante I für eine Klasse C ist ein Boolscher <strong>OCL</strong>-<br />
Ausdruck.<br />
Semantik: I gilt in jedem feststellbaren Zustand (snapshot) jeder<br />
Instanz von C.<br />
Vor- und Nachbedingungen:<br />
Vor- und Nachbedingungen (v, n) für eine Operation p ist ein<br />
Paar von Boolschen <strong>OCL</strong>-Ausdrücken.<br />
Semantik: v muss zum Zeitpunkt, wenn p aufgerufen wird, true<br />
sein. n muss zum Zeitpunkt, wenn p terminiert, true sein<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
se<br />
Folie 106<br />
2
Der Kontext<br />
© 2004-2007, Rainer Schmidberger, ISTE<br />
Der Kontext legt fest, auf welches Element sich ein <strong>OCL</strong> <strong>Constraint</strong><br />
bezieht.<br />
context [ kontextInstanz : ] typeName<br />
inv: OclAusdruck1<br />
...<br />
inv: OclAusdruckn<br />
11.01.2007<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
Beispiel:<br />
se<br />
context Person<br />
inv: self.alter > 0<br />
self (die referenziert per<br />
default auf die Kontext-<br />
Instanz)<br />
Soll bedeuten: zu keinem<br />
Zeitpunkt darf es ein Objekt der<br />
Klasse Person geben, das einen<br />
negativen Wert im Attribut alter<br />
hat<br />
Folie 107<br />
Boolean Operationen<br />
© 2004-2007, Rainer Schmidberger, ISTE<br />
Operation<br />
Oder | Und |<br />
Exklusiv Oder<br />
Negation<br />
Notation<br />
a or | and | xor b<br />
not a<br />
Ergebnistyp<br />
Boolean<br />
Boolean<br />
11.01.2007<br />
Vergleich<br />
Ungleichheit<br />
a = b<br />
a b<br />
Boolean<br />
Boolean<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
se<br />
Impliziert (wenn a<br />
true ist, muss auch b<br />
true sein<br />
a implies b<br />
Boolean<br />
Folie 108<br />
3
Integer/Real Operationen<br />
© 2004-2007, Rainer Schmidberger, ISTE<br />
Operation<br />
Vergleich<br />
Rechnen<br />
Modulo<br />
Notation<br />
a = b, ab, ab, a=b,<br />
a+b, a-b, a*b, a/b<br />
a.mod(b)<br />
Ergebnistyp<br />
Boolean<br />
Integer/Real<br />
Integer/Real<br />
11.01.2007<br />
Min, Max<br />
a.max(b), a.min(b)<br />
Integer/Real<br />
...<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
se<br />
Folie 109<br />
© 2004-2007, Rainer Schmidberger, ISTE<br />
11.01.2007<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
Spezielle <strong>OCL</strong>-Operatoren<br />
oclIsTypeOf (t : OclType) : Boolean<br />
oclIsKindOf (t : OclType) : Boolean<br />
oclInState (s : OclState) : Boolean<br />
Prüfung von Zuständen bei Zustandsautomaten (State D.)<br />
oclIsNew () : Boolean<br />
für Nachbedingungen, prüft, ob Objekte innerhalb einer<br />
Methode neu erzeugt wurden<br />
oclAsType(t :OclType) :instanceof OclType<br />
Beispiel:<br />
se<br />
context Person<br />
inv: self.oclIsTypeOf( Person ) -- ist true<br />
inv: self.oclIsTypeOf( Firma) -- ist false<br />
Folie 110<br />
4
© 2004-2007, Rainer Schmidberger, ISTE<br />
11.01.2007<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
<strong>OCL</strong> Kollektionen<br />
Set(Menge), OrderdSet<br />
Bag (Liste)<br />
Sequence (geordnete Liste)<br />
Instanzierung:<br />
als Literal<br />
Set { 1, 2, 4, 42}<br />
Sequence {1..10} entspricht Sequence {1,2,3,4,5,6,7,8,9,10}<br />
durch Navigation<br />
durch Aufruf von Kollektionsmethoden<br />
durch Klasse.allInstances()<br />
se<br />
Folie 111<br />
<strong>OCL</strong> Kollektionen (Auszug)<br />
© 2004-2007, Rainer Schmidberger, ISTE<br />
11.01.2007<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
se<br />
Operator<br />
count(objekt)<br />
size<br />
isEmpty<br />
notEmpty<br />
forAll()<br />
exists()<br />
select()<br />
includesAll<br />
(Menge2)<br />
Ergebnistyp<br />
integer<br />
integer<br />
boolean<br />
boolean<br />
boolean<br />
boolean<br />
Menge<br />
boolean<br />
Beschreibung<br />
Anzahl, wie oft das Objekt in der<br />
Kollektion enthalten ist<br />
Anzahl d. Elemente<br />
wahr, wenn Menge leer ist<br />
falsch, wenn Menge leer ist<br />
wahr, wenn für jedes<br />
Element gilt<br />
wahr, wenn für mind.<br />
ein Element gilt<br />
Teilmenge, für die gilt<br />
wahr, wenn alle Elemente der<br />
Menge Menge2 enthalten sind<br />
Folie 112<br />
5
© 2004-2007, Rainer Schmidberger, ISTE<br />
11.01.2007<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
<strong>OCL</strong> Kollektionen (2)<br />
se<br />
c->forAll(objekt1, ... Objektn |<br />
)<br />
context Firma<br />
inv:<br />
self.Mitarbeiter->forAll(p1, p2 |<br />
p1 p2 implies p1.Name p2.Name)<br />
c->exists(objekt1, ... Objektn |<br />
)<br />
liefert true falls für<br />
alle Elemente true ist.<br />
liefert true falls für<br />
mindestens eines der<br />
Elemente true ist.<br />
context Firma<br />
inv:<br />
self.Mitarbeiter->exists(p | p.Gehalt > 100000)<br />
Folie 113<br />
© 2004-2007, Rainer Schmidberger, ISTE<br />
11.01.2007<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
<strong>OCL</strong> - Beispiel<br />
se<br />
Person<br />
Name<br />
Vorname<br />
Gehalt<br />
Alter<br />
Mitarbeiter<br />
0..*<br />
Arbeitgeber<br />
Firma<br />
Bezeichnung<br />
Die Mitarbeiter sind mind. 16 und max. 65 Jahre alt<br />
Jeder hat ein Gehalt > 0<br />
context Firma<br />
inv:<br />
self.Mitarbeiter->forAll(m | m.Alter>=16 and m.AlterforAll(m | m.Gehalt >= 0)<br />
0..1<br />
Folie 114<br />
6
<strong>OCL</strong> - Beispiel<br />
© 2004-2007, Rainer Schmidberger, ISTE<br />
0..*<br />
Mitarbeiter<br />
0..1<br />
Chef<br />
Person<br />
Name<br />
Vorname<br />
Gehalt<br />
Alter<br />
Mitarbeiter<br />
0..*<br />
0..1<br />
Arbeitgeber<br />
Firma<br />
Bezeichnung<br />
11.01.2007<br />
Der Chef verdient mehr als sein Mitarbeiter<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
se<br />
context Person<br />
inv:<br />
self.Chef->notEmpty() implies<br />
self.Chef.Gehalt > self.Gehalt<br />
Folie 115<br />
<strong>OCL</strong> - Beispiel<br />
© 2004-2007, Rainer Schmidberger, ISTE<br />
0..*<br />
Mitarbeiter<br />
0..1<br />
Chef<br />
Person<br />
Name<br />
Vorname<br />
Gehalt<br />
Alter<br />
Mitarbeiter<br />
0..*<br />
0..1<br />
Arbeitgeber<br />
Firma<br />
Bezeichnung<br />
11.01.2007<br />
Der Chef arbeitet bei der selben Firma wie sein Mitarbeiter<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
se<br />
context Person<br />
inv:<br />
self.Chef->notEmpty() implies<br />
self.Chef.Arbeitgeber = self.Arbeitgeber<br />
Folie 116<br />
7
<strong>OCL</strong> - Beispiel<br />
© 2004-2007, Rainer Schmidberger, ISTE<br />
0..*<br />
Mitarbeiter<br />
0..1<br />
Chef<br />
Person<br />
Name<br />
Vorname<br />
Gehalt<br />
Alter<br />
Mitarbeiter<br />
0..*<br />
0..1<br />
Arbeitgeber<br />
Firma<br />
Bezeichnung<br />
11.01.2007<br />
Es gibt mindestens einen „Oberchef“<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
se<br />
context Firma<br />
inv:<br />
self.Mitarbeiter->select(Chef->isEmpty())->size >= 1<br />
Folie 117<br />
Vor- und Nachbedingungen<br />
© 2004-2007, Rainer Schmidberger, ISTE<br />
11.01.2007<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
se<br />
Person<br />
Name<br />
Gehalt : Real<br />
Mitarbeiter<br />
0..*<br />
0..1<br />
Arbeitgeber<br />
Firma<br />
Bezeichnung<br />
istPleite : Boolean<br />
einstellen(p : Person)<br />
context Firma::einstellen(p : Person)<br />
pre:<br />
not self.istPleite and -- Firma ist nicht pleite<br />
p.Arbeitgeber->isEmpty() -- Person ist nicht bereits<br />
-- anderswo beschäftigt<br />
post:<br />
p.Arbeitgeber = self and -- jetzt eingestellt<br />
p.Gehalt > p.Gehalt@pre -- Stellenwechsel mit<br />
-- Gehaltserhöhung<br />
Folie 118<br />
8
© 2004-2007, Rainer Schmidberger, ISTE<br />
11.01.2007<br />
<strong>OCL</strong> Messages<br />
Um auszudrücken, dass eine „Botschaft“ versendet<br />
wurde, dient der hasSent (‘^’) Operator:<br />
context Firma::einstellen(p : Person)<br />
post: p^setArbeitgeber(self)<br />
Bei unspezifizierten Parametern:<br />
context Subject::hasChanged()<br />
post: observer^update(? : Integer, ? : Integer))<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
Die Menge der Aufrufe einer Methode an einen<br />
Empfänger wird über ^^ ausgedrückt<br />
se<br />
Folie 119<br />
<strong>OCL</strong> Werkzeuge<br />
11.01.2007<br />
© 2004-2007, Rainer Schmidberger, ISTE<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
se<br />
Folie 120<br />
9
11.01.2007<br />
© 2004-2007, Rainer Schmidberger, ISTE<br />
<strong>OCL</strong> Literatur<br />
http://www.omg.org/technology/documents/modeling<br />
_spec_catalog.htm<br />
Jos Warmer, Anneke Kleppe, „The <strong>Object</strong> <strong>Constraint</strong><br />
<strong>Language</strong>“, second edition, Addison-Wesley, 2003.<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
se<br />
Folie 121<br />
© 2004-2007, Rainer Schmidberger, ISTE<br />
11.01.2007<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
Übung<br />
se<br />
+assistenzTrainer<br />
0..*<br />
Trainer<br />
Verein<br />
vereinsName : String<br />
1<br />
+arbeitgeber<br />
+mitarbeiter 11..*<br />
Spieler<br />
istVerletzt : Boolean<br />
istTorwart : Boolean<br />
1<br />
+chefTrainer<br />
+torwart<br />
1<br />
+feldspieler<br />
10<br />
Spiel<br />
austragungsort : String<br />
austragungsDatum : Date<br />
0..1<br />
Aufstellung<br />
auswechseln(spielerRein : Spieler, spielerRaus : Spieler)<br />
0..1<br />
+gast<br />
+heim<br />
Folie 122<br />
10
© 2004-2007, Rainer Schmidberger, ISTE<br />
11.01.2007<br />
Aufgabe<br />
Jeder Verein hat mindestens einen Cheftrainer<br />
Kein Spieler einer Aufstellung ist verletzt<br />
Alle Spieler einer Aufstellung arbeiten beim selben<br />
Verein<br />
Vor und Nachbedingung<br />
auswechseln<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
se<br />
Folie 123<br />
© 2004-2007, Rainer Schmidberger, ISTE<br />
Übung a:<br />
Jeder Verein hat mindestens einen Cheftrainer<br />
context Verein<br />
inv: not self.chefTrainer->isEmpty()<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
11.01.2007<br />
se<br />
Folie 124<br />
11
© 2004-2007, Rainer Schmidberger, ISTE<br />
11.01.2007<br />
Übung b:<br />
Kein Spieler der Aufstellung ist verletzt<br />
context Aufstellung<br />
inv: self.feldSpieler->Select(istVerletzt)->isempty()<br />
inv: not self.torwart.istVerletzt<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
se<br />
Folie 125<br />
© 2004-2007, Rainer Schmidberger, ISTE<br />
11.01.2007<br />
Übung c:<br />
Alle Spieler einer Aufstellung arbeiten beim selben Verein<br />
context Aufstellung<br />
inv: self.feldSpieler->forAll(s1, s2 |<br />
s1.arbeitgeber = s2.arbeitgeber)<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
se<br />
Folie 126<br />
12
© 2004-2007, Rainer Schmidberger, ISTE<br />
11.01.2007<br />
Übung d:<br />
Auswechslung<br />
context Aufstellung::auswechseln(spielerRein : Spieler,<br />
spielerRaus : Spieler)<br />
pre:<br />
self.feldspieler->exists(spielerRaus) and<br />
not self.feldspieler->exists(spielerRein) and<br />
not spielerRein.istVerletzt<br />
Programmentwicklung,<br />
Vorlesungsskript UML<br />
se<br />
post:<br />
not self.feldspieler->exists(spielerRaus) and<br />
self.feldspieler->exists(spielerRein)<br />
Folie 127<br />
13