Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Object Constraint Language (OCL) – wersja 2.0

Podobne prezentacje


Prezentacja na temat: "Object Constraint Language (OCL) – wersja 2.0"— Zapis prezentacji:

1 Object Constraint Language (OCL) – wersja 2.0
Standardowy język definicji ograniczeń dla modeli UML

2 Wprowadzenie OCL jest formalnym językiem specyfikacji wyrażeń występujących w modelach UML Wyrażenia OCL nie mogą mieć efektów ubocznych – nie mogą zmieniać stanu systemu OCL może natomiast specyfikować zmianę stanu OCL nie jest językiem programowania Nie da się w nim wyrazić zagadnień związanych z implementacją

3 Użycie wyrażeń OCL Specyfikacja zapytań
Specyfikacja niezmienników klas i typów danych w modelu klas Specyfikacja niezmienników typu dla stereotypów Specyfikacja warunków wstępnych (preconditions) i warunków końcowych (postconditions) dla operacji i metod Specyfikacja warunków dozoru (guards) Specyfikacja celu komunikatów i akcji Specyfikacja ograniczeń dla operacji Specyfikacja reguł wyprowadzenia atrybutów pochodnych

4 Przykładowy diagram klas

5 Związki OCL z metamodelem UML – określenie kontekstu
Każde wyrażenie OCL jest pisane w kontekście pewnej instancji konkretnego typu Wewnątrz wyrażenia instancja stanowiąca kontekst określana jest słowem zarezerwowanym self Kontekst wewnątrz wyrażenia można określić przy pomocy deklaracji kontekstu context Company Deklarację kontekstu zwykle się opuszcza jeśli dane ograniczenie jest pokazane na diagramie UML. W powyższej deklaracji self jest instancją klasy Company.

6 Związki z metamodelem UML – niezmienniki
Niezmiennik to rodzaj ograniczenia, który musi być spełniony przez wszystkie instancje danego klasyfikatora w każdej chwili. context Company inv: self.numberOfEmployees > 50 self zazwyczaj można opuścić: inv: numberOfEmployees > 50

7 Związki z metamodelem UML – niezmienniki (c.d.)
Można zdefiniować symbol zastępujący self: context c: Company inv: c.numberOfEmployees > 50 Ograniczenie może mieć nazwę: inv enoughEmployees: c.numberOfEmployees > 50

8 Związki z metamodelem UML – warunki wstępne i końcowe
Kontekstem jest operacja lub inna cecha czynnościowa self jest instancją typu, do którego należy dana cecha czynnościowa Słowo zarezerwowane result określa wynik operacji context Type::operation(par1: T1, ...): ReturnType pre: ... post: ...

9 Związki z metamodelem UML – warunki wstępne i końcowe (c.d.)
Przykład warunku końcowego: context Person::income(d: Date): Integer post: result = 5000 Warunki wstępne i końcowe mogą mieć nazwy: context ClassA::op(par: T): ReturnType pre parameterOk: par > 63 post resultOk: result = par + 23

10 Związki z metamodelem UML – określenie kontekstu pakietu
package A::B context C inv: ... context C::op1() pre: ... endpackage

11 Związki z metamodelem UML – ograniczenia na zwracaną wartość
Ograniczenia body condition dla operacji będących zapytaniami context ClassA::op(): T body: ... Przykład: context Person::getCurrentSpouse(): Person pre: self.isMarried = true body: self.marriages->select(ended = false).spouse

12 Związki z metamodelem UML – wartości początkowe i pochodne
Wyrażenia OCL mogą opisywać wartości początkowe lub pochodne (wyprowadzone) atrybutów i końców powiązań context Person::income: Integer init: parents.income->sum() * kieszonkowe derive: if underAge then parents.income->sum() * 0.01 else job.salary endif -- rozpoczyna komentarz

13 Typy podstawowe OCL Integer Real Boolean String
Operacje (przykładowe): +, -, *, /, abs() Real +, -, *, floor() Boolean and, or, xor, not, implies, if-then-else String concat(), size(), substring() Wszystkie są instancjami InfrastructureLibrary::Core::Constructs::PrimitiveType

