700 likes | 850 Views
The Object Constraint Language: Expressing Constraints in the UML. (Most slides created by Robert B. France, Professor
E N D
The Object Constraint Language: Expressing Constraints in the UML (Most slides created by Robert B. France, Professor Department of Computer Science, Colorado State University. Other material from: (Source: http://www.cse.dmu.ac.uk/~aoc/teaching-notes/Contents/CSCI3007/CSCI3007OCLtutorial.pdf)
Declarative vs Imperative Programming • With imperative programming, you say both what is to be done – and how it is to be done: List<int> collection = new List<int> { 1, 2, 3, 4, 5 }; List<int> results = new List<int>(); foreach(var num in collection) { if (num % 2 != 0) results.Add(num); } • Create a result collection • Step through each number in the collection • Check the number, if it's odd, add it to the results • With declarative programming, you say what is to be done – but not how it is to be done: var results = collection.Where( num => num % 2 != 0); From this link
What is OCL? • The Object Constraint Language (OCL) is a declarative language for describing rules that apply to UML models • OCL expressions are always associated with a UML model • OCL expressions can be associated with any model element in UML • OCL can be used • to describe constraints • A constraint is a restriction on one or more values of a model or system. • A constraint is an expression that evaluates to true or false • as a query language • Queries are expressions that evaluate to a value (true, false and other values) • Can be used to define new attributes and operations
Flight departing Flights origin Airport departTime: Time /arrivalTime: Time duration : Interval maxNrPassengers: Integer * 1 name: String 1 * arriving Flights desti- nation Constraints vs. Queries • Examples of constraints: • The duration of a flight is the same as the difference between the arrival and departure times • The maximum number of passengers on a flight must be less than 1,001 • The origin of a flight must be different than its destination • Examples of queries: • Return all the departing flights from a given airport • Return all the flights departing from a given airport with a departure time after 4p.m. • Derive the arrival time by adding the duration of the flight to the departure time.
Why OCL? - because UML is not enough! Required age of car owners? Requirement that a person may own at most one red car
Different kinds of constraints • Class invariant • a constraint that must always be met by all instances of the class • Precondition of an operation • a constraint that must always be true BEFORE the execution of the operation • Postcondition of an operation • a constraint that must always be true AFTER the execution of the operation
Flight departing Flights origin Airport departTime: Time /arrivalTime: Time duration : Interval maxNrPassengers: Integer * 1 name: String 1 * arriving Flights desti- nation Example: Expressing Invariants • Flight capacity constraint: The maximum number of passengers that can be on a flight must be less than or equal to 1,000. context Flight inv capacity: self.maxNrPassengers <= 1000 Note: self can be omitted context Flight inv capacity: maxNrPassengers <= 1000
Constraint context and self • Every OCL expression is bound to a specific context. • The context is often the element that the constraint restricts • The context may be denoted within the expression using the keyword ‘self’. • ‘self’ is implicit in all OCL expressions • Similar to ‘this’ in C++
Flight duration: Integer inv: duration < 4 Notation • Constraints may be denoted within the UML model or in a separate document. • the expression: context Flight inv durationLimit: self.duration < 4 • is identical to: context Flight inv: duration < 4 • is identical to:
Time $midnight: Time month : String day : Integer year : Integer hour : Integer minute : Integer difference(t:Time):Interval before(t: Time): Boolean plus(d : Interval) : Time Interval nrOfDays : Integer nrOfHours : Integer nrOfMinutes : Integer equals(i:Interval):Boolean $Interval(d,h,m : Integer) : Interval Example model Flight departing Flights origin Airport departTime: Time /arrivalTime: Time duration : Interval maxNrPassengers: Integer * 1 flights name: String 1 * airline * 1 arriving Flights desti- nation Airline 1 passengers name: String {ordered} * Passenger minAge: Integer age: Integer needsAssistance: Boolean airline 0..1 0..1 CEO book(f : Flight)
Time $midnight: Time month : String day : Integer year : Integer hour : Integer minute : Integer difference(t:Time):Interval before(t: Time): Boolean plus(d : Interval) : Time Interval nrOfDays : Integer nrOfHours : Integer nrOfMinutes : Integer equals(i:Interval):Boolean $Interval(d,h,m : Integer) : Interval Flight departing Flights origin Airport departTime: Time /arrivalTime: Time duration : Interval maxNrPassengers: Integer * 1 flights name: String 1 * airline * 1 arriving Flights desti- nation Airline 1 passengers name: String {ordered} * Passenger minAge: Integer age: Integer needsAssistance: Boolean airline 0..1 0..1 CEO book(f : Flight) • Constraint: The difference between the depart and arrival time for a flight must be the same as its duration. • context Flight • inv duration: self.departTime.difference(self.arrivalTime).equals(self.duration)
Elements of an OCL expression • In an OCL expression these elements may be used: • basic types: String, Boolean, Integer, Real. • classifiers from the UML model and their features • attributes, and class attributes • associations from the UML model
Some OCL Reserved Words • AND • ATTR • ELSE • ENDIF • IF • IMPLIES • INV • LET • NOT • OR • POST • PRE • THEN • XOR
OCL Comments • Comments in OCL are written following two successive dashes “--” • -- this is a comment
Time $midnight: Time month : String day : Integer year : Integer hour : Integer minute : Integer difference(t:Time):Interval before(t: Time): Boolean plus(d : Interval) : Time Interval nrOfDays : Integer nrOfHours : Integer nrOfMinutes : Integer equals(i:Interval):Boolean $Interval(d,h,m : Integer) : Interval Flight Example: OCL basic types departing Flights origin Airport departTime: Time /arrivalTime: Time duration : Interval maxNrPassengers: Integer * 1 flights name: String 1 * airline * 1 arriving Flights desti- nation Airline 1 passengers name: String {ordered} * Passenger minAge: Integer age: Integer needsAssistance: Boolean airline 0..1 0..1 CEO book(f : Flight) • context Airline • inv: name.toLower = ‘usair’ • context Passenger • inv: age >= ((9.6 - 3.5)* 3.1).floor implies mature = true • NB: A B = ~A v B
Associations and navigations • Every association in the model is a navigation path. • The context of the expression is the starting point. • Role names are used to identify the navigated association.
Flight departing Flights origin Airport departTime: Time /arrivalTime: Time duration : Interval maxNrPassengers: Integer * name: String * arriving Flights desti- nation Example: navigations • The name of the airline for a flight is Delta context Flight inv: airline.name = ‘Delta’ airline • The origin of a flight must be different than its destination context Flight inv: origin <> destination 1 Airline name: String
<<enumeration>> Ftype cargo passenger Example: Invariant involving Enumerated Type 1 Flight * Airplane flights ftype : Ftype atype : Ftype • The type of a flight must be the same as the type of the airplane. • {context Flight • inv ftype = Ftype::cargo implies Airplane.atype = Ftype::cargo • inv ftype = Ftype::passenger implies Airplane.atype = Ftype:: passenger}
JobType trainer programmer Association classes • Persons working with IBM have the job type “trainer” otherwise their job type is “programmer”. context Person inv: if employer.name = ‘IBM’ then Job.type = JobType::trainer else Job.type = JobType::programmer endif Job type : JobType 1 Company * Person employee employer name : String
Syntax for specifying operations context NameOfClass::operationName():returnType pre : -- some expression body : -- some expression post : some expression
Pre- and PostCondition Example A class named Account has an attribute balance and an operation overdraft() that returns true if the balance is less than 0 and false otherwise. context Account::overdraft():Boolean pre : -- none post : result = (balance < 0)
More complex operation specifications • The operation birthdayOccurs() adds 1 to the customer age. context Customer::birthdayOccurs() pre : -- none post : age = age@pre + 1 • What does this describe? context Account::safeWithdraw(amt:Integer) pre : balance > amt post : balance = balance@pre - amt
Time $midnight: Time month : String day : Integer year : Integer hour : Integer minute : Integer difference(t:Time):Interval before(t: Time): Boolean plus(d : Interval) : Time Interval nrOfDays : Integer nrOfHours : Integer nrOfMinutes : Integer equals(i:Interval):Boolean $Interval(d,h,m : Integer) : Interval Example model Flight departing Flights origin Airport departTime: Time /arrivalTime: Time duration : Interval maxNrPassengers: Integer * 1 flights name: String 1 * airline * 1 arriving Flights desti- nation Airline 1 passengers name: String {ordered} * Passenger $minAge: Integer age: Integer needsAssistance: Boolean airline 0..1 0..1 CEO book(f : Flight)
Derived Attribute & Initial Value Example Defining derived attributes context Flight::arrivalTime:Time derive:departTime.plus(duration) Defining initial attribute value context Flight::maxNrPassengers:Integer init: 100 Defining initial association end value context Flight::passengers:Set(Passenger) init: Set{}
Flight departing Flights origin Airport departTime: Time /arrivalTime: Time duration : Interval maxNrPassengers: Integer * 1 flights 1 name: String * airline 1 * arriving Flights desti- nation Airline 1 name: String Query operation examples Return all the departing flights from a given airport context Airport::departures():Set(Flight) body: result=departingFlights Return all the airports served by an airline context Airline::served():Set(Airport) body: result=flights.destination->asSet()
Flight 0..* 1 Airplane flights type : enum of cargo, passenger type : enum of cargo, passenger Significance of collections in OCL • Most navigations return collections rather than single elements
Subtypes of Collection • Set: each element occurs only once (Non-ordered, unique) • OrderedSet: a set with ordered elements. • Bag: elements may be present more than once(non-ordered, non-unique) • Sequence: a bag with ordered elements (ordered, non-unique)
passengers {ordered} * Passenger $minAge: Integer age: Integer needsAssistance: Boolean Flight departing Flights origin Airport departTime: Time /arrivalTime: Time duration : Interval maxNrPassengers: Integer book(f : Flight) * 1 flights 1 name: String * airline 1 * arriving Flights desti- nation Airline 1 name: String Subtypes of Collection • Set: arrivingFlights - from the context Airport • Non-ordered, unique • Bag: arrivingFlights.duration - from the context Airport • Non-ordered, non-unique • Sequence: passengers - from the context Flight • Ordered, non-unique
Collection operations • OCL has a great number of predefined operations on the collection types. • Syntax: • collection->operation Use of the “->” (arrow) operator instead of the “.” (dot) operator
The collect operation • Syntax: collection->collect(elem : T | expr) collection->collect(elem | expr) collection->collect(expr) • The collect operation results in the collection of the values resulting from evaluating expr for all elements in the collection • Shorthand often trips people up. Be Careful!
airline1 f1 airp1 f2 airline2 f3 airp2 airline3 f4 f5 departing flights arriving flights Example: collect operation All arriving flights must be associated with an airline context Airport inv: self.arrivingFlights -> collect(airLine) ->notEmpty
The select operation • Syntax: collection->select(elem : T | expression) collection->select(elem | expression) collection->select(expression) • The select operation results in the subset of all elements for which expression is true
airline1 f4 duration = 5 f1 duration = 2 f2 duration = 5 f5 duration = 2 f3 duration = 3 airp1 airline2 airp2 airline3 Example: select operation There must be at least one departing flight whose duration is less than 4 context Airport inv: self.departingFlights->select(duration<4)->notEmpty departing flights arriving flights
The forAll operation • Syntax: • collection->forAll(elem : T | expr) • collection->forAll(elem | expr) • collection->forAll(expr) • The forAll operation results in true if expr is true for all elements of the collection
airline1 f4 depart = 9 f1 depart = 7 f2 depart = 5 f5 depart = 8 f3 depart = 8 airp1 airline2 airp2 airline3 departing flights arriving flights Example: forAll operation All departing flights must leave after 6 context Airport inv: self.departingFlights->forAll(departTime.hour>6)
The exists operation • Syntax: collection->exists(elem : T | expr) collection->exists(elem | expr) collection->exists(expr) • The exists operation results in true if there is at least one element in the collection for which the expression expris true.
airline1 f4 depart = 9 f1 depart = 7 f2 depart = 5 f5 depart = 8 f3 depart = 8 airp1 airline2 airp2 airline3 departing flights arriving flights Example: exists operation context Airport inv: self.departingFlights->exists(departTime.hour<6)
Other collection operations • isEmpty: true if collection has no elements • notEmpty: true if collection has at least one element • size: number of elements in collection • count(elem): number of occurences of elem in collection • includes(elem): true if elem is in collection • excludes(elem): true if elem is not in collection • includesAll(coll): true if all elements of coll are in collection
Examples • A vehicle owner must be at least 18 years old.: context Vehicle • inv: self.owner. age >= 18
Examples • A car owner must be at least 18 years old.: context Car • inv: self.owner. age >= 18
Examples • Nobody has more than 3 vehicles: context Person • inv: self.fleet->size <= 3
Examples • All vehicles of a person are black: context Person • inv: fleet->forAll(v | v.colour = #black)
Examples • Nobody has more than 3 red vehicles: context Person • inv: fleet->select(v | v.colour = #red)->size <= 3