header Homepage DutchHomepage EnglishContactIndex
Training courses Training courses Projects Projects Books and publications Books and publications Research en Development Research Projecten The company The company
More on the Model Driven Architecture More on the Model Driven Architecture More on the object constraint language More on the object constraint language What is OCL?Current statusFuture developmentsTools and services More on the unified modeling language More on the unified modeling language
Downloads Downloads OCL logo

Introduction to OCL

The Object Constraint Language (OCL) is a language that enables one to describe expressions and constraints on object-oriented models and other object modeling artifacts. An expression is an indication or specification of a value. A constraint is a restriction on one or more values of (part of) an object-oriented model or system.

Various constraint languages have been used in object-oriented modeling methods (Syntropy, Catalysis, and BON), and programming languages (Eiffel). The OCL is a standard query language, which is part of the Unified Modeling Language (UML) set by the Object Management Group (OMG) as a standard for object-oriented analysis and design.

Types of expressions

Expressions can be used in a number of places in a UML model:

  • To specify the initial value of an attribute or association end.
  • To specify the derivation rule for an attribute or association end.
  • To specify the body of an operation.
  • To indicate an instance in a dynamic diagram.
  • To indicate a condition in a dynamic diagram.
  • To indicate actual parameter values in a dynamic diagram.

Types of constraints

There are four types of constraints:

  • An invariant is a constraint that states a condition that must always be met by all instances of the class, type, or interface. An invariant is described using an expression that evaluates to true if the invariant is met. Invariants must be true all the time.
  • A precondition to an operation is a restriction that must be true at the moment that the operation is going to be executed. The obligations are specified by postconditions.
  • A postcondition to an operation is a restriction that must be true at the moment that the operation has just ended its execution.
  • A guard is a constraint that must be true before a state transition fires.

The Context of an OCL Expression

The context definition of an OCL expression specifies the model entity for which the OCL expression is defined. Usually this is a class, interface, datatype, or component. In terms of the UML standard, this is called a Classifier.

Sometimes the model entity is an operation or attribute, and rarely it is an instance. It is always a specific element of the model, usually defined in a UML diagram. This element is called the context of the expression.

Next to the context, it is important to know the contextual type of an expression. The contextual type is the type of the context, or of its container. It is important because OCL expressions are evaluated for a single object, which is always an instance of the contextual type. To distinguish between the context and the instance for which the expression is evaluated, the latter is called the contextual instance. Sometimes it is necessary to refer explicitly to the contextual instance. The keyword self is used for this purpose.

For example, the contextual type for all expressions in Figure 1 is the class LoyaltyAccount. The precondition (pre: i>0) has as context the operation earn. When it is evaluated, the contextual instance is the instance of LoyaltyAccount for which the operation has been called. The initial value (init: 0) has as context the attribute points. The contextual instance will be the instance of LoyaltyAccount that is newly created.

Invariants on attributes

The simplest constraint is an invariant on an attribute. Suppose our model contains a class Customer with an attribute age, then the following constraint restricts the value of the attribute:

context Customer inv:
age >= 18

Invariants on associations

One may also put constraints on associated objects. Suppose in our model contains the class Customer has an association to class Salesperson, with role name salesrep and multiplicity 1, then the following constraint restricts the value of the attribute knowledgelevel of the associated instance of Salesperson:

context Customer inv:
salesrep.knowledgelevel >= 5

Collections of objects

In most of the cases the multiplicity of an association is not 1, but more than 1. Evaluating a constraint in these cases will result in a collection of instances of the associated class. Constraints can be put on either the collection itself, e.g. limiting the size, or on the elements of the collection. Suppose in our model the association between Salesperson and Customer has role name clients and multiplicity 1..* on the side of the Customer class, then we might restrict this relationship by the following constraint.

context Salesperson inv:
clients->size() <= 100 and clients->forAll(c: Customer | c.age >= 40)

Pre- and postconditions

In pre- and postconditions the parameters of the operation may be used. Furthermore, there is a special keyword result which denotes the return value of the operation. It can be used in the postcondition only. As an example we have added an operation sell to the Salesperson class.

context Salesperson::sell( item: Thing ): Real
pre: self.sellableItems->includes( item )
post: not self.sellableItems->includes( item ) and result = item.price

Derivation Rules

Models often define derived attributes and associations. A derived element does not stand alone. The value of a derived element must always be determined from other (base) values in the model. Omitting the way to derive the element value results in an incomplete model. Using OCL, the derivation can be expressed in a derivation rule. In the following example, the value of a derived element usedServices is defined to be all services that have generated transactions on the account:

context LoyaltyAccount::usedServices : Set(Services)
derive: transactions.service->asSet()

Initial Values

In the model information, the initial value of an attribute or association role can be specified by an OCL expression. In the following examples, the initial value for the attribute points is 0, and for the association end transactions, it is an empty set:

context LoyaltyAccount::points : Integer
init: 0
context LoyaltyAccount::transactions : Set(Transaction)
init: Set{}

Note the difference between an initial value and a derivation rule. A derivation rule states an invariant: The derived element should always have the same value that the rule expresses. An initial value, however, must hold only at the moment when the contextual instance is created. After that moment, the attribute may have a different value at any point in time.

Body of Query Operations

The class diagram can introduce a number of query operations. Query operations are operations that have no side effects, i.e., do not change the state of any instance in the system. Execution of a query operation results in a value or set of values, without any alterations in the state of the system. Query operations can be introduced in the class diagram, but can only be fully defined by specifying the result of the operation. Using OCL, the result can be given in a single expression, called a body expression. In fact, OCL is a full query language, comparable to SQL. The use of body expressions is an illustration thereof.

The next example states that the operation getCustomerName will always result in the name of the card owner associated with the loyalty account:

context LoyaltyAccount::getCustomerName() : String
body: Membership.card.owner.name

Broken constraints

Note that evaluating a constraint does not change any values in the system. A constraint states "this should be so". If for a certain object the constraint is not true, in other words, it is broken, then the only thing we can conclude is that the object is not correct, it does not conform to our specification. Whether this is a fatal error or a minor mistake, and what should be done to correct the situation is not expressed in the OCL.


This page was last updated on March 08, 2005
© Copyright Klasse Objecten, Soest, the Netherlands
Email address: info@klasse.nl