14 Typy z modeli UML Wszystkie klasyfikatory zdefiniowane w danym modelu UML są typami dostępnymi w wyrażeniach OCL dołączonych do tego modelu

15 Typy wyliczeniowe context Person inv: wife.gender = Gender::female
Powyższy niezmiennik jest niekompletny (brakuje sprawdzenia czy wife->notEmpty() )

16 Definiowanie zmiennych o zasięgu pojedynczego wyrażenia
context Person inv: let income: Integer = job.salary->sum() in if isUnemployed then income < 100 else income >= 100 endif

17 Definiowanie dodatkowych atrybutów/operacji
Przy pomocy ograniczeń oznaczonych stereotypem <<definition>> można w wyrażeniach OCL definiować dodatkowe atrybuty i operacje klasyfikatorów Pozwala to współdzielić zmienne i operacje pomiędzy kilkoma ograniczeniami Dodatkowe cechy stają się zwykłymi atrybutami i operacjami klasyfikatora o stereotypie <<OclHelper>> Można je równoważnie (używając stereotypu <<OclHelper>>) zdefiniować w modelu UML

18 Definiowanie atrybutów/operacji – przykład
context Person def: income: Integer = job.salary->sum() def: nickname: String = ‘Super Dyzio’ def: hasTitle(t: String): Boolean = job->exists(title = t)

19 Zgodność typów Każdy typ jest zgodny z każdym swoim nadtypem (uogólnieniem) Relacja zgodności jest przechodnia (nie jest symetryczna) Typ kolekcji elementów typu T1 jest zgodny z typem kolekcji elementów typu T2 o ile T1 jest zgodny z T2 Collection(T1) jest zgodny z Collection(T2) o ile T1 jest zgodny z T2 Ta sama reguła obowiązuje dla par Set(T1)/Set(T2), OrderedSet(T1)/OrderedSet(T2), Bag(T1)/Bag(T2) i Sequence(T1)/Sequence(T2)

20 Komentarze w OCL Komentarze wierszowe – od dwuznaku ‘--’ do końca linii -- komentarz wierszowy Komentarze blokowe – ograniczone dwuznakami ‘/*’ i ‘*/’ /* komentarz blokowy */

21 Wartości nieokreślone
Są wynikiem niektórych operacji (np. branie pierwszego elementu pustej kolekcji) Na ogół wyrażenie o składowych nieokreślonych ma wartość nieokreśloną Wyjątek stanowią wyrażenia logiczne, w których wartość nieokreślona spełnia reguły logiki trójwartościowej Można jawnie testować, czy dany obiekt ma wartość nieokreśloną przy pomocy operacji oclIsUndefined() typu OclAny

22 Atrybuty obiektów Wynikiem wyrażenia jest wartość typu atrybutu
context Person inv: self.age > 0 Wynikiem wyrażenia jest wartość typu atrybutu W przypadku atrybutów o krotności większej niż 1 wynikiem jest kolekcja

23 Operacje obiektów Zwykłe wywołanie operacji – wynikiem jest wartość typu zwracanego przez operację aPerson.income(aDate) Jeśli operacja ma parametry inout lub out wynikiem jest krotka (tuple) złożona ze wszystkich parametrów out, inout i zwracanej wartości

24 Przykład operacji Jeśli operacja ma sygnaturę
Person::income(d: Date, out bonus: Integer): Integer to wynikiem jej wywołania jest krotka typu Tuple(bonus: Integer, result: Integer) do której składowych można odwołać się następująco: p.income(d).bonus = 100 and p.income(d).result = 3000

25 Końce powiązań i nawigacja
context Company inv: self.manager.isUnemployed = false inv: self.employee->size() <= 50 Jeśli krotnością końca jest co najwyżej 1 wartością wyrażenia jest obiekt odpowiedniego typu self.manager to obiekt klasy Person Jeśli koniec ma górne ograniczenie krotności większe niż 1 wartością jest kolekcja standardowo Set(T), dla właściwości uporządkowanych OrderedSet(T) self.employee to kolekcja Set(Person) OCL definiuje standardowe typy kolekcji i operacje na nich. Operator dostępu do operacji kolekcji to ‘->’.

