Standardy w zakresie systemów rozproszonych i baz danych

24
P.Habela, K.Subieta. SSR, Wykład 11, Folia 1 maj 2009 Standardy w zakresie systemów rozproszonych i baz danych Piotr Habela Kazimierz Subieta Polsko-Japońska Wyższa Szkoła Technik Komputerowych, Warszawa Wykład 11: c.d. Wprowadzenie do OCL

description

Standardy w zakresie systemów rozproszonych i baz danych. Wykład 11: c.d. Wprowadzenie do OCL. Piotr Habela Kazimierz Subieta Polsko-Japońska Wyższa Szkoła Technik Komputerowych, Warszawa. Specyfikacja OCL (1). Deklarowanie zmiennych - PowerPoint PPT Presentation

Transcript of Standardy w zakresie systemów rozproszonych i baz danych

Page 1: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 1 maj 2009

Standardy w zakresie systemów rozproszonych i baz danych

Piotr HabelaKazimierz Subieta

Polsko-Japońska Wyższa SzkołaTechnik Komputerowych, Warszawa

Wykład 11:c.d. Wprowadzenie do OCL

Page 2: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 2 maj 2009

Specyfikacja OCL (1)

• Deklarowanie zmiennychOclExpressionCS ::=  'let' VariableDeclarationListCS 'in' OclExpressionCS– Przykład: let zmienna: TypZmiennej = wyrażenie1 in wyrażenie2

• Operator ifOclExpressionCS ::=  'if' OclExpressionCS 'then' OclExpressionCS

'else' OclExpressionCS 'endif' – W OCL dla wyrażenia 'if' część 'else' jest obowiązkowa– Przykład: if wiek < 35 then ‘młody' else ‘stary'

• PorównaniaOclExpressionCS ::= OclExpressionCS Porównanie OclExpressionCSPorównanie ::= '='  | '<>' | '<'  | '>'  | '<=' |'>=‘

• Operatory arytmetyczneOclExpressionCS ::= OclExpressionCS OperatorArytmet OclExpressionCSOperatorArytmet ::= ‘+' | ‘-'  | ‘*' | ‘/'

Page 3: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 3 maj 2009

• Wołanie operacji infiksowych OclExpressionCS ::= OclExpressionCS simpleNameCS OclExpressionCS– simpleNameCS pochodzi z biblioteki OCL– Przykład: booleanExpression1 implies booleanExpression2

• Wołanie operacji prefiksowychOclExpressionCS ::= '-' OclExpressionCS | simpleNameCS OclExpressionCS – Przykład: not booleanExpression

• Iteratory na pojedynczych zmiennychOclExpressionCS ::= OclExpressionCS '->' simpleNameCS '('

VariableDeclarationCS '|' OclExpressionCS ')' – Przykłady: employees -> select (e | e.age < 50)

employees -> select (p: Person | p.age < 50)• Iteratory na dwóch zmiennych

OclExpressionCS ::= OclExpressionCS '->' simpleNameCS '(' VariableDeclarationCS ',' VariableDeclarationCS '|' OclExpressionCS ')'

– Pierwsze OclExpressionCS musi być pojedynczą nazwą– Przykład: employees -> forAll (e1, e2 | e1 <> e2 implies e1.empno <> e2.empno)

Specyfikacja OCL (2)

Page 4: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 4 maj 2009

Specyfikacja OCL (3)

• Wołanie operacji na kolekcjachOclExpressionCS ::= OclExpressionCS '->' simpleNameCS '(' ')' – Przykład: employees -> count()OclExpressionCS ::= OclExpressionCS '->' simpleNameCS '('

OclExpressionCS argumentsCS_trail ')' – Przykład: employees -> sortedBy(surname)– argumentsCS_trail – być może pusta lista dalszych argumentów

• Zwyczajne wołanie operacjiOclExpressionCS ::= OclExpressionCS '.' simpleNameCS '(' argumentsCS ')' – Przykład: employees -> select (age < 35).raise(100)

• Wiązanie atrybutu lub zmiennejOclExpressionCS ::= OclExpressionCS '.' simpleNameCS | simpleNameCS

• Wołanie operacji OclExpressionCS ::= simpleNameCS '(' ')' | simpleNameCS '(' argumentsCS ')'

Page 5: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 5 maj 2009

OCL – ścieżki dostępu, literały• Ścieżki:

pathNameCS ::= simpleNameCS '::' simpleNameCS | simpleNameCS '::' pathNameCS– Ta reguła reprezentuje ścieżkę nazw, która jest używana do dostępu do

