OCL a integritní omezení Karel Richta Katedra softwarového inženýrství Fakulta informačních technologií České vysoké učení technické v Praze ©
[email protected], 2011
Softwarové inženýrství I., BI-SI1 04/2011, Přednáška 9
Evropský sociální fond Praha & EU: Investujeme do vaší budoucnosti
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 1/78
Proč OCL? • Pomocí diagramů UML nelze popsat všechno – proto je součástí specifikace UML i definice OCL. • Co je zvláštní na následujícím obrázku?
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 2/78
Jiný příklad: Předměty a zkoušky class Studium bez omez... Předmět
Student -
jméno: string příjmení: string 0..*
studuje 0..*
0..* -
si zapsal
+z
0..*
+má
kód: string název: string 1
0..*
Zkouškový termín -
[email protected] (ČVUT)
datum: Date místnost: int
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 3/78
Předměty a zkoušky o něco lépe class Příklad Studium s omezením
Student -
jméno: string příjmení: string
Předmět
studuje 0..*
0..*
+z
0..*
-
kód: string název: string 1
si zapsal {C1}
Student/studentka si mohou zapsat zkouškový termín pouze z předmětů, které právě studují.
[email protected] (ČVUT)
+má 0..*
0..*
Zkouškový termín -
datum: Date místnost: int
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 4/78
OCL - Object Constraint Language • pochází z metodiky Syntropy (IBM) http://en.wikipedia.org/wiki/Syntropy • je čistě funkcionální (bez vedlejších efektů) • není to programovací jazyk - je určen pro vyjádření invariantů - je to specifikační jazyk • je silně typovaný (každý výraz OCL má definován typ) • má předdefinovanou sadu typů (primitivní typy Integer, Boolean, String, Real, UnlimitedInteger a z nich utvořené kolekce)
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 5/78
Jak vypadá zápis v OCL? context <jméno> [inv|pre|post]:
klíčové slovo context slouží pro definici kontextu pro výraz v OCL, např. zápis: context Osoba inv : označuje, že uvedený výraz se vztahuje k instanci kontextu (třídy) Osoba (na kterou se lze odkazovat klíčovým slovem self) klíčová slova inv, pre, post zastupují stereotypy <>, <<precondition>>, <<postcondition>>
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 6/78
Příklad zápisu v OCL context Osoba inv: self.příjem > 10000 tento zápis vyjadřuje, že pro každou instance třídy Osoba, musí mít atribut příjem hodnotu větší než 10000
context x:Osoba inv: x.příjem > 10000 označuje totéž
context x:Osoba inv OK : x.příjem > 10000 zavádí pro toto integritní omezení jméno (OK)
Příklad popisu metody: context Osoba::pridej(kolik:Integer):Integer pre : kolik > 100 -- nemá smysl přidávat méně post : result = self.příjem@pre + kolik [email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 7/78
Příklad: Předměty a zkoušky class Studium v OCL Student
Předmět studuje
-
jméno: string příjmení: string
0..* -
0..* 0..*
kód: string název: string +z
1
si zapsal {C1} «Invariant» {-- Student/studentka si mohou zapsat zkouškový termín pouze z předmětů, které právě studují. inv C1 : is-element(self.si_zapsal.z, studuje)}
[email protected] (ČVUT)
OCL a integritní omezení
+má 0..* 0..*
Zkouškový termín -
datum: Date místnost: int
BI-SI1, 2011, Přednáška 9, 8/78
EA vygeneruje tabulky, ale integritní omezení ne.
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 9/78
Příklad: Hypotéky Uvažme příklad světa hypoték - ukázka z katalogu požadavků: 1. Každá hypotéka bude vždy pro jednu osobu. 2. Osoba si může vzít několik hypoték. 3. Každou nemovitost vlastní právě jedna osoba. 4. Osoba může vlastnit libovolný počet nemovitostí. 5. Každá hypotéka musí být zajištěna nejméně jednou nemovitostí. 6. Nemovitost může být použita k zajištění více hypoték.
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 10/78
Příklad modelu evidence hypoték class Hypotéky bez omezení
Osoba Nemovitost +vlastní
-
-
označení: string hodnota: penize +je_zajištěna
+je_majetkem -
0..*
1 -
+
1..*
jméno: string příjmení: string příjem: peníze žádost(peníze, Nemovitost) : boolean +pro
+zajišťuje
+má_půjč enu
0..*
1
0..*
Hypotéka -
[email protected] (ČVUT)
od: datum do: datum celková_částka: peníze = 250.000,měsíční_splátka: peníze
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 11/78
Příklad: Hypotéky o něco lépe class Hypotéky s omezením
Osoba Nemovitost +vlastní
-
označení: string hodnota: penize +je_zajištěna
+je_majetkem
0..*
1
1..*
-
jméno: string příjmení: string příjem: peníze
+
žádost(peníze, Nemovitost) : boolean +pro
«Invariant» {Hypotéka může být zajištěna pouze takovými nemovitostmi, které daná osoba vlastní.}
{C1}
+zajišťuje 0..* +má_půjč enu
0..*
Hypotéka -
[email protected] (ČVUT)
1
od: datum do: datum celková_částka: peníze = 250.000,měsíční_splátka: peníze
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 12/78
class DDL
Nemov itost Osoba «column» označení: VARCHAR2(50) +FK_je_majetkem +PK_Osoba «column» hodnota: penize jméno: VARCHAR2(50) (je_majetkem = osobaID) *pfK nemovitostID: Integer příjmení: VARCHAR2(50) FK je_majetkem: Integer příjem: peníze «FK» 0..* 1 *PK osobaID: Integer «PK» + PK_Nemovitost(Integer)
«PK» + PK_Osoba(Integer)
«FK» + skládá se z(Integer) + FK_je_majetkem(Integer)
CASE (EA) vygeneruje tabulky, ale integritní omezení ne.
+PK_Osoba
1
(pro = osobaID)
+PK_Nemovitost
«FK» +FK_pro 0..*
(nemovitostID = nemovitostID) «FK»
Hypotéka
+Nemovitost 0..* JoinHypotékaToNemov itost «column» *FK nemovitostID: Integer *FK hypotékaID: Integer
«column» od: datum do: datum +Hypotéka +PK_Hypotéka celková_č ástka: peníze = 250.000,(hypotékaID = hypotékaID) měsíč ní_splátka: peníze «FK» *PK hypotékaID: Integer 1..* FK pro: Integer
«FK» + Nemovitost(Integer) + Hypotéka(Integer)
«PK» + PK_Hypotéka(Integer) «FK» + FK_pro(Integer)
13
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 13/78
CASE vygeneruje SQL, ale IO ne. DROP TABLE Hypotéka CASCADE CONSTRAINTS; . . . CREATE TABLE Hypotéka ( od do celková_částka měsíční_splátka hypotékaID pro ); . . .
DATE, DATE, NUMBER(12,2) DEFAULT 250.000,-, NUMBER(12,2), Integer NOT NULL, Integer
ALTER TABLE Hypotéka ADD CONSTRAINT PK_Hypotéka PRIMARY KEY (hypotékaID); . . . ALTER TABLE Hypotéka ADD CONSTRAINT FK_pro FOREIGN KEY (pro) REFERENCES Osoba (osobaID); . . .
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 14/78
Ale mohl by něco vygenerovat • V popisu integritního omezení v jazyce OCL je dost informace pro vygenerování integritního omezení – např. pro SQL: ALTER TABLE JoinHypotékaToNemovitost ADD CONSTRAINT C2 CHECK ( /* -- Hypotéky osoby mohou být zajištěny pouze nemovitostmi, které tato osoba vlastní. context inv: self.je_zajištěna.je_majetkem = self.pro */ nemovitostID.je_majetkem = hypotékaID.pro );
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 15/78
Kdy použít OCL? • pro vyjádření integritních omezení v datovém modelu (diagramu tříd) • pro vyjádření typových omezení při definici stereotypů • pro popis vstupních a výstupních podmínek operací, nebo • pro popis operací (metod) ve tvaru: operace(x1, …, xn) = výraz kde výraz může obsahovat x1, …, xn
• jako navigační jazyk
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 16/78
Výrazy v OCL self.příjem hodnota vlastnosti objektu o kterém v daném kontextu mluvíme – v tomto případě se jedná o atribut a hodnotu typu „peníze“
x.vlastní hodnota vlastnosti objektu o kterém v daném kontextu mluvíme – v tomto případě se jedná o vztah a hodnotu typu „kolekce nemovitostí“ (případně prázdná) class Příklad modelu pro hypotéky skládá se 1 z
0..* Osoba
Nemov itost -
označení: string hodnota: penize
+vlastní 0..*
+je_majetkem 1 +
+je_zajištěna
jméno: string příjmení: string příjem: peníze žádost(peníze, Nemovitost) : boolean
1..* +pro
1
Nemovitost se zde chápe jako
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 17/78
Příklad použití OCL I. class Auta
Person -
name: String birthdate: Date /age: int
+ + +
getName() : String {query} birthDay() : Date setAge(int) : int
1
Date -
«enumeration» Colour
Vehicle +ow ner ow nership
+fleet 0..*
-
colour: Colour
Car
black white red
Bike
day: int month: int year: int
• Kolik osob může vlastnit auto? • Vlastníkem auta může být osoba, které je alespoň 18 let? context Car inv: self.owner.age >= 18
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 18/78
Příklad použití OCL II. class Auta
Person -
name: String birthdate: Date /age: int
«enumeration» Colour
Vehicle +ow ner ow nership 1
+fleet 0..*
-
colour: Colour
black white red
+ getName() : String {query} + birthDay() : Date + setAge(int) : int
Date -
Car
Bike
day: int month: int year: int
• Co znamená podmínka? context Person inv: self.age >= 18
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 19/78
Příklad modelu evidence hypoték class Příklad modelu pro hypotéky skládá se 1 z
0..* Osoba
Nemov itost -
+vlastní
označení: string hodnota: penize
+je_majetkem 1 -
0..*
+ +je_zajištěna
jméno: string příjmení: string příjem: peníze žádost(peníze, Nemovitost) : boolean
1..* +pro
1
Nemovitost se zde chápe jako jednotka vlatnictví. Pokud nějakou nemovitost vlatsní více osob, rozdělí se na samostatné č ásti dle podílu vlastníků.
Hypotéka +zajišťuje 1..* -
[email protected] (ČVUT)
od: datum do: datum celková_č ástka: peníze měsíční_splátka: peníze
+má_půjčenu 0..*
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 20/78
OCL lze použít pro navigaci class Příklad modelu pro hypotéky skládá se 1 z
0..*
Nemov itost Chceme označit měsíční splátky +je_majetkem +vlastní označení: string hypoték --osoby Q: hodnota: penize 0..* 1 +
+je_zajištěna 1..* Q.má_půjčenu.měsíční_splátka
Osoba jméno: string příjmení: string příjem: peníze žádost(peníze, Nemovitost) : boolean +pro
1
Nemovitost se zde chápe jako jednotka vlatnictví. Pokud nějakou nemovitost vlatsní více osob, rozdělí se na samostatné č ásti dle podílu vlastníků.
(je to množina údajů – výsledek je typu Bag(peníze) )
Hypotéka +zajišťuje 1..* -
[email protected] (ČVUT)
od: datum do: datum celková_č ástka: peníze měsíční_splátka: peníze
+má_půjčenu 0..*
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 21/78
Integritní omezení v OCL class Příklad modelu pro hypotéky skládá se 1 z
0..* Osoba
Nemov itost -
+vlastní
označení: string hodnota: penize
+je_majetkem 1 -
0..*
+ +je_zajištěna
jméno: string příjmení: string příjem: peníze žádost(peníze, Nemovitost) : boolean
1..* +pro
1
Nemovitost se zde chápe jako jednotka vlatnictví. Pokud nějakou nemovitost vlatsní více osob, rozdělí se na samostatné č ásti dle podílu vlastníků.
Hypotéka +zajišťuje 1..* -
od: datum do: datum celková_č ástka: peníze měsíční_splátka: peníze
„Hypotéka musí být zajištěna nemovitostí, jejíž cena není menší než celková zapůjčená částka (pokud je zajištěna +má_půjčenu jednou nemovitostí).“ 0..*
context Hypotéka inv : self.celková_částka <= self.je_zajištěna.hodnota [email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 22/78
Typy v OCL předefinované primitivní typy (s obvyklými operacemi): Integer Boolean String Real UnlimitedInteger konstruktory: Collection, Set, Bag, Sequence s operátory: collect, select, reject, forAll, exists, iterate, include, count, union, intersect, isEmpty, notEmpty, isUnique, ...
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 23/78
Primitivní typy Typ
Operace
Boolean
and, or, xor, not, implies, if-then-else
Integer
*, +, -, /, abs(), div(Integer), mod(Integer), min(Integer), max(Integer)
Real
*, +, -, /, abs(), floor(), round(), max(Real), min(Real)
String
size(), concat(String), toUpper(), toLower(), substring(Integer, Integer)
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 24/78
Operace s primitivními typy size() : Integer (počet znaků v řetězci self) substring(lower : Integer, upper : Integer) : String (podřetězec self začínající na pozici lower a končící na pozici upper. Pozice se počítají od 1 do self.size(). • pre: 1 <= lower • pre: lower <= upper • pre: upper <= self.size() concat(s : String) : String (spojení řetězců self a s) • post: result.size() = self.size() + s.size() • post: result.substring(1, self.size() ) = self • post: result.substring(self.size() + 1, result.size() ) = s [email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 25/78
Výčtové typy context Person inv: gender = Gender::male
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 26/78
Příklad použití OCL III. class Auta
Person -
name: String birthdate: Date /age: int
+ + +
getName() : String {query} birthDay() : Date setAge(int) : int
1
Date -
«enumeration» Colour
Vehicle +ow ner ow nership
+fleet 0..*
-
colour: Colour
Car
black white red
Bike
day: int month: int year: int
• Všechna vozidla osob jsou černá: context Person inv: self.fleet -> forAll(v | v.colour = Colour::black)
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 27/78
Výrazy v OCL (pokr.) x.vlastní -> isEmpty() test, zda hodnota typu „kolekce nemovitostí“ je prázdná
x.vlastní.hodnota kolekce hodnot typu „peníze“ představující cenu nemovitostí, které objekt x vlastní
x.vlastní.hodnota -> sum() cena nemovitostí, které objekt x vlastní, spočítaná jako součet hodnot jednotlivých nemovitostí class Pøíklad modelu pro hypotéky skládá se 1 z
0..* Osoba
Nemovitost -
oznaèení: string hodnota: penize
+vlastní 0..*
+je_majetkem 1 +
+je_zajištìna
jméno: string pøíjmení: string pøíjem: peníze žádost(peníze, Nemovitost) : boolean
1..* +pro
[email protected] (ČVUT)
Nemovitost se zde chápe jako jednotka vlatnictví. Pokud nějakou
OCL a integritní omezení
1
BI-SI1, 2011, Přednáška 9, 28/78
Vytváření kolekcí Set {2 , 4, 1 , 5 , 7 , 13, 11, 17 } OrderedSet {1 , 2, 3 , 5 , 7 , 11, 13, 17 } Sequence {1 , 2, 3 , 5 , 7 , 11, 13, 17 } Bag {1, 2, 3, 2, 1}
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 29/78
Pro všechny objekty jsou definovány metody: Typ
Operace oclIsTypeOf(t : OclType) : Boolean oclIsKindOf(t : OclType) : Boolean oclInState(s : OclState) : Boolean oclIsNew() : Boolean oclAsType(t : OclType) : instance of OclType
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 30/78
Kolekce Typ
Operace
Collection
->size(), ->includes(Object), ->includesAll(Collection), ->excludes(Object), ->excludesAll(Collection), ->count(Object), ->isEmpty(), ->notEmpty(), ->sum(), ->exists(Expression), ->forAll(Expression), ->isUnique(Expression), ->sortedBy(Expression), ->iterate(Expression), ->any(Expression), ->one(Expression)
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 31/78
Příklad použití OCL IV. class Auta
Person -
name: String birthdate: Date /age: int
1
+ + +
«enumeration» Colour
Vehicle +ow ner ow nership
+fleet 0..*
-
colour: Colour
black white red
getName() : String {query} birthDay() : Date setAge(int) : int
Date -
Car
Bike
day: int month: int year: int
• Nikdo nemůže vlastnit více než 3 vozidla context Person inv: self.fleet -> size <= 3
• nebo změníme násobnost v diagramu – to je ale statické, nemůže se to dynamicky měnit. [email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 32/78
Kolekce typu Set Typ
Operace
Collection::Set
->union(Set), ->union(Bag), ->intersection(Set), ->intersection(Bag), ->including(Object), ->excluding(Object), ->symmetricDifference(Set), ->select(Expression), ->reject(Expression), ->collect(Expression), ->count(Object), ->asSequence(), ->asBag()
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 33/78
Kolekce typu Bag Typ
Operace
Collection::Bag
->union(Bag), ->union(Set), ->intersection(Bag), ->intersection(Set), ->including(Object), ->excluding(Object), ->symmetricDifference(Set), ->select(Expression), ->reject(Expression), ->collect(Expression), ->count(Object), ->asSequence(), ->asSet()
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 34/78
Kolekce typu Sequence Typ
Operace
Collection::Sequence
->union(Bag), ->union(Set), ->intersection(Bag), ->intersection(Set), ->including(Object), ->excluding(Object), ->symmetricDifference(Set), ->select(Expression), ->reject(Expression), ->collect(Expression), ->count(Object), ->asSequence(), ->asSet()
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 35/78
Přesnější vyjádření IO class Příklad modelu pro hypotéky skládá se 1 z
0..* Osoba
Nemov itost -
+vlastní
označení: string hodnota: penize
+je_zajištěna
+je_majetkem 1 -
0..*
jméno: string příjmení: string příjem: peníze
+ žádost(peníze, Nemovitost) : boolean „Hypotéka musí být zajištěna +pro 1 Nemovitost se zde chápe jako nemovitostmi, jejichž součet jednotka vlatnictví. Pokud nějakou nemovitost vlatsní více osob, rozdělí cen není menší než celková se na samostatné č ásti dle podílu vlastníků. zapůjčená částka.“
1..*
Hypotéka +zajišťuje 1..* -
od: datum do: datum celková_č ástka: peníze měsíční_splátka: peníze
+má_půjčenu 0..*
context Hypotéka inv : Y36SIN -self. Jazyk celková_částka OCL <= self. je_zajištěna.hodnota 36 -> sum() [email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 36/78
A obráceně class Příklad modelu pro hypotéky skládá se 1 z
0..* Osoba
Nemov itost -
+vlastní
označení: string hodnota: penize
+je_majetkem 1 -
0..*
+ +je_zajištěna
jméno: string příjmení: string příjem: peníze žádost(peníze, Nemovitost) : boolean
1..* +pro Nemovitost se zde chápe jako jednotka vlatnictví. Pokud nějakou nemovitost vlatsní více osob, rozdělí se na samostatné č ásti dle podílu vlastníků.
1
„Nemovitost může zajišťovat pouze tolik hypoték, jejichž součet celkových částek není větší, než cena nemovitosti.“
Hypotéka +zajišťuje 1..* -
od: datum do: datum celková_č ástka: peníze měsíční_splátka: peníze
+má_půjčenu 0..*
context Nemovitost inv : self.zajišťuje.celková_částka -> sum() <= self.hodnota Richta: NSWI041 - Jazyk OCL 37 [email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 37/78
obj ect Hypotéky bez hranic
H-123 :Hypotéka
Důležitá podmínka
Karlštejn :Nemovitost
zajištěna
?
pro
Josef :Osoba
Bouda :Nemovitost
vlastní
class Příklad modelu pro hypotéky skládá se 1 z
0..* Osoba
Nemov itost -
+vlastní
označení: string hodnota: penize
+je_majetkem 1 -
0..*
+ +je_zajištěna
jméno: string příjmení: string příjem: peníze žádost(peníze, Nemovitost) : boolean
1..* +pro Nemovitost se zde chápe jako jednotka vlatnictví. Pokud nějakou nemovitost vlatsní více osob, rozdělí se na samostatné č ásti dle podílu vlastníků.
Hypotéka
1
„Hypotéky osoby mohou být zajištěny pouze nemovitostmi, které tato osoba vlastní.“
+zajišťuje 1..* -
od: datum do: datum celková_č ástka: peníze měsíční_splátka: peníze
+má_půjčenu 0..*
context Hypotéka inv : self.je_zajištěna.je_majetkem = self.pro Richta: NSWI041 - Jazyk OCL [email protected] (ČVUT)
OCL a integritní omezení
38 BI-SI1, 2011, Přednáška 9, 38/78
Vlastnosti operací v OCL class Příklad modelu pro hypotéky skládá se 1 z
0..* Osoba
Nemov itost -
+vlastní
označení: string hodnota: penize
+je_majetkem 1 -
„Osoby mohou žádat0..*o hypotéky, pokud suma +je_zajištěna 1..* měsíčních splátek osoby Nemovitost se zde chápe jako jednotka vlatnictví. Pokud nějakou nepřesáhne 30% příjmu nemovitost vlatsní více osob, rozdělí se na samostatné č ásti dle podílu osoby.“ vlastníků.
+
jméno: string příjmení: string příjem: peníze žádost(peníze, Nemovitost) : boolean +pro
1
Hypotéka +zajišťuje 1..* -
od: datum do: datum celková_č ástka: peníze měsíční_splátka: peníze
+má_půjčenu 0..*
context Osoba::žádost(částka:peníze,zajištění:Nemovitost) pre : (self.má_půjčenu.měsíční_splátka -> sum()) + částka/počet_splátek <= self.příjem * 0.3 39 [email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 39/78
Typická vlastnost hierarchie class Příklad modelu pro hypotéky skládá se 1 z
0..* Osoba
Nemov itost -
+vlastní
označení: string hodnota: penize
+je_majetkem 1 -
0..*
+ +je_zajištěna
jméno: string příjmení: string příjem: peníze žádost(peníze, Nemovitost) : boolean
1..* +pro Nemovitost se zde chápe jako jednotka vlatnictví. Pokud nějakou nemovitost vlatsní více osob, rozdělí se na samostatné č ásti dle podílu vlastníků.
1
„Nemovitost se nemůže skládat sama ze sebe.“
Hypotéka +zajišťuje 1..* -
od: datum do: datum celková_č ástka: peníze měsíční_splátka: peníze
+má_půjčenu 0..*
context Nemovitost inv : not (self.skládá_se_z isElement(self)) [email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 40/78
Příklad použití OCL V. class Auta
Person -
name: String birthdate: Date /age: int
1
+ + +
«enumeration» Colour
Vehicle +ow ner ow nership
+fleet 0..*
-
colour: Colour
black white red
getName() : String {query} birthDay() : Date setAge(int) : int
Date -
Car
Bike
day: int month: int year: int
• Nikdo nevlastní víc než 3 černá vozidla: context Person inv: self.fleet -> select(v | v.colour = Colour::black) -> size <= 3
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 41/78
Příklad použití OCL VI. class Auta
Person -
name: String birthdate: Date /age: int
+ + +
getName() : String {query} birthDay() : Date setAge(int) : int
+ow ner ow nership 1
Date -
«enumeration» Colour
Vehicle +fleet 0..*
-
colour: Colour
Car
black white red
Bike
day: int month: int year: int
• Co znamená podmínka? context Person inv: self.fleet -> iterate(v ; acc:Integer=0 | if (v.colour = Colour::black) then acc+1 else acc endif) <= 3 [email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 42/78
Příklad použití OCL VII. class Auta
Person -
name: String birthdate: Date /age: int
+ + +
getName() : String {query} birthDay() : Date setAge(int) : int
+ow ner ow nership 1
Date -
«enumeration» Colour
Vehicle +fleet 0..*
-
colour: Colour
Car
black white red
Bike
day: int month: int year: int
• Co znamená podmínka? context Person inv: self.fleet -> age < 18 implies forAll(v | not v.oclIsKindOf(Car))
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 43/78
Příklad použití OCL VIII. class Auta
Person -
name: String birthdate: Date /age: int
+ + +
getName() : String {query} birthDay() : Date setAge(int) : int
+ow ner ow nership 1
Date -
«enumeration» Colour
Vehicle +fleet 0..*
-
colour: Colour
Car
black white red
Bike
day: int month: int year: int
• Existuje červené auto: context Car inv: Car.allInstances -> exists(c | c.colour = Colour::red)
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 44/78
Příklad použití OCL IX. class Auta
Person -
name: String birthdate: Date /age: int
+ow ner ow nership 1
+ + +
«enumeration» Colour
Vehicle +fleet 0..*
-
colour: Colour
black white red
getName() : String {query} birthDay() : Date setAge(int) : int
Date -
Car
Bike
day: int month: int year: int
• Metoda setAge třídy Person pro nezáporný argument newAge nastaví atribut age: context Person::setAge(newAge:Integer):Integer pre: newAge >= 0 post: self.age = newAge [email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 45/78
Příklad použití OCL X. class Auta
Person -
name: String birthdate: Date /age: int
+ + +
getName() : String {query} birthDay() : Date setAge(int) : int
+ow ner ow nership 1
Date -
«enumeration» Colour
Vehicle +fleet 0..*
-
colour: Colour
Car
black white red
Bike
day: int month: int year: int
• Vyvolání metody birthday třídy Person zvýší věk osoby o 1: context Person::birthday() post: self.age = self.age@pre + 1
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 46/78
Příklad použití OCL XI. class Auta
Person -
name: String birthdate: Date /age: int
+ow ner ow nership 1
+ + +
«enumeration» Colour
Vehicle +fleet 0..*
-
colour: Colour
black white red
getName() : String {query} birthDay() : Date setAge(int) : int
Date -
Car
Bike
day: int month: int year: int
• Výsledek volání metody getName třídy Person je hodnota atributu name: context Person::getName():String post: result = self.name
• nebo, protože getName je {query}: context Person inv: self.getName = self.name [email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 47/78
Úrovně modelů
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 48/78
Příklad využití OCL (metamodel UML)
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 49/78
Příklad podmínky v OCL (metamodel) class Model elementu
«metaclass» Element -
mustBeOwned: boolean
+owner 0..1
„Element, který musí mít vlastníka, musí mít vlastníka.“
+ownedElement 0..*
context Element inv: self.mustBeOwned() implies owner->notEmpty()
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 50/78
Příklad: definice odvozené vlastnosti „Elementy, které vlastní daný element (je to odvozené sjednocení).“
/ownedElement: Element[*]
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 51/78
Příklad: definice odvozené vlastnosti „Element, který vlastní tento element (owner) – je to odvozené sjednocení (union).“
/owner: Element [0..1] [email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 52/78
Příklad: popis operace v OCL Operace allOwnedElements() vrací všechny elementy, které přímo či nepřímo vlastní daný element
context Element::allOwnedElements(): Set(Element) post: result = ownedElement -> union( ownedElement->collect(e | e.allOwnedElements() ) [email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 53/78
Příklad: podmínky v OCL
Element nemůže přímo, nebo nepřímo vlastnit sám sebe context Element inv: not self.allOwnedElements() -> includes(self)
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 54/78
The End
[email protected] (ČVUT)
OCL a integritní omezení
BI-SI1, 2011, Přednáška 9, 55/78