26 Brakujące nazwy końców powiązań
Wyprowadzane są z nazw typów na końcach przez zamianę pierwszej litery na małą

27 Końce o krotności nie większej niż 1
Mogą być traktowane jako pojedyncze obiekty albo zbiory złożone z pojedynczych obiektów (lub puste) context Person inv: self.wife->notEmpty() implies self.wife.gender = Gender::female

28 Klasy powiązań Do specyfikacji nawigacji do klasy powiązania OCL stosuje regułę nazewniczą analogiczną do reguły brakującej nazwy końca context Person inv: self.job->size() <= self.age

29 Klasy powiązań zwrotnych
Nawigacja w stronę końca bosses self.employeeRanking[bosses]->sum() > 0 Nawigacja w stronę końca employees self.employeeRanking[employees]->sum() > 0

30 Powiązania kwalifikowane
W przypadku użycia wartości kwalifikatora otrzymujemy pojedynczy obiekt context Bank inv: self.customer[11].gender = Gender::male Opuszczając kwalifikator otrzymujemy kolekcję inv: self.customer->size() >= 30000

31 Predefiniowane operacje wszystkich obiektów
Następujące operacje są zdefiniowane we wspólnym przodku wszystkich typów OCL, tzn. OclAny, a zatem są dostępne dla wszystkich obiektów: oclIsTypeOf(t: OclType): Boolean oclIsKindOf(t: OclType): Boolean oclInState(s: OclState): Boolean oclIsNew(): Boolean oclIsUndefined(): Boolean oclIsInvalid(): Boolean oclAsType(t: OclType): T allInstances(): Set(T) oclIsKindOf() uwzględnia nadtypy allInstances() to operacja klasowa

32 Dostęp do przedefiniowanych atrybutów i operacji
Jeśli B jest podklasą A i przedefiniowuje właściwość A::p1 i jeśli self jest klasy B to self.p1 oznacza (zawsze) B::p1, natomiast self.oclAsType(A).p1 oznacza A::p1

33 Przykład cechy klasowej
context Singleton inv: Singleton.allInstances()->size() <= 1

34 Przykład określenia stanu obiektu
c.oclInState(On) c.oclInState(Off) c.oclInState(Off::NoPower)

35 Wartości poprzednie w warunkach końcowych
W warunku końcowym wartość właściwości jest rozumiana jako jej wartość w momencie zakończenia operacji stanowiącej kontekst Jednak często jest potrzebne odniesienie do wartości właściwości w momencie rozpoczynania operacji – służy do tego operator context Company::hireEmployee(p: Person) post: numberOfEmployees = + 1 and employee = and stockprice() = + 10 @pre jest zawsze przyrostkiem nazwy operacji/atrybutu (przed ewentualnymi parametrami)

36 Wartości poprzednie (c.d.)
Jeśli wartością poprzednią właściwości jest obiekt, to jego dla jego właściwości uwzględniane są wartości aktualne chyba że jawnie wyspecyfikujemy odniesienie do wartości poprzednich

37 Krotki Krotka jest zestawem nazwanych części o zróżnicowanych typach. Poniższe definicje literałów krotkowych są równoważne. Tuple {name: String = ‘Kowalski’, age: Integer = 20} Tuple {name = ‘Kowalski’, age = 20} Tuple {age = 20, name = ‘Kowalski’} Odniesienie do składowej części krotki: Tuple {age = 20, name = ‘Jan’}.age = 50 Wartość części krotki może być określona przez dowolne wyrażenie OCL

38 Kolekcje OCL OCL zawiera 5 typów kolekcji:
Abstrakcyjny typ Collection(T) Specjalizujące go typy konkretne Set(T) – zbiór elementów typu T OrderedSet(T) – zbiór uporządkowany Bag(T) – wielozbiór (zbiór z powtórzeniami) Sequence(T) – ciąg (wielozbiór uporządkowany)