nazw (np. typów) w innych pakietach. – Przykład: packageA::subpackageA1::typeX

• Literały:LiteralExpCS ::=

CollectionLiteralExpCS| TupleLiteralExpCS| PrimitiveLiteralExpCSCollectionLiteralExpCS ::= CollectionTypeIdentifierCS '{‘ CollectionLiteralPartsCS '}' – Przykłady:

OrderedSet {'first', 'second', 'third'} Bag {10, 20, 10, 50, 50}

– Identyfikatory kolekcji: 'Set', 'Bag', 'Sequence', 'OrderedSet' • Literały kolekcji określane przez zakres:

CollectionRangeCS ::= OclExpressionCS '..' OclExpressionCS – Przykład: Sequence { 1..12, 14..100 }

Page 6: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 6 maj 2009

Prymitywne literały i krotki

• Prymitywne literałyPrimitiveLiteralExpCS ::= IntegerLiteralExpCS | RealLiteralExpCS

| StringLiteralExpCS | BooleanLiteralExpCS

– Włączają literały: Real, Boolean, Integer, String

• Krotki (struktury)TupleLiteralExpCS ::= 'Tuple' '{' VariableDeclarationListCS '}‘

– Reguła reprezentuje literały reprezentujące krotki

– Przykład:

Tuple {name: String = 'John', surname: String = 'Brown', age: Integer = 47}

Page 7: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 7 maj 2009

Deklaracje zmiennych, typy i argumentyVariableDeclarationCS ::= VariableDeclarationCS_strict | simpleNameCS – Typ i wyrażenie inicjujące są opcjonalne. – Przykłady: p: Person i: Integer = 7

VariableDeclarationCS_strict ::= simpleNameCS ':' typeCS | simpleNameCS ':' typeCS '=' OclExpressionCS

| simpleNameCS '=' OclExpressionCS

typeCS ::= simpleNameCS | pathNameCS | collectionTypeCS | tupleTypeCS

collectionTypeCS ::= CollectionTypeIdentifierCS '(' typeCS ')' – Przykłady: Bag(Integer) Sequence(String) OrderedSet(String)

tupleTypeCS ::= 'TupleType' '(' VariableDeclarationListCS ')' – Przykład: TupleType(name: String, surname: String, age: Integer)

argumentsCS ::= OclExpressionCS argumentsCS_trail ? argumentsCS_trail ::= ',' OclExpressionCS

argumentsCS_trail ?

Page 8: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 8 maj 2009

Operacje na typie Boolean

Operator Przykład Typ rezultatu Opis

or a or b Boolean Alternatywa

and a and b Boolean Koniunkcja

xor a xor b BooleanAlternatywa wyłączna

not not a Boolean Negacja

= a = b Boolean Równość

<> a <> b Boolean Nierówność

implies a implies b Boolean Implikacja

Page 9: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 9 maj 2009

Operacje na typach Integer i Real

Operator Przykład Typ rezultatu Opis

= <> a = b Boolean Równość , nierówność

< <= a < b Boolean Mniejszy, mniejszy lub równy

> >= a > b Boolean Większy, większy lub równy

+ - a + b Integer lub Real Dodawanie, odejmowanie

* / a * b Integer lub Real Mnożenie, dzielenie

mod a.mod(b) Integer Modullo (reszta od dzielenia)

div a.div(b) Integer Dzielenie liczb całkowitych

abs a.abs() Integer lub Real Wartość absolutna

max a.max(b) Integer lub Real Wartość maksymalna z a i b

min a.min(b) Integer lub Real Wartość minimalna z a i b

round a.round() Integer Wartość zaokrąglona

floor a.floor() Integer Wartość zaokrąglona w dół

Page 10: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 10 maj 2009

Operacje na typie String

• Postfiksowa konwencja a la Smalltalk nie jest fortunnym pomysłem twórców OCL

• Klasyczna konwencja, np. toUpper(a), wydaje się dużo lepsza.

Operator Przykład Typ rezultatu Opis

= <> a = b Boolean Równość , nierówność

concat

+

a.concat(b)

a + b

String Konkatenacja

Konkatenacja dodana w VIDE

toLower a.toLower() String Zmiana na małe litery

toUpper a.toUpper() String Zmiana na duże litery

substring a.substring(i, j) String Wybranie podstringu od i-tego do j-tego znaku

Page 11: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 11 maj 2009

Standardowe operatory na kolekcjach

Operator PrzykładTyprezultatu

Opis

count x->count(y) Integer Liczba wystąpień obiektu y w kolekcji x

excludes x->excludes(y) Boolean True jeżeli y nie jest elementem x

