I ntroduction to OCL Why is formalization required? Graphical - - PDF document
I ntroduction to OCL Why is formalization required? Graphical - - PDF document
I ntroduction to OCL Why is formalization required? Graphical elements of the diagrammatic specifications are very powerful and obvious easy to understand how they fit together ;) Modeling details, such as uniqueness and referential
2
The quest for formalization ...
Accuracy and unambiguity in specification is the
aim of the branch of computer science known as “formal methods”
Several attempts have been made to combine
them with object-oriented modeling …
Formal methods in OO (1/4)
Extending and adapting an existing formal
language with object-oriented constructs
– Ex: Z++, Object-Z, VDM++ This approach is not in line with industrial
practice trends to use the simple, but powerful, graphical notations in OOAD.
Most practitioners are not at ease in using
traditional formal specification languages ...
3
Z, Z++ and Object Z
Z is a specification language developed by the Programming
Research Group at Oxford University
– "Understanding Z", J.M.Spivey, Cambridge U Press, 1988
Z is used for describing and modeling computing systems
– It is based on axiomatic set theory and first order predicate logic – Z is written using many non-ASCII symbols
Z++ is an object-oriented extension of Z
– "Z++, an Object-Oriented Extension to Z", Lano, Z User Workshop, Oxford 1990, Springer Workshops in Computing, 1991, pp.151-172
Object Z is another object-oriented extension of Z developed
at University of Queensland, Australia
– "Object Orientation in Z", S. Stepney et al eds, Springer 1992
An Object-Z extract …
4
Formal methods in OO (2/4)
Complementing diagrammatic notations with
some existing formal language constructs
– Ex: Syntropy (subset of Z combined with OMT), ROOA (A. Moreira), Metamorphosis (J. Araújo) Compromise solution, joining the benefits of
graphical modeling and formal languages
– Drawback1: conceptual gap between formalisms – Drawback2: same as in previous approach
A bit of Syntropy
5
Formal methods in OO (3/4)
Use of a constraint language to express design
by contract modeling issues (B. Meyer)
– Ex: BON (Business Object Notation) object-oriented method (Waldén 95).
- Has a full-fledged textual assertion mechanism, allowing to
specify system structure and semantics (constraints, invariants, properties of expected results)
– Bridges the semantic gap but failed widespread acceptance (too tied to Eiffel language world) – Acceptance often comes from standardization ...
BON:
Elevator example
6
Formal methods in OO (4/4)
The last and more promising road is OCL Is a part of the UML standard published by the
OMG (let’s have a look at it ...)
Used in the standard itself to clarify the
semantics of the graphical notations
Allows to specify invariants, preconditions,
postconditions, guard conditions, and other types of constraints (restrictions)
Therefore supports design by contract
Object Constraint Language
It is a formal, yet simple notation, to be used
jointly with UML diagrams
Its syntax has some similarities to those of
some OO programming languages
It is underpinned by mathematical set theory
and logic, like in formal languages
However it was designed for usability and is
easily grasped by those familiar with OO modeling concepts (particularly UML ones)
7
Object Constraint Language
OCL brings the best of the previous
approaches:
– simplicity and powerfulness of graphical notations – preciseness and unambiguity granted by formality, in a usable and conceptually integrated fashion – Moreover, since it is a part of UML, it has become a de jure standard (soon de facto?)
Adding OCL to UML models
Graphic Editors
System X Diagrams System Z Diagrams System Y Diagrams
Modeling Tools
Tool Repository
OCL Expressions Evaluator
UML Model Workload (Model Objects) OCL Expressions (Model Constraints) Expression Results
Workload Generator
UML Model
8
Some bits of history ...
Version Date Submitters / Supporters
1.1 (36 p.) Sep 1997 Rational, Microsoft, Hewlett-Packard, Oracle, Sterling Software, MCI Systemhouse, Unisys, ICON Computing, IntelliCorp, i-Logix, IBM, ObjecTime, Platinum Technology, Ptech, Taskon, Reich Technologies, Softeam 1.2 … … 1.3 June 1999 … 1.4 … … 2.0 (214 p.) Jan 2003 Submitters: Boldsoft, Rational, IONA, Adaptive Ltd. Supporters: Klasse Objecten, Borland, Kings College, University of Bremen, Dresden University of Technology, Kabira Technologies, IBM, Telelogic, University of Kent, Project Technology, University of York, Compuware, Syntropy Ltd., Oracle, Softeam
Objectives of OCL 2.0
Define a MOF 2.0-compliant metamodel for OCL.
– This metamodel should define the concepts and semantics of OCL and act as an abstract syntax for the language.
(Re)define the OCL 1.4 syntactical definition
– That is done by means of a grammar, as a concrete syntax expressing the abstract syntax defined above.
To allow for alternative concrete syntaxes (e.g. Java-like
syntax or visual constraint diagrams)
– This is achieved by defining a strict separation between the metamodel and the concrete syntax.
9
OCL features evolution
OCL 1.* is side-effect free (only selectors allowed)
– Selectors are query operations which return a value but do not change the object state (their label isQuery = true)
OCL 2.* allows expressing messages sent by
components, classes or other constructs that may have behavior (using the OclMessage concept)
– This allows the specification of behavioral constraints
UML 1.4 predefined types and operations are defined
as the OCL 2.0 Standard Library.
The concrete syntax of OCL 2.0 is backwards
compatible with OCL 1.4 !!!
OCL types
OclAny Enumeration Collection Real Integer Sequence Bag Set String Boolean
10
Standard operators
Type Operations Boolean =, not, and, or, xor, implies, if-then-else Real =, +, -, *, /, abs, floor, max, min, <, >, <=, >= Integer =, +, -, *, /, abs, div, mod, max, min, <, >, <=, >= String =, size, toLower, toUpper, concat, substring
Expressing class invariants
Constraints that represent conditions that must
be met by all class instances, at all times.
– Their context is, therefore, a class, hereafter represented in the first line, underlined, as in:
Sequence self.oclIsKindOf( Collection )
- sequence inherits from Collection and therefore its
instances can be used where a collection is allowed (this is a comment) Percentage (self >= 0) and (self <=1)
- - Percentage inherits from Real 0 is 0% and 1 is 100%
11
Expressing operation assertions
Pre-conditions are constraints that must be
true before an operation is executed
– In the design by contract paradigm, they represent the rights of the object that offers the service or, if you want, the client responsibilities. Post-conditions are constraints that must be
true when the operation ends its execution
– They represent the obligations to be fulfilled by the
- bject that offers the service, or, if you want, the
client rights.
Design by Contract
Obligation Right SUPPLIER Right Obligation CLIENT POST-CONDITION PRE-CONDITION
12
Operation assertions: examples
The context of both pre and post-conditions is,
therefore, an operation:
Sequence::prepend(object: T): Sequence(T) post: result->size() = self@pre->size() +1 post: result->at(1) = object
“::” is a scope indicator “->” is used for applying an operation to a collection “@pre” is a timing tag (state at preconditions evaluation)
Expressing operation semantics
Date::isBefore(t:Date): Boolean = if self.year = t.year then if self.month = t.month then self.day < t.day else self.month < t.month endif else self.year < t.year endif
Date
day : In teger mon th : In tege r ye ar : In teger now : Date isBefore(t : Date) : Boolean isAfter(t : Date) : Boolean isEqual(t : Date) : Boolean ye arsSince(t : Da te) : In teger today() : Date
13
Collection operations
Collection is an abstract
class
Collection
s ize() : Integer i ncludes (obj ect : OclAny) : Boolean count(object : OclAny) : Integer includesAll(c2 : Collection(T)) : Boolean i s Empty() : Boolean notEmpty() : Boolea n s um () : Real exists (expr : OclExpres sion) : Boolean forAl l(expr : Ocl Expres sion) : Boolea n iterate(expr : OclExpres sion) : OclType
Sequence Bag Set Collection
Set operations
Sets are non
- rdered
collections without duplicates.
Set
union(s et2 : Set(T)) : Set (T) union(bag1 : Bag(T)) : Bag (T) =(s et2 : Set(T)) : Boolean inters ection(s et2 : Set(T)) : Set (T) inters ection(bag1 : Bag(T)) : Bag (T)
- (s et2 : Set(T)) : Set (T)
including(object : T) : Set (T) excluding(object : T) : Set (T) s ym m etricDifference(s et2 : Set(T)) : Set (T) s elect(expr : OclExpres s ion) : Set (T) reject(expr : OclExpres s ion) : Set (T) collect(expr : OclExpres s ion) : Set (expr.evaluationType()) count(object : T) : Integer as Sequence() : Sequence (T) as Bag() : Bag (T)
14
Bag operations
Bags are unordered collections that may hold duplicate elements
Bag
=(bag2 : Bag(T)) : Boolean union(bag2 : Bag(T)) : Bag (T) union(set1 : Set(T)) : Bag (T) intersection(bag2 : Bag(T)) : Bag (T) intersection(s et1 : Set(T)) : Set (T) including(object : T) : Bag (T) excluding(object : T) : Bag (T) select(expr : OclExpress ion) : Bag (T) reject(expr : OclExpress ion) : Bag (T) collect(expr : OclExpress ion) : Bag (expr.evaluationType[)) count(object : T) : Integer asSequence() : Sequence (T) asSet() : Set (T)
Sequence operations
Sequences are
- rdered
collections that may hold duplicate elements
Sequence
count(object : T) : In teger =(sequence2 : Sequence(T)) : Boolean union(s equence2 : Sequence(T)) : Sequence (T) append(object : T) : Sequence (T) prepend(object : T) : Sequence (T) s ubSequence(lower : Integer, upper : Integer) : Sequence (T) at(at : Integer) : T firs t() : T las t() : T including(object : T) : Sequence (T) excluding(object : T) : Sequence (T) s elect(expr : OclExpress ion) : Sequence (T) reject(expr : OclExpres sion) : Sequence (T) collect(expr : OclExpress ion) : Sequence (expr.evaluationType[)) iterate(expr : OclExpres sion) : OclType asBag() : Bag (T) asSet() : Set (T)
15
Collection type:
- perations
The Collection class is an abstract class
from which the previous three are derived:
Collection Collection.allInstances->select(oclType = Collection)- >isEmpty()
- - the allInstances operation returns the set of all objects of
the named class and of all its subclasses;
- - this operation is defined in the OclType meta-class.
Note: the dot notation is used both for attribute access and for expressing navigation through class associations
Expressing unicity constraints
Customer Customer.allInstances->forAll(c1, c2: Customer | c1 <> c2 implies c1.client_id <> c2.client_id)
- -Customer identifiers should always be unique
Customer
client_id : Integer name : String title : String isMale : Boolean dateOfBirth : Date age()
16
Navigation and collections
OCL expressions can be built by
navigating in the class diagram
By definition, the result of navigating
through just one association is a Set
The result of navigating through more
than one association where at least one has multiplicity many is a Bag.
– Exception: if the association is adorned with the {ordered} tag, we get a Sequence.
Navigation example
Customer not (related_with->includes(self))
- - what does this mean?
+related_with 0..* Customer
client_id : Integer name : String title : String isMale : Boolean dateOfBirth : Date age()
17
“Royal & Loyal” case study
Loyalty program management system Customers must become members to get an
account and then have cards
Customers make earning and burning transactions Transactions are associated with a given card Program partners offer services of a given level Adapted example from [Warmer & Kleppe 1999]
Burning Earning Membership LoyaltyAccount 0..1 1 0..1 1 ProgramPartner ServiceLevel 1 0..* +actualLevel 1 0..* Transaction 0..* 1 +trans actions 0..* 1 Service 0..* 1 +deliveredServices 0..* 1
- 0. .*
1 +availableServices
- 0. .*
1 0..* 1 +transactions 0..* 1 LoyaltyProgram 1..* 1..* +partners 1..* 1..* 1..* 1 1..* {ordered} 1 CustomerCard 1 1 +card 1 1
- 0. .*
1 +transactions
- 0. .*
+card 1 Customer 0..* 0..* +program 0..* 0..* 1 0..* +owner 1 +cards 0..*
- 0. .*
- 0. .*
+related_with
18
Navigation and naming rules
Rule 0 - Class names start with an uppercase
letter and role names with a lowercase letter
Rule 1 - While navigating from a class to
another, if the role of the destination class is defined then use it. Otherwise apply rule 2
Rule 2 - While navigating from a class to
another, if the role of the destination class is not defined, then use the name of the destination class starting with a lowercase letter
Navigating and naming rules
Problem: a card issued for a membership is in the possession of the customer who is mentioned in the membership
Membership
card.owner = customer
19
Navigating and naming rules
Problem: construct a function “program()” that returns the loyalty program corresponding to the transaction Transaction::Program():LoyaltyProgram = (H1) card.membership.program (H2) service.serviceLevel.loyaltyProgram (H3) ? (H4) ? (H5) ?
Enumerations
Enumeration values are prefixed with “ #”
Ex 1: a CustomerCard color is silver or gold CustomerCard
color = #silver or color = #gold
Ex 2: the card color relative to a given membership must match the corresponding service level Membership
actualLevel.name = 'Silver' implies card.color = #silver and card.color = #silver implies actualLevel.name = 'Silver' and actualLevel.name = 'Gold' implies card.color = #gold and card.color = #gold implies actualLevel.Name = 'Gold'
20
Operations over collections
The partners of a given program cannot burn
more than 10000 points (as a whole)
LoyaltyProgram
partners.deliveredServices.transactions-> select (OclType = Burning)->collect(points)->sum < 10000
- - same as above but using the shorthand for collect
partners.deliveredServices.transactions.points->sum < 10000
- - is there something wrong?
Operations over collections
The partners of a given program cannot burn
more than 10000 points (individually)
LoyaltyProgram
partners->forAll(p: Partner | p.deliveredServices.transactions-> select (OclType = Burning)->collect(points)->sum < 10000) partners->forAll(deliveredServices.transactions-> select (OclType = Burning)->collect(points)->sum < 10000)
21
Notation may be simplified ...
Example: there is one service level whose
name is 'basic’
LoyaltyProgram
- - inv BasicService:
self.serviceLevel->exists( s: ServiceLevel | s.name = 'basic' )
- - inv BasicService2:
serviceLevel->exists( s | s.name = 'basic' )
- - inv BasicService3:
serviceLevel->exists( name = 'basic' )
Operation Semantics example
Customer.age() ? Customer.age():Integer = (H1) dateOfBirth.today().yearsSince( dateOfBirth ) (H2) dateOfBirth.yearsTo( dateOfBirth.today() )
Date
day : Integer month : Integer year : Integer now : Date isBefore(t : Date) : Boolean isAfter(t : Date) : Boolean isEqual(t : Date) : Boolean yearsSince(t : Date) : Integer today() : Date yearsTo(t : Date) : Integer
Customer
client_id : Integer name : String title : String isMale : Boolean dateOfBirth : Date age()
22
Invariant example
The initial date of the card
validity must be previous to the cancellation date
CustomerCard (H1) validFrom.isBefore(goodThru) (H2) goodThru.isAfter(validFrom)
Date
day : Integer month : Integer year : Integer now : Date isBefore(t : Date) : Boolean isAfter(t : Date) : Boolean isEqual(t : Date) : Boolean yearsSince(t : Date) : Integer today() : Date yearsTo(t : Date) : Integer
Invariant example
The name printed in the card is a concatenation of the
- wner title followed by the owner name
CustomerCard printedName = owner.title.concat(owner.name) Customer cards->forAll(printedName=self.title.concat(self.name))
23
Invariant example
The number of valid cards for every customer
must be equal to the number of programs the customer participates in CustomerCards program->size = cards->select(valid)->size
Invariant example
A customer cannot hold more than one valid card
for every program in which he participates
Customer program->forAll(membership.card-> select (valid and (owner=self))->size <=1)
24
Operation semantics example
Write the predicate Alarm that allows detecting
that a given balance (alarm level) between burned points and earned points was exceeded, for a named LoyaltyProgram
LoyaltyProgram::Alarm(level: Real): Boolean= Burning.allInstances->select(program() = self) -> collect(points)->sum > (Earning.allInstances->select(program() = self) -> collect(points)->sum) * level
Now that you are feeling confident :)
Example: Valid cards are "gold" for holders that
have had in the past some card (expired before the issue of the current one) within the same program, for which they have had transactions of at least 150000 points or if they have always had done more than 5000 points worth of transactions for all expired cards, no matter which program. If cards are not gold then they are "silver”!!!
25
This is almost correct. Why?
CustomerCard
color = if membership.program.customer.cards ->select(owner = self.owner) -> exists(goodThru.isBefore(self.validFrom) and transactions.points->sum >= 15000) or owner.cards -> select (goodThru.isBefore(self.validFrom)) -> forAll (transactions.points -> sum > 5000) then #gold else #silver endif
Implementation of OCL in USE
OCL syntax
Implicit flattening is only done when used with the shorthand notation for collect. For instance: company.branches.employees
– results in a Bag(Employee)
company.branches->collect(c | c.employees)
– results in a Bag(Set(Employee))
This result can be flattened into a Bag(Employee) by explicit flattening the collection with the `flatten' operation added in USE: company.branches->collect(c | c.employees)->flatten
26
Implementation of OCL in USE
OCL syntax Type checking requires that empty collections must be specified as:
- clEmpty(<collection-type>)
For example:
- clEmpty(Set(Integer))
instead of
- Set{}
Implementation of OCL in USE
OCL semantics
Some OCL operations are non-deterministic, e.g.,
- Set(T)->asSequence
The result of these operations are implementation
- dependent. The equation:
- s1->asSequence = s1->asSequence
will therefore be wrong in general.
27
Implementation of OCL in USE
OCL extensions/variations
Collection types can be nested to any level, e.g.,
Bag(Set(Sequence(Person)))
All types include an undefined value. For example, the expression 1/0 results in the value "undefined" of type Integer Checking for an undefined value can be done with the new
- perations "isDefined" and "isUndefined". These are defined for
all types, e.g., (1/0).isUndefined() results in "true" An undefined value may be explicitly specified with the new
- peration "oclUndefined(T)" where T may be any type
OCL Tools
Feature IBM Parser Dresden Toolkit TU Munich Tool ModelRun (… Rose) Bremen USE Syntactical analysis
- Type checking
- Logical
consistency checking Dynamic invariant validation
- Dynamic pre /
post condition validation
- Test
automation
- Code
verification and synthesis