Object Constraint Language (OCL) – wersja 2.0

Slides:



Advertisements
Podobne prezentacje
Związki w UML.
Advertisements

Wzorce.
Wykład 10 Metody Analizy Programów Specyfikacja Struktur Danych
Standardy w zakresie systemów rozproszonych i baz danych
Bazy danych II Instrukcja SELECT Piotr Górczyński 25/08/2001.
XPath XSLT – część XPath. XSLT – część 12 XPath – XML Path Language Problem: –jednoznaczne adresowanie fragmentów struktury dokumentu XML.
ZŁOŻONOŚĆ OBLICZENIOWA
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 7: Procedury i funkcje © Jan Kaczmarek.
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 8: Wykorzystanie procedur i funkcji © Jan Kaczmarek.
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 6: Tablice, rekordy, zbiory.
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 5: Typy porządkowe, wyliczeniowe i okrojone. Definiowanie.
Język SQL – zapytania zagnieżdżone (podzapytania)
Bartosz Walter Prowadzący: Bartosz Walter
Struktury.
Tablice.
Inteligentne Systemy Informacyjne
Zasady zaliczenia Warunki uzyskania zaliczenia:
Typy standardowe Typ Boolean Typ Integer Typ Float Typ Character Operacje wejścia-wyjścia.
Pakiety i ATD 1 Definicja. Pakietem albo jednostką programową nazywamy grupę logicznie powiązanych elementów, które mogą być typami, podtypami, obiektami.
Typy pochodne 1 Często dogodnie jest wprowadzić nowy typ, który jest podobny do istniejącego, niemniej jednak różny. Niech T będzie pewnym typem. Możemy.
Programowanie zorientowane obiektowo 1 Programowanie zorientowane obiektowo (object-oriented programming) jest to metodologia programowania bazująca na.
Instrukcje 1 Definicje wstępne Formalny opis akcji wykonywanej przez komputer nazywamy instrukcją ( statement), Każda instrukcja kończona jest średnikiem.
Ogólne jednostki programowe 1
Tablice jednowymiarowe 1
Typy danych – podstawy 1 W Adzie wszystkie dane muszą być określonego typu. Definicja Typ danych (data type) jest to zbiór wartości i operacji, które można.
Typy prywatne 1 Typy prywatne W Adzie typy prywatne (private types) służą do bezpiecznego udostępniania danych zdefiniowanych w pakiecie, z którego korzysta.
Diagramy klas w języku UML
Projektowanie i programowanie obiektowe II - Wykład IV
Modele baz danych - spojrzenie na poziom fizyczny
Projektowanie - wprowadzenie
Język SQL (Structured Query Language) DDL (Data Definition Language)
Bazy Danych II prowadzący: mgr inż. Leszek Siwik
Nadstruktura języka UML w wersji 2.2 Część V Wdrożenie (pakiet UML::Deployments)
Infrastruktura języka UML w wersji 2.2
Nadstruktura języka UML w wersji 2.2
Infrastruktura języka UML w wersji 2.2
Wprowadzenie do JSP Copyright © Politecnico di Milano September 2003 Translation: Kamil Żyła, Politechnika Lubelska.
SQL – Structured Query Language (3)
Podstawy programowania
Podstawy układów logicznych
Automatyczne dereferencje w języku SBQL
Java – coś na temat Klas Piotr Rosik
Inicjalizacja i sprzątanie
XML – eXtensible Markup Language
Rozwiązanie zadań do zaliczenia I0G1S4 // indeks
Programowanie obiektowe 2013/2014
ZWIĄZKI MIĘDZY KLASAMI KLASY ABSTRAKCYJNE OGRANICZENIA INTERFEJSY SZABLONY safa Michał Telus.
Wykład 10 typ zbiorowy rekurencja.
Modelowanie obiektowe Diagramy klas
PL/SQL – dalsza wędrówka
Programowanie w języku C++
UML W V ISUAL S TUDIO Mateusz Lamparski. UML D EFINICJA Unified Modeling Language (UML) to graficzny język do obrazowania, specyfikowania, tworzenia i.
J A V A S C R I P T Obiekty Opracowała: Anna Śmigielska.
Programowanie strukturalne i obiektowe C++
Model obiektowy bazy danych
Diagram aktywności (czynności)
Diagram klas Kluczowymi elementami są: klasy (class)
Przegląd konstrukcji języka OCL
OCL precyzyjne modelowanie w UML
OCL.
Infrastruktura języka UML w wersji 2.2 Część VI Pakiet Core::Constructs (diagramy: bazowy, przestrzeni nazewniczych, klasyfikatorów, wyrażeń, ograniczeń)
Piotr Czapiewski Wydział Informatyki ZUT. Web Services Description Language.
Partnerstwo dla Przyszłości 1 Lekcja 28 Dziedziczenie i rodzaje dziedziczenia.
Asocjacja,Kompozycja,Agregacja
P ASCAL Definicje, deklaracje, podstawowe instrukcje 1.
Transformacja modelu EER do modelu relacyjnego
Programowanie Obiektowe – Wykład 2
Haskell Składnia funkcji.
PGO - Projektowanie i implementacja pierwszych klas
Zapis prezentacji:

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

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ą

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

Przykładowy diagram klas

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.

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

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

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

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

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

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

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() * 0.01 -- kieszonkowe derive: if underAge then parents.income->sum() * 0.01 else job.salary endif -- rozpoczyna komentarz

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

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

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

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

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

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)

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)

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

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

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

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

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

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 ‘->’.

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

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

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

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

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

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

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

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

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

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 przyrostkowy @pre context Company::hireEmployee(p: Person) post: numberOfEmployees = numberOfEmployees@pre + 1 and employee = employee@pre->including(p) and stockprice() = stockprice@pre() + 10 @pre jest zawsze przyrostkiem nazwy operacji/atrybutu (przed ewentualnymi parametrami)

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 a.b@pre.c chyba że jawnie wyspecyfikujemy odniesienie do wartości poprzednich a.b@pre.c@pre

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

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)

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

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 { 1..10 } Sequence { 1..(3+7) }

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)

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)

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()

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()

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)

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

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)

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

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)

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))

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

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)

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

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

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)

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)

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)

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)

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)

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

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

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

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

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

Użycie wyrażeń OCL w modelach UML