excludesAll x->excludesAll(y) BooleanTrue jeżeli nie ma elementu kolekcji y, który

jest jednocześnie elementem x

includes x->includes(y) Boolean True jeżeli y jest elementem x

includesAll x->includesAll(y) Boolean True jeżeli wszystkie elementy kolekcji y są w x

isEmpty x->isEmpty() Boolean True jeżeli kolekcja x jest pusta

notEmpty x->notEmpty() Boolean True jeżeli kolekcja x jest niepusta

Page 12: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 12 maj 2009

Funkcje agregowane

Operator PrzykładTyprezultatu

Opis

size x->size() Integer Liczba elementów w kolekcji x

sum x->sum() Integer lub Real Suma arytmetyczna elementów kolekcji x

avg x->avg() Real Średnia arytmetyczna elementów kolekcji x

min x->min() Integer, Real lub

StringNajmniejsza wartość w kolekcji x

max x->max() Integer, Real lub

StringNajwiększa wartość w kolekcji x

Operatory sum, avg, min i max zostały wprowadzone w VIDE, są rozszerzeniem standardu.

Page 13: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 13 maj 2009

Dalsze operatory na kolekcjach (1)

Operator PrzykładTyprezultatu

Opis

= x = y Boolean Identyczność kolekcji x i y

<> x <> y Boolean Przecięcie kolekcji x i y jest puste

- x - y setRóżnica zbiorów: wynik zawiera te

elementy x, których nie ma w y

append x->append(o) OrderedSet lub

SequenceDodaj element o na koniec

sekwencji x

asBag x->asBag() Bag Konwersja do Bag

asOrderedSet x->asOrderedSet() OrderedSet Konwersja do OrderedSet

asSequence x->asSequence() Sequence Konwersja do Sequence

asSet x->asSet() Set Konwersja do Set

Page 14: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 14 maj 2009

Dalsze operatory na kolekcjach(2)

Operator PrzykładTyp

rezultatuOpis

at x->at(i) objectZwraca element kolekcji x znajdujący się na pozycji i

excluding x->excluding(o) collectionZwraca kolekcję x pomniejszoną o element o

first x->first() object Pierwszy element kolekcji x

flatten x->flatten() collectionSpłaszcza zagnieżdżoną kolekcję x o jeden poziom

including x->including(o) collection Zwraca kolekcję x zwiększoną o element o

indexOf x->indexOf(o) IntegerZwraca numer pozycji elementu o w kolekcji x

insertAt x->insertAt(i, o) OrderedSet lub Sequence

Zwraca OrderedSet lub Sequence, w których wstawiony został element o na pozycję i

intersection x->intersection(y) Set lub Bag Przecięcie kolekcji x i y

last x->last() object Ostatni element w kolekcji x

Page 15: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 15 maj 2009

Dalsze operatory na kolekcjach (3)

• Wątpliwości budzi redundancja operatorów, np. symmetricDifference łatwo wyrazić przez sumę i różnicę kolekcji: x sD y = (x – y) (y – x) = (x y) – (x ∩ y) • Niekiedy ma znaczenie, czy operacja jest dokonywana na zapamiętanej kolekcji, czy też na kolekcji obliczonej poprzez zapytanie. Np. wstawienie nowego elementu do zapamiętanego zbioru (including) jest nieco inną operacją.

Operator PrzykładTyp

rezultatuOpis

prepend x->prepend(o) OrderedSet lub Sequence

Dodaje element o jako pierwszy przed kolekcją x

subOrderedSet x->subOrderedSet(i, j) OrderedSetWybiera elementy sekwencji od i-tego do j-tego; rezultat typu OrderedSet

subSequence x->subSequence(i, j) SequenceWybiera elementy sekwencji od i-tego do j-tego; rezultat typu Sequence

symmetricDifference x -> symmetricDifference(y) SetZawiera elementy x, których nie ma w y, i vice versa

union x->union(y) collectionSuma dwóch kolekcji lub konkatenacja sekwencji

Page 16: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 16 maj 2009

Operatory pętli i zmienne iteracyjne (1)

Operator PrzykładTyp

rezultatuOpis

any x->any(e) objectWybiera dowolny element z kolekcji x dla którego wyrażenie e jest prawdziwe

collect x->collect(e) collectionProjekcja: zwraca wartości wyrażenia e dla każdego elementu kolekcji x

collectNested

x-> collectNested(e)

collectionTak samo jak dla collect, ale dotyczy to kolekcji kolekcji

iterate x->iterate(i: Type1;a: Type2=e1 | e2)

