Standardy w zakresie systemów rozproszonych i baz danych
description
Transcript of 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
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 ::= ‘+' | ‘-' | ‘*' | ‘/'
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)
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 ')'
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 }
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}
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 ?
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
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ół
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
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
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.
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
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
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
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))
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
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
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.
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))
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.’))
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))
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ć.
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– …