1 / 24

Standardy w zakresie systemów rozproszonych i baz danych

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

rasia
Download Presentation

Standardy w zakresie systemów rozproszonych i baz danych

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 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

  2. Specyfikacja OCL (1) • Deklarowanie zmiennych OclExpressionCS ::=  'let' VariableDeclarationListCS 'in' OclExpressionCS • Przykład: letzmienna: TypZmiennej = wyrażenie1 inwyrażenie2 • Operator if OclExpressionCS ::=  'if' OclExpressionCS 'then' OclExpressionCS 'else' OclExpressionCS 'endif' • W OCL dla wyrażenia 'if' część 'else' jest obowiązkowa • Przykład: ifwiek < 35 then‘młody' else‘stary' • Porównania OclExpressionCS ::= OclExpressionCS Porównanie OclExpressionCS Porównanie ::= '='  | '<>' | '<'  | '>'  | '<=' |'>=‘ • Operatory arytmetyczne OclExpressionCS ::= OclExpressionCS OperatorArytmet OclExpressionCS OperatorArytmet ::= ‘+' | ‘-'  | ‘*' | ‘/'

  3. Specyfikacja OCL (2) • Wołanie operacji infiksowych OclExpressionCS ::= OclExpressionCS simpleNameCS OclExpressionCS • simpleNameCS pochodzi z biblioteki OCL • Przykład: booleanExpression1 implies booleanExpression2 • Wołanie operacji prefiksowych OclExpressionCS ::= '-' OclExpressionCS| simpleNameCS OclExpressionCS • Przykład: not booleanExpression • Iteratory na pojedynczych zmiennych OclExpressionCS ::= 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 <> e2implies e1.empno <> e2.empno)

  4. Specyfikacja OCL (3) • Wołanie operacji na kolekcjach OclExpressionCS ::= 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 operacji OclExpressionCS ::= OclExpressionCS '.' simpleNameCS '(' argumentsCS ')' • Przykład: employees -> select (age < 35).raise(100) • Wiązanie atrybutu lub zmiennej OclExpressionCS ::= OclExpressionCS '.' simpleNameCS | simpleNameCS • Wołanie operacji OclExpressionCS ::= simpleNameCS '(' ')' | simpleNameCS '(' argumentsCS ')'

  5. 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| PrimitiveLiteralExpCS CollectionLiteralExpCS ::= 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 }

  6. Prymitywne literały i krotki • Prymitywne literały PrimitiveLiteralExpCS ::= 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}

  7. Deklaracje zmiennych, typy i argumenty VariableDeclarationCS ::= 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 ?

  8. Operacje na typie Boolean

  9. Operacje na typach Integer i Real

  10. 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.

  11. Standardowe operatory na kolekcjach

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

  13. Dalsze operatory na kolekcjach (1)

  14. Dalsze operatory na kolekcjach(2)

  15. 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ą.

  16. Operatory pętli i zmienne iteracyjne (1) 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))

  17. Operatory pętli i zmienne iteracyjne (2)

  18. Przykłady wykorzystania OCL w VIDE Emp name : String address : String salary: Integer boss[0..1] Dept name : String location: String[1..*] • Utwórz nowego pracownika newEmp := 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) foreachsalary += 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)) worksIn employs[0..*]

  19. 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.

  20. 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) asL join ((Dept whereLin location).name)groupasDnames • 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) asloc join ((Dept wherelocin location)groupas d) . (loc as L, (d.name)groupasDnames, (d.boss.Emp.salary) as bossAvg))

  21. 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.’))

  22. …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) elsec + ‘ employees earn between ‘+ i +’ and ‘ + (i+999))

  23. 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 badawczego Dept->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ć.

  24. 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 • …

More Related