Type2

Zmiennej a jest początkowo przypisana wartość wyliczona przez e1. Zmienna iteracyjna i iteruje po kolekcji x i w każdym obrocie jest wyliczane e2 dla tego i oraz a. Wartość ta jest podstawiana pod a.

Funkcja agregowana sum: x->iterate(i: Integer; a: Integer=0 | a+i)Funkcja agregowana max: x->iterate(i: Integer; a: Integer= -9999| i.max(a))

Page 17: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 17 maj 2009

Operatory pętli i zmienne iteracyjne (2)

Operator PrzykładTyp

rezultatuOpis

exists x->exists(e) BooleanKwantyfikator egzystencjalny: zwraca true jeżeli e jest true dla przynajmniej jednego elementu x

forAll x->forAll(e) BooleanKwantyfikator uniwersalny: zwraca false jeżeli e jest false dla przynajmniej jednego elementu x

isUnique x->isUnique(e) BooleanZwraca true jeżeli wyrażenie e zwraca różną wartość dla każdego elementu x

one x->one(e) BooleanZwraca true jeżeli e jest true dla dokładnie jednego elementu x

reject x->reject(e) collection Zwraca te elementy x, dla których e jest false

select x->select(e) collection Zwraca te elementy x, dla których e jest true

sortedBy x->sortedBy(e) OrderedSet lub Sequence

Zwraca elementy kolekcji x posortowane zgodnie z wyrażeniem e

Page 18: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 18 maj 2009

Przykłady wykorzystania OCL w VIDE

• Utwórz nowego pracownikanewEmp := Emp create {name = ‘John’; address = ‘44th Street’; salary =

3000}• Podaj nazwiska pracowników, których szefem jest Bert:

Emp->select(worksIn.boss.name=’Bert’).name • Dla każdego pracownika, którego szefem jest Smith i

