Difference between revisions of "OCL"

From Suhrid.net Wiki
Jump to navigationJump to search
Line 177: Line 177:
  
 
Here the select is working on bag of Person that employees produces. The first part of select specifies on which object we are applying the condition, then a '|' separator character, then the condition for the select. Then the operator isEmpty() is applied which will return true if the collection returned by the select is true.
 
Here the select is working on bag of Person that employees produces. The first part of select specifies on which object we are applying the condition, then a '|' separator character, then the condition for the select. Then the operator isEmpty() is applied which will return true if the collection returned by the select is true.
 +
 +
=== collect ===
 +
 +
* Takes an expression as an argument and makes a collection which '''contains all values''' of the expression.
 +
* for e.g. this gives a bag of all ages of all employees in a department.
 +
* Note just this statement, probably doesnt make sense, because its not acting as a constraint. [TODO]
 +
 +
<syntaxhighlight lang="java5">
 +
context Department
 +
staff->collect(p:Person | p.Age())
 +
</syntaxhighlight>
 +
 +
  
 
[[Category:OODE]]
 
[[Category:OODE]]

Revision as of 11:28, 1 November 2011

Introduction

  • How can we express constraints in UML ?
  • E.g. the balance attribute in a SavingsAccount class can never be less than zero and more than 100000.
  • UML only has a notion of an informal constraint in terms of a note - which can be attached to a model. However its just text.
  • To write formal and machine checkable constraints - we use the Object Constraint Language (OCL).

Assertions

  • In a program, assertions express constraints on program state that must be true at a specified point during execution.
  • In a model/diagram, they document what must be true of an implementation of a modelling element.
  • Can have optional preconditions - (must be true when operation is invoked). for e.g. an argument to a certain operation cannot be null.
  • Can have optional postconditions - (must be true when operation completes). for e.g. the operation must update the database when it completes.

Design by contract

  • A pre and post condition can be viewed as a contract between an operation and its invokers.
  • Something like - "If the client promises to invoke the operation with the precondition satisfied, then the operation guarantees that its implementing methods will deliver a final state in which the postcondition is true".
  • So the invoker doesn't care about how final state is produced
  • And the implementer doesn't need to worry about cases where the precondition is not true.
  • So a contract can be many things:
    • A specification of what a method should do.
    • Documentation - more precise than class interfaces.
    • Offers runtime checks for correctness.
    • Are a basis for testing.
    • Are a basis for formal proofs of programs correctness.

OCL

  • OCL is the constraint language for UML.
  • Used to write general constraints on UML as well as DBC.
  • Can apply to any modeling element, not only classes.
  • OCL Essential Capabilities:
    • Specifying which model element is to be constrained (the context).
    • Navigating through models to identify objects that are relevant to a constraint.
    • Asserting properties about links between objects.

OCL Context

  • Consider a BankAccountclass with an integer balance.
  • OCL constraint
context BankAccount inv:
self.balance>=0 and self.balance<=250000
  • The constraint is an invariant that applies in the context of the class BankAccount. Invariant for the context BankAccount means that the constraint holds true for all instances of BankAccount.
  • Note it does not have the same meaning as static.
  • This means the balance for any BankAccount object must be within 0 and 250000.
  • self means the same thing as "this".
  • In this case, self need not be mentioned (doesnt make a difference though)

Navigation Expressions

  • We can refer to object that are linked to the context object.
  • We need to start from the context object. Consider the below example:

Ocl-navigation.jpg

  • To get the set of employees working in a department :
context Department
self.staff
  • The association name has to be followed
  • Think of it something like the below code in Java, to access the Person object,
class Department {
  private Set<Person> staff;

  public Set<Person> getStaff() {
    return this.staff;
  }
}
  • If there is no association name, then the class name at the destination end of the context object can be used.
  • The class name has to be in lower case
  • Eg to get the department from the company:
context Company
self.department
  • The multiplicity of the assocation will tell us how many objects are retrieved.
  • e.g. below OCL will retrieve one object
context Department
self.company

Iterated Traversals

  • Navigations can be composed of multiple references - we can denote more paths through a diagram.
  • e.g All the people who work for a comapany
context Company
self.department.staff

self.department will give a set of departments, and then .staff is applied to each department producing a set of people. If people were not unique to a department, then a bag of people would be returned.

Names and Invariants

  • An OCL invariant need not be applicable to any instance:
  • e.g.
context bart: Person inv
bart.age == 10
  • Here bart is an object of type Person and we are stating that for the object bart, the age will always be 10. This is the invariant constraint for a single object.
  • An invariant can be given a name:
context bart: Person inv how_old:
bart.age == 10

Basic types

  • OCL supports basic types such as boolean, integer, real, string
  • Collection types such as collection,set,bag,tuple, are also basic types.
  • Additionally, every class appearing in the UML class model can be used as a basic type in OCL.

Basic operations

  • oclIsTypeOf(t:OclType):true, if selfand t are the same type (This is sort of useless, better to use oclIsKindOf())
  • oclIsKindOf(t:OclType):true, if self and t are the same type or self is of a class derived from t (This behaves like Java's instanceof operator)
  • oclInState(s:OclState):true, if selfis in the state specified by s. s is the name of some state in the statechartfor the class.
  • oclIsNew():true if used in a postcondition and the object is created by the operation.

Logic in OCL

  • Three valued: true, false and undefined.
  • e.g. illegal type conversion can result in undefined.
  • What will be the result of combining OCL's logic operators together ? i.e. what is the truth table ?
  • An expression is undefined if one of its arguments is undefined, except:
    • true OR anything is true (conventional)
    • false AND anything is false (conventional)
    • false IMPLIES anything is true. (TODO: what does this mean)

Operations on objects and collections

  • Operations and attributes defined for classes in a model can be used in an OCL expression.
  • Example:
context Person
self.age()
self.contract.grade.salary
  • Collections have some built in operations (like Java's Collection class has methods like size(), toArray() etc) which are accessed through the "->" operator.
  • e.g. sum() is a pre-defined operation on integer collection, here salary is a bag of integers - representing salarys of all staff.
context Department
staff.contract.grade.salary->sum()
  • How this works is that staff (self.staff) where self refers to a department instance will return a bag of Person objects. staff.contract will then return a bag of contract objects (contracts for all person objects in previous bag), similarly a bag of grade objects, followed by a bag of salary objects. The operation sum() is then applied to this bag.

select

  • An operation which allows us to specify criteria by which we can pick certain objects from a collection.
  • Like an SQL Query.
  • e.g : specify an invariant for the company, that none of its employees should have a salary that exceeds 50000
context Company inv:
employees->select(p:Person | p.contract.grade.salary > 50000)->isEmpty()

Here the select is working on bag of Person that employees produces. The first part of select specifies on which object we are applying the condition, then a '|' separator character, then the condition for the select. Then the operator isEmpty() is applied which will return true if the collection returned by the select is true.

collect

  • Takes an expression as an argument and makes a collection which contains all values of the expression.
  • for e.g. this gives a bag of all ages of all employees in a department.
  • Note just this statement, probably doesnt make sense, because its not acting as a constraint. [TODO]
context Department
staff->collect(p:Person | p.Age())