39 Kolekcje OCL a nawigacja powiązań
Kolekcje są wynikami nawigacji powiązań Set(T) dla powiązań prostych (bez dodatkowych atrybutów) Bag(T) dla powiązań złożonych oraz prostych z powtórzenami OrderedSet(T) dla powiązań prostych uporządkowanych Sequence(T) dla powiązań prostych uporządkowanych z powtórzeniami

40 Literały kolekcji Set { ‘zielony’, ‘niebieski’, ‘czerwony’ } OrderedSet { ‘Ala’, ‘Ela’, ‘Ola’ } Bag { 1, 1, 3, 5, 1, 10, 10 } Dla literałów ciągów istnieje notacja skrótowa. Poniższe definicje są równoważne: Sequence { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } Sequence { } Sequence { 1..(3+7) }

41 Operacje na kolekcjach
Standardowa biblioteka OCL zawiera dużą liczbę operacji typu Collection(T) i jego podtypów Zapewnia to możliwość manipulowania standardowymi kolekcjami Operacje standardowe nigdy nie zmieniają stanu kolekcji (są zapytaniami)

42 Operacja select Pozwala wyspecyfikować podzbiór wyjściowej kolekcji przez podanie warunku przynależności Składnia collection->select(warunek) collection->select(v | warunek-z-v) collection->select(v: Typ | warunek-z-v)

43 Operacja select – przykłady
context Company inv: employee->select(age > 50)->notEmpty() inv: employee->select(p | p.age > 50)->notEmpty() inv: employee->select(p: Person | p.age > 50)->notEmpty()

44 Operacja reject Operacja o składni analogicznej do select, ale określająca warunek odrzucenia context Company inv: employee->reject(isMarried)->isEmpty() inv: employee->reject(p | p.isMarried)->isEmpty() inv: employee->reject(p: Person | p.isMarried)->isEmpty()

45 Operacja collect Konstruuje kolekcję wywiedzioną z danej kolekcji, ale zawierającą inne obiekty Set(T) przekształca w Bag(T) OrderedSet(T) przekształca w Sequence(T) Przykład (definicje równoważne) employee->collect(birthDate) employee->collect(person | person.birthDate) employee->collect(p: Person | p.birthDate)

46 Operacja collect – notacja skrótowa
Zamiast employee->collect(birthDate) self.employee->collect(income(‘ ’)) można pisać employee.birthDate self.employee.income(‘ ’)

47 Kwantyfikator ogólny context Company
inv: employee->forAll(age <= 65) inv: employee->forAll(p | p.age <= 65) inv: employee->forAll(p: Person | p.age <= 65) inv: employee->forAll(e1, e2 | e1 <> e2 implies e1.lastName <> e2.lastName)

48 Kwantyfikator szczegółowy
context Company inv: employee->exists(firstName = ‘Elvis’) inv: employee->exists(p | p.firstName = ‘Elvis’) inv: employee->exists(p: Person | p.firstName = ‘Elvis’)

49 Operacja iterate Najogólniejsza z operacji iteratorowych
Pozwala stworzyć nową kolekcję na podstawie danej przy pomocy jawnie określonego wyrażenia collection->iterate(e: Type; acc: Type2 = <wyr> | wyrażenie-z-e-i-acc)

50 Operacja iterate - przykład
Następująca operacja collect collection->collect(x: T | x.property) może być zdefiniowana przy pomocy iterate w następujący sposób collection->iterate(x: T; acc: Bag(T2) = Bag {} | acc->including(x.property))

51 Dodatkowe operacje typu Collection(T)
includes(object: T): Boolean excludes(object: T): Boolean count(object: T): Boolean includesAll(c: Collection(T)): Boolean excludesAll(c: Collection(T)): Boolean sum(): T product(c: Collection(T2)): Set(Tuple(first: T, second: T2)) product() wylicza iloczyn kartezjański