zarabiającego mniej niż 2000 podwyższ zarobek o 100:(Dept ->select (boss.name = ‘Smith’).employs -> select (salary < 2000) foreach salary += 100;

• Czy to prawda, że w każdym dziale istnieje pracownik zarabiający więcej od swego szefa?(Dept -> forAll(d | d.employs -> exists(e | e.salary > d.boss.salary))

Empname : Stringaddress : Stringsalary: Integer

Deptname : Stringlocation: String[1..*]

boss[0..1]

employs[0..*] worksIn

Page 19: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 19 maj 2009

Dalsze przykłady (1)

Dept->allInstances()->select(name=’toys’).employs->size()Dept->allInstances()->select(name=’toys’).employs.salary->sum()Dept->allInstances()->select(name=’toys’).employs.salary->avg()Dept->allInstances()->select(name=’toys’).employs.salary->min()Dept->allInstances()->select(name=’toys’).employs.salary->max()

• Niech Person będzie nadklasą dla Emp, zaś getIncome metodą zdefiniowaną dla Emp. Wówczas można wykorzystać dziedziczenie i polimorfizm:Person->allInstances()->collect(getIncome())->sum()

• Można także uzyskać efekt operatora zależnego złączenia (podaj identyfikator działu pod dept i sumaryczny zarobek pod totalSal):Dept->allInstances()->collect(d |

Tuple{ dept = d, totalSal = d.employs.getSalary()->avg() } ) – Tuple jest konstruktorem struktury

• allInstances: jeżeli przed -> jest nazwa klasy, to operator ten odzyskuje wszystkie obiekty tej klasy.

Page 20: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 20 maj 2009

Dalsze przykłady i porównanie z SBQL

• Dla każdej lokacji działu podaj zbiór nazw działów, które są tam ulokowane:Dept->allInstances()->collect(location)->asSet() ->collect(loc | Tuple{ L = loc, Dnames = (Dept->allInstances->select(location=loc)->collect(name))})

• To samo zapytanie w SBQL (44 -> 22 jednostki leksykalne):unique(Dept.location) as L join ((Dept where L in location).name) groupas Dnames

• Dla każdej lokacji działu podaj zbiór nazw działów, które są tam ulokowane oraz średni zarobek szefów tych działów:Dept->allInstances()->collect(location)->asSet() ->collect(loc | Tuple{ L = loc, Dnames = Dept->allInstances->select(location=loc)->collect(name), bossAvg = Dept->allInstances->select(location=loc) ->collect(d | d.boss.salary)->avg()})

• To samo zapytanie w SBQL:unique(Dept.location) as loc join ((Dept where loc in location) groupas d) . (loc as L, (d.name) groupas Dnames, (d.boss.Emp.salary) as bossAvg))

Page 21: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 21 maj 2009

Jeszcze przykłady• Podaj miasta goszczące wszystkie działy:

Dept->allInstances()-> select(d |

(Dept->allInstances()->collect(location)->asSet())

->forAll(loc | d.location -> exists(dloc | loc = dloc)))

• Załóżmy, że klasa Dept ma metodę budget pozwalającą na obliczenie rocznego budżetu działu. Dla każdego pracownika działu zlokalizowanych w Radomiu przygotuj komunikaty stringowe zawierające nazwisko oraz procent rocznego budżetu konsumowany przez tego pracownika. Emp->allInstances()->select(e | e.worksIn.location -> includes(‘Radom’))->

collect(‘Employee ‘ + name + ‘ consumes ‘ + (salary * 12 * 100 /(e.worksIn.Dept.budget())) + ‘ % of the " + worksIn.Dept.name +

‘ department budget.’)

• Zapis oryginalny w OCL:Emp->allInstances()->select(e | e.worksIn.location -> includes(‘Radom’))->

collect(‘Employee ‘.concat(name). concat(‘ consumes ‘).

concat(salary * 12 * 100 /(e.worksIn.Dept.budget()). concat(‘ % of the ‘).

concat(worksIn.Dept.name). concat(‘ department budget.’))

Page 22: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 22 maj 2009

…i jeszcze przykład

• Dla każdego przedziału <n, n+999>, n = 0, 1000, 2000, 3000, ... przygotuj komunikat zawierający liczbę pracowników mających zarobek z tego przedziału i sam przedział. Komunikaty wyjściowe powinny mieć poprawną formę gramatyczną (w języku angielskim): przyrostki –s dla liczby mnogiej rzeczowników i dla czasowników w liczbie pojedynczej.Bag {0, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 11000} ->

collect(i | Emp->allInstances()->select(salary >= i and salary < i+1000))->size()->

collect(c | if c = 1 then 1 + ‘ employee earns between ‘+ i +’ and ‘ + (i+999)

else c + ‘ employees earn between ‘+ i +’ and ‘ + (i+999))

Page 23: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 23 maj 2009

Przykłady użycia OCL w zdaniach imperatywnych• Daj minimalną płacę dla tych pracowników, którzy nie mają jeszcze

określonej płacy.Emp->allInstances()->select(salary->size() = 0) foreach { e | e.raiseSalary(e.worksIn.getSalary()->min()); }

• Przesuń wszystkich pracowników z działu zabawek do działu badawczegoDept->allInstances()->select(name = ‘Toys’)->collect(employs) foreach { e |e unlink worksIn; e link worksIn to Dept->allInstances() ->select(name = ‘Research’);}

• Inny wariant:Emp->allInstances()->select(worksIn.name = ‘Toys’) foreach { e | e unlink

worksIn; e link worksIn to Dept->allInstances()->select(name = ‘Research);}• Daj 10% podwyżki wszystkim studentom, którzy są jednocześnie

pracownikami działu znajdującego się w Warszawie:EmpStudent->allInstances()->select(worksIn.location->select(m| m = ‘Warsaw’) ) foreach { es | es.raiseSalary(es.getSalary * 0.1)); }

• Niektóre zapytania trudno uznać za łatwe, ale ważne jest, że da się je zadać.

Page 24: Standardy w zakresie systemów rozproszonych  i baz danych

P.Habela, K.Subieta. SSR, Wykład 11, Folia 24 maj 2009

Plusy i minusy OCL

• Plusy:– Język obsługuje pełny model obiektowy UML– Jest ortogonalny (brak dużych zlepków takich jak select…from…where…group by…

having...order by…)– Jest dość popularny w środowisku UML– Łatwa intuicyjna semantyka

• Minusy– Fatalna składnia, przerosty składniowe, nieczytelne wyrażenia– Jak dotąd, nie ma programistów w OCL– Brak uniwersalności (np. żadnych możliwości rekurencyjnych)– Niedospecyfikowanie (np.. brak semantyki dla zakresów nazw)– Redundantny i trochę przypadkowy wybór funkcjonalności– Nieprzystosowanie do roli języka zapytań (brak optymalizacji)– Brak myślenia o zanurzeniu OCL w uniwersalny język programowania– Brak perspektyw baz danych i innych abstrakcji programistycznych– Brak efektów ubocznych– Niejasny stosunek do wartości zerowych (podważa przykrycie SQL, gdzie wartości

zerowe są ważną funkcjonalnością)– Niespójność i przecinanie się funkcjonalności OCL z funkcjonalnością UML 2.1– …