52 Dodatkowe operacje wspólne dla Bag(T), Set(T) i Sequence(T)
operator = (również dla OrderedSet(T)) including(object: T): odpowiednia_kolekcja excluding(object: T): odpowiednia_kolekcja flatten(): odpowiednia_kolekcja asSet(): Set(T) asBag(): Bag(T) asOrderedSet(): OrderedSet(T) asSequence(): Sequence(T)

53 Dodatkowe operacje wspólne dla Set(T) i Bag(T)
union(s: Set(T)): odpowiednia_kolekcja union(b: Bag(T)): Bag(T) intersection(s: Set(T)): Set(T) intersection(b: Bag(T)): odp_kolekcja

54 Dodatkowe operacje kolekcji uporządkowanych
append(object: T): odpowiednia_kolekcja prepend(object: T): odpowiednia_kolekcja insertAt(index: Integer, object: T): odpowiednia_kolekcja at(index: Integer): T indexOf(object: T): Integer first(): T last(): T

55 Dodatkowe operacje Set(T) OrderedSet(T) Sequence(T)
operator - (s: Set(T)): Set(T) symmetricDifference(s: Set(T)): Set(T) OrderedSet(T) subOrderedSet(lower: Integer, upper: Integer): OrderedSet(T) Sequence(T) subSequence(lower: Integer, upper: Integer): Sequence(T)

56 Dodatkowe operacje iteratorowe
Collection(T) isUnique(iterator | body): Boolean any(iterator | body): T one(iterator | body): Boolean Set(T) sortedBy(iterator | body): OrderedSet(T) Bag(T) i Sequence(T) sortedBy(iterator | body): Sequence(T)

57 Komunikaty w OCL Komunikaty (instancje OclMessage) służą do specyfikacji zdarzenia komunikacyjnego – wywołania operacji lub wysłania sygnału Operator ‘^’ określa czy komunikat został wysłany context Subject::hasChanged() post: observer^update(3, 19) post: observer^update(?, ?) post: observer^update(?: Integer, ?: Integer)

58 Analiza instancji komunikatów
Operator ‘^^’ zwraca ciąg rzeczywiście wysłanych komunikatów observer^^update(3, 4) Formalne parametry komunikatu są dostępne jako atrybuty instancji OclMessage context Subject::hasChanged() post: let msgs: Sequence(OclMessage) = observer^^update(?, ?) in msgs->notEmpty() and msgs->exists(m | m.j > m.i) Tutaj: Observer::update(i: Integer, j: Integer)

59 Analiza instancji komunikatów (c.d.)
Analiza komunikatów wysłanych do różnych obiektów context Subject::hasChanged() post: let msgs: Sequence(OclMessage) = observers->collect(o | o^^update(?, ?)) in msgs->forAll(m | m.i < m.j)

60 Przetwarzanie zwracanych wartości
context Person::giveSalary(amount: Integer) post: let msg: OclMessage = company^^getMoney(amount) in msg.hasReturned() and msg.result() = true Jest to sposób na określenie sposobu wyliczenia zwracanych wartości dla operacji, które nie są zapytaniami

61 Pozostałe operacje klasy OclMessage
isOperationCalled(): Boolean isSignalSent(): Boolean

62 Inne typy specjalne OCL
OclVoid Jedyna instancja nazywa się null (odpowiada specyfikacji wartości UML NullLiteral) OclInvalid Jedyna instancja nazywa się invalid OclElement OclType

63 Rozwiązywanie konfliktów nazw właściwości
Może zachodzić w przypadku zmiennych niejawnych self niejawne iteratory Rozstrzygane na korzyść zmiennych z najbardziej wewnętrznego zasięgu

64 Przykład konfliktu nazw
context Person inv: employer->forAll( employee->exists(lastName = name) ) znaczy to samo, co employee->exists(p | p.lastName = name) )

65 Użycie wyrażeń OCL w modelach UML


Pobierz ppt "Object Constraint Language (OCL) – wersja 2.0"

Podobne prezentacje


Reklamy Google