Vous êtes sur la page 1sur 24

Object Constraint Language (OCL) Une introduction

Master 2 IFPRU - Module Ingnierie des modles - FMIN310

Marianne Huchard 7 novembre 2008

Prsentation gnrale

OCL est un langage formel, bas sur la logique des prdicats du premier ordre, pour annoter les diagrammes UML en permettant notamment lexpression de contraintes.

1.1

Objectif du langage

Voici les arguments avancs pour lintroduction dOCL. Accompagner les diagrammes UML de descriptions : prcises non ambigus Eviter cependant les dsavantages des langages formels traditionnels qui sont peu utilisables par les utilisateurs et les concepteurs qui ne sont pas rompus lexercice des mathmatiques : rester facile crire ... et facile lire Dans le cadre de lingnierie des modles, la prcision du langage OCL est ncessaire pour pouvoir traduire automatiquement les contraintes OCL dans un langage de programmation an de les vrier pendant lexcution dun programme.

1.2

Historique

OCL sinspire de Syntropy [CD94] mthode base sur une combinaison dOMT (Object Modeling Technique) [RBE+ 97] et dun sous-ensemble de Z. A lorigine, OCL a t dvelopp en 1997 par Jos Warmer (IBM), sur les bases du langage IBEL (Integrated Business Engineering Language). Il a t formellement intgr UML 1.1 en 1999. Nous prsentons dans ce document OCL tel quil est propos dans la version UML 2.0 [OMG03a]. Vous trouverez dans [MG00] une prsentation dOCL (UML 1.4) qui a servi de base la ralisation de ce support de cours, et dans [Nyt] quelques exemples complmentaires.

1.3

Principe

La notion de contrainte Une contrainte est une expression valeur boolenne que lon peut attacher nimporte quel lment UML. Elle indique en gnral une restriction ou donne des informations complmentaires sur un modle. Langage dclaratif Les contraintes ne sont pas oprationnelles. On ne peut pas invoquer de processus ni doprations autres que des requtes. On ne dcrit pas le comportement adopter si une contrainte nest pas respecte. Langage sans eet de bord Les instances ne sont pas modies par les contraintes.

1.4

Utilisation

Les contraintes servent dans plusieurs situations : description dinvariants sur les classes et les types pr-conditions et post-conditions sur les oprations et mthodes contraintes sur la valeur retourne par une opration ou une mthode rgles de drivation des attributs description de cibles pour les messages et les actions expression des gardes (conditions dans les diagrammes dynamiques) invariants de type pour les strotypes Les contraintes servent en particulier dcrire la smantique dUML ou de ses diverses extensions, en participant la dnition des prols.

La notion de contexte

Une contrainte OCL est lie un contexte, qui est le type, lopration ou lattribut auquel la contrainte se rapporte. context monContexte <strotype> : Expression de la contrainte
Personne age : entier /majeur : boolen + getAge():entier {query} + setAge(in a : entier)

Fig. 1 Une classe Personne Le strotype peut prendre les valeurs suivantes : inv invariant de classe pre prcondition post postcondition body indique le rsultat dune opration query 2

init indique la valeur initiale dun attribut derive indique la valeur drive dun attribut Par exemple, on peut dnir les contraintes suivantes dans le contexte de la classe Personne de la gure 1, puis dans le contexte de ses mthodes setAge, getAge et pour son attribut age. context Personne inv : (age <= 140) and (age >=0) - - lge est compris entre 0 et 140 ans On peut placer des commentaires dans les expressions OCL, ils dbutent par deux tirets et se prolongent jusqu la n de la ligne. context Personne::setAge(a :entier) pre : (a <= 140) and (a >=0) and (a >= age) post : age = a on peut crire galement a=age context Personne::getAge() :entier body : age context Personne::age :entier init : 0 context Personne::majeur :boolen derive : age>=18 Version visuelle La gure 2 prsente une version alternative, graphique, de la contrainte sur lge de la personne.

Personne age : entier + setAge(in a : entier)

{<<invariant>> (age<=140 and age >=0) }

Fig. 2 Une classe Personne Nommage de la contrainte context Personne inv ageBorn : (age <= 140) and (age >=0) - - lge ne peut depasser 140 ans Utilisation du mot-clef self pour dsigner lobjet Notez le caractre . qui ore la navigation (accs) lattribut. context Personne inv : (self.age <= 140) and (self.age >=0) - - lge ne peut depasser 140 ans

Utilisation dun nom dinstance formel context p :Personne inv : (p.age <= 140) and (p.age >=0) - - lage ne peut depasser 140 ans Question 2.1 Ajoutez un attribut mre de type Personne dans la classe Personne. Ecrivez une contrainte prcisant que la mre dune personne ne peut tre cette personne elle-mme et que lge de la mre doit tre suprieur celui de la personne. Rponse 2.1 context Personne inv : self.mre <> self and self.mre.age > self.age

Types OCL

La gure 3 prsente la hirarchie des types en OCL. Nous les dcrirons progressivement dans cette section et dans les suivantes.
OclAny

OclType OclModelElement Rel

Boolen

String

OclState

Tuple

Collection

types et lments du modle

Entier types de base prdfinis ............ Set OrderedSet Bag Sequence

OclVoid

Fig. 3 La hirarchie des types en OCL

3.1

Types de base

Les types de base prdnis sont les suivants. Entier (Integer) Rel (Real) String Boolen (Boolean) Quelques types spciaux sy ajoutent, en particulier : OclModelElement (numration des lments du modle) OclType (numration des types du modle) OclAny (tout type autre que Tuple et Collection) OclState (pour les diagrammes dtats) OclVoid sous-type de tous les types

Entier oprateurs = <> + - * / abs div mod max min < > <= >= - est unaire ou binaire Rel oprateurs = <> + - * / abs oor round max min < > <= >= - est unaire ou binaire String oprateurs = size() concat(String) toUpper() toLower() substring(Entier, Entier) Les chanes de caractres constantes scrivent entre deux simples quotes : voici une chane Boolen oprateurs = or xor and not b1 implies b2 if b then expression1 else expression2 endif Quelques exemples dutilisation des oprateurs boolens, sur la gure 4.
Personne age : entier majeur : Boolen mari : Boolen catgorie : enum {enfant,ado,adulte}

Fig. 4 La classe Personne prcise context Personne inv : mari implies majeur context Personne inv : if age >=18 then majeur=vrai else majeur=faux endif Cette dernire contrainte peut tre plus concise (nous lavons mme dj crite avec derive) : context Personne inv : majeur = age >=18

prcdence des oprateurs . -> not - unaire */ +if then else < > <= >= <> = and or xor implies

3.2

Types numrs

Leurs valeurs apparaissent prcdes de #. Par exemple, pour donner un invariant supplmentaire pour la gure 4, nous pourrions crire : context Personne inv : if age <=12 then catgorie =#enfant else if age <=18 then catgorie =#ado else catgorie=#adulte endif endif Cet invariant peut aussi scrire avec derive.

3.3

Types des modles

Les types des modles utilisables en OCL sont les classicateurs , notamment les classes, les interfaces et les associations. On peut crire en particulier des expressions impliquant des objets dont les types sont relis par une relation de spcialisation, grce aux oprateurs : oclAsType(t) (conversion ascendante ou descendante de type vers t) ; la conversion ascendante sert pour laccs une proprit rednie ; la conversion descendante sert pour laccs une nouvelle proprit. oclIsTypeOf(t) (vrai si t est supertype direct) oclIsKindOf(t) (vrai si t est supertype indirect) Dans le cadre de la gure 5, nous pourrions crire par exemple les expressions (r est suppos dsigner une instance de Rectangle) : p=r p.oclAsType(Rectangle) r.oclIsTypeOf(Rectangle) (vrai) r.oclIsKindOf(Polygone) (vrai) Question 3.1 En supposant lexistence dun attribut hauteur dans la classe Rectangle et dune mthode hauteur() :Rel dans Polygone, crivez une contrainte dans Polygone disant que le rsultat de hauteur() :Rel vaut hauteur pour les polygones qui sont des rectangles, sinon 0. Remarquez que cest un exemple de mauvaise conception objet mais une excellente illustration des oprateurs prsents ci-dessus !

Polygone p : Polygone r : Rectangle

Rectangle

Fig. 5 Polygones et rectangles Rponse 3.1 context Polygone::hauteur() post : if self.oclIsKindOf(Rectangle) then result=self.oclAsType(Rectangle).hauteur else result=0 endif

4
4.1

Navigation dans les modles


Accs aux attributs

Laccs (navigation) vers un attribut seectue en mentionnant lattribut, comme nous lavons dj vu, derrire loprateur daccs not .
Personne age : Entier + getAge():Entier{query} Voiture propritaire : Personne

Fig. 6 Personnes et voitures Pour la classe Voiture de la gure 6, on peut ainsi crire la contrainte ci-dessous. context Voiture inv propritaireMajeur : self.propritaire.age >= 18

Question 4.1 Ecrivez pour le diagramme de la gure 7 la contrainte qui caractrise lattribut driv carteVermeil. Un voyageur a droit la carte vermeil si cest une femme de plus de 60 ans ou un homme de plus de 65 ans. Rponse 4.1 context Voyageur inv : carteVermeil = ((age >=65) or ((sexe=#fminin) and (age >=60))) Cette contrainte peut galement secrire avec derive. 7

Voyageur nom:String age:int sexe:Sexe / carteVermeil:Boolean

<<enumeration>> Sexe masculin fminin

Fig. 7 Voyageur

4.2

Accs aux oprations query

Il se fait avec une notation identique (utilisation du .). Pour la classe Voiture de la gure 6, on peut ainsi rcrire la contrainte propritaireMajeur. context Voiture inv : self.propritaire.getAge() >= 18

4.3

Accs aux extrmits dassociations

La navigation le long des liens se fait en utilisant : soit les noms de rles soit les noms des classes extrmits en mettant leur premire lettre en minuscule, condition quil ny ait pas ambigut Pour la classe Voiture de la gure 8, on peut ainsi rcrire la contrainte propritaireMajeur.
Personne 1 age : Entier + getAge():Entier{query} propritaire possde * Voiture

Fig. 8 Personnes et voitures (avec association) context Voiture inv : self.propritaire.age >= 18

context Voiture inv : self.personne.age >= 18 Question 4.2 Donnez un exemple o lutilisation du nom de classe conduit une ambigut. Rponse 4.2 Deux associations entre Voiture et Personne (possde et aConduit) Question 4.3 (Exercice tir de [Nyt]) Soient deux contraintes associes au diagramme de la gure 9 : context C1 inv : c2.attr2=c2.c3.attr3 8

C1 attr1:Boolean 0..1 0..*

C2 attr2:Boolean

C3 attr3:Boolean

Fig. 9 Contraintes ... context C2 inv : attr2=c3.attr3 Pensez-vous que les deux contraintes soient quivalentes ? Rponse 4.3 La premire dit que pour des instances de C2 et C3 lies avec une instance de C1 les attributs attr2 et attr3 sont gaux, mais nimpose rien des instances de C2 et C3 non lies une instance de C1 (et il y en a cause de la multiplicit). La deuxime dit que pour tout couple dinstances de C2 et C3 lies, ces deux attributs sont gaux.

4.4

Navigation vers les classes association

Pour naviguer vers une classe association, on utilise le nom de la classe (en mettant le premier caractre en minuscule). Par exemple dans le cas du diagramme de la gure 10 1 : context p :Personne inv : p.contrat.salaire >= 0 Ou encore, on prcise le nom de rle oppos (cest mme obligatoire pour une association rexive) : context p :Personne inv : p.contrat[employeur].salaire >= 0
0..1

emploie

Entreprise
employeur employ

Personne

responsable 0..1

0..1 agentSecrtariat

Contrat typeContrat dateEmbauche salaire

encadre

Encadrement dateDbut valuations

Fig. 10 Emploi Pour naviguer depuis une classe association, on utilise les noms des rles ou de classes. La navigation depuis une classe association vers un rle ne peut donner quun objet. Dans lexemple ci-dessous, c est un lien, qui associe par dnition une seule entreprise un seul employ. context c :Contrat inv : c.employ.age >= 16
en UML 2, contrairement UML 1.xx, le nom de la classe dassociation et le nom de lassociation devraient tre identiques car il sagit dun mme lment UML ; le diagramme est donc ici crit en UML 1.xx
1

Question 4.4 Dans la mme gure 10, exprimez par une contrainte : le fait que le salaire dun agent de secrtariat est infrieur celui de son responsable ; un agent de secrtariat a un type de contrat "agentAdministratif" ; un agent de secrtariat a une date dembauche antrieure la date de dbut de lencadrement (on suppose que les dates sont des entiers) ; crire la dernire contrainte dans le contexte Personne. Rponse 4.4 Le salaire dun agent de secrtariat est infrieur celui de son responsable. context e :encadrement inv : e.responsable.contrat.salaire >= e.agentSecrtariat.contrat.salaire Un agent de secrtariat a un type de contrat "agentAdministratif". context e :encadrement inv : e.agentSecrtariat.contrat.typeContrat=agentAdministratif Un agent de secrtariat a une date dembauche antrieure la date de dbut de lencadrement (on suppose que les dates sont des entiers). context e :encadrement inv : e.agentSecrtariat.contrat.dateEmbauche <= e.dateDebut Lcrire dans le contexte Personne ... context p :Personne inv : p.agentSecrtariat.contrat.dateEmbauche <= p.encadrement[agentSecrtariat].dateDebut Dans ce dernier cas, pour tre rigoureux il faudrait vrier de manire prliminaire que p.agentSecrtariat est valu, mais nous ne verrons que plus loin dans le cours comment faire.

5
5.1

Elments du langage
Dsignation de la valeur antrieure

Dans une post-condition, il est parfois utile de pouvoir dsigner la valeur dune proprit avant lexcution de lopration. Ceci se fait en suxant le nom de la proprit avec @pre. Par exemple, pour dcrire une nouvelle mthode de la classe Personne : context Personne::feteAnniversaire() pr : age < 140 post : age = age@pre + 1

10

5.2

Dnition de variables et doprations

On peut dnir des variables pour simplier lcriture de certaines expressions. On utilise pour cela la syntaxe : let variable : type = expression1 in expression2 Par exemple, avec lattribut driv impot dans Personne, on pourrait crire : context Personne inv : let montantImposable : Rel = contrat.salaire*0.8 in if (montantImposable >= 100000) then impot = montantImposable*45/100 else if (montantImposable >= 50000) then impot = montantImposable*30/100 else impot = montantImposable*10/100 endif endif L encore, il serait plus correct de vrier tout dabord que contrat est valu. Si on veut dnir une variable utilisable dans plusieurs contraintes de la classe, on peut utiliser la construction def. context Personne def : montantImposable : Rel = contrat.salaire*0.8 Lorsquil est utile de dnir de nouvelles oprations, on peut procder avec la mme construction def. context Personne def : ageCorrect(a :Rel) :Boolen = a>=0 and a<=140 Une telle dnition permet de rcrire la pr-condition de lopration setAge et linvariant sur lge dune personne de manire plus courte. context Personne::setAge(a :entier) pre : ageCorrect(a) and (a >= age) context Personne inv : ageCorrect(age) - - lge ne peut depasser 140 ans

5.3

Retour de mthode

Lobjet retourn par une opration est dsign par result. context Personne::getAge() post : result=age Lorsque la postcondition se rsume dcrire la valeur du rsultat cest donc quivalent lutilisation de body. 11

Question 5.1 Proposez une classe Etudiant, disposant de 3 notes et munie dune opration mention qui retourne la mention de ltudiant sous forme dune chane de caractres. Ecrivez les contraintes et en particulier utilisez le let pour crire la postcondition de mention. Rponse 5.1 context Etudiant::mention() post : let moyenne : Real =(note1+note2+note3)/3 in if (moyenne >= 16) then result=trs bien else if (moyenne >= 14) then result=bien else result=moins bien endif endif

Collections
Collection

Set Ensemble mathmatique

OrderedSet Ensemble mathmatique ordonn

Bag Famille

Sequence Famille ordonne

Fig. 11 Les types de collections

6.1

Types de collections

La gure 11 prsente les cinq types de collections existant en OCL : Collection est un type abstrait Set correspond la notion mathmatique densemble OrderedSet correspond la notion mathmatique densemble ordonn Bag correspond la notion mathmatique de famille (un lment peut y apparatre plusieurs fois) Sequence correspond la notion mathmatique de famille, et les lments sont, de plus, ordonns. On peut dnir des collections par des littraux de la manire suivante : Set { 2, 4, 6, 8 } OrderedSet { 2, 4, 6, 8 } Bag { 2, 4, 4, 6, 6, 8 } Sequence { le, chat, boit, le, lait } Sequence { 1..10 } spcication dun intervalle dentiers Les collections peuvent avoir plusieurs niveaux, il est possible de dnir des collections de collections, par exemple : Set { 2, 4, Set {6, 8 }} 12

6.2

Les collections comme rsultats de navigation

Set On obtient naturellement un Set en naviguant le long dune association ordinaire (ne mentionant pas bag ou seq lune de ses extrmits). Par exemple, pour la gure 10, lexpression self.employ dans le contexte Entreprise est un Set. Bag La gure 12 illustre une navigation permettant dobtenir un Bag : cest le rsultat de lexpression self.occurrence.mot dans le contexte Texte. Cette expression est, par ailleurs, un raccourci pour une notation que nous verrons ci-aprs.
Texte * Occurrence *

1 Mot

Fig. 12 Occurrences de mots dans un texte

OrderedSet On peut obtenir un ensemble ordonn en naviguant vers une extrmit dassociation munie de la contrainte ordonn, par exemple avec lexpression self.personne dans le contexte FileAttente.
FileAttente 0..1 {ordonn} Personne *

Fig. 13 File dattente Sequence On peut obtenir une squence en naviguant vers une extrmit dassociation munie de la contrainte seq, par exemple avec lexpression self.mot dans le contexte Texte de la gure 14.
Texte {seq} * Mot

Fig. 14 Une autre reprsentation des textes Question 6.1 Quobtient-on en accdant un attribut multi-valu ? Rponse 6.1 (Question 6.1) On obtient un bag si une valeur peut tre rpte plusieurs fois ; une squence si les valeurs sont de plus ordonnes ; un set sil ny a jamais de doublon dans les valeurs ; un orderedSet si les valeurs sont de plus ordonnes.

13

6.3

Oprations de Collection

Notez que les langages de transformation de modles qui voient le jour actuellement disposent doprateurs assez semblables ceux proposs par OCL, des ns de parcours des modles. 6.3.1 Remarques gnrales

Dans la suite, nous considrons des collections dlments de type T. Appel Les oprations sur une collection sont gnralement mentionnes avec -> Itrateurs Les oprations qui prennent une expression comme paramtre peuvent dclarer optionnellement un itrateur, par exemple toute opration de la forme operation(expression) existe galement sous deux formes plus complexes. operation(v | expression-contenant-v) operation(v : T | expression-contenant-v) 6.3.2 Oprations sur tous les types de collections

isEmpty() :Boolean notEmpty() :Boolean Permettent de tester si la collection est vide ou non. Ils servent en particulier tester lexistence dun lien dans une association dont la multiplicit inclut 0. Pour revenir sur lexemple des employs (dernire question) : context p :Personne inv : p.agentSecretariat->notEmpty() implies p est un responsable p.agentSecrtariat.contrat.dateEmbauche <= p.encadrement[agentSecrtariat].dateDebut size() :Entier Donne la taille (nombre dlments). count(unObjet :T) :Entier Donne le nombre doccurrences de unObjet. sum() :T Addition de tous les lments de la collection (qui doivent supporter une opration + associative) Nous pouvons par exemple dnir une variable reprsentant lge moyen des employs dune entreprise. context e :Entreprise def : ageMoyen : Real = e.employ.age->sum() / e.employ.age->size() Ou encore, pour une classe Etudiant gnralise, disposant dun attribut notes :Real[*], on peut dnir la variable moyenne. context e :Etudiant def : moyenne : Real = e.notes->sum() / e.notes->size() 14

includes(o :T) :Boolean excludes(o :T) :Boolean Retourne vrai (resp. faux) si et seulement si o est (resp. nest pas) un lment de la collection. Toujours pour la classe Etudiant gnralise, disposant dun attribut notes :Real[*], on peut dnir lopration estElimin() :Boolean. Un tudiant est limin sil a obtenu un zro. context e :Etudiant def : estElimin() : Boolean = e.notes->includes(0) includesAll(c :Collection(T)) :Boolean excludesAll(c :Collection(T)) :Boolean Retourne vrai (resp. faux) si et seulement si la collection contient tous les (resp. ne contient aucun des) lments de c. forAll(uneExpression :Boolean) :Boolean Vaut vrai si et seulement si uneExpression est vraie pour tous les lments de la collection. Dans une entreprise, une contrainte est que tous les employs aient plus de 16 ans. context e :Entreprise inv : e.employe->forAll(emp :Personne | emp.age >= 16) Cette opration a une variante permettant ditrer avec plusieurs itrateurs sur la mme collection. On peut ainsi parcourir des ensembles produits de la mme collection. forAll(t1,t2 :T | expression-contenant-t1-et-t2) En supposant que la classe Personne dispose dun attribut nom, on peut admettre que deux employs dirents nont jamais le mme nom. context e :Entreprise inv : e.employe->forAll(e1,e2 :Personne | e1 <> e2 implies e1.nom <> e2.nom) exists(uneExpression :Boolean) Vrai si et seulement si au moins un lment de la collection satisfait uneExpression. Dans toute entreprise, il y a au moins une personne dont le contrat est de type "agent administratif". context e :Entreprise inv : e.contrat->exists(c :Contrat | c.typeContrat=agent administratif) iterate(i :T ; acc :Type = uneExpression | ExpressionAvecietacc) : Cette opration permet de gnraliser et dcrire la plupart des autres. i est un itrateur sur la collection acc est un accumulateur initialis avec uneExpression Lexpression ExpressionAvecietacc est value pour chaque i et son rsultat est aect dans acc. Le rsultat de iterate est acc. Cette opration permet dans lexemple ci-dessous de caractriser le rsultat dune hypothtique opration masseSalariale dune entreprise. 15

context Entreprise::masseSalariale() :Real post : result = employ->iterate(p :Personne ; ms :Real=0 | ms+p.contrat.salaire) Question 6.2 Ecrire size et forAll dans le contexte de la classe Collection. Rponse 6.2 (Question 6.2) Voici comment ces mthodes sont spcies dans [OMG01]. context Collection : :size() post : result = self->iterate(elem ; acc :Integer=0| acc+1) context Collection : :forAll(expr) post : result = self->iterate(elem ; acc :Boolean=true| acc and expr) isUnique(uneExpression :BooleanExpression) :Boolean Vrai si et seulement si uneExpression svalue avec une valeur distincte pour chaque lment de la collection. sortedBy(uneExpression) :Sequence Retourne une squence contenant les lments de la collection tris par ordre croissant suivant le critre uneExpression. Lvaluation de uneExpression doit donc supporter lopration <. Question 6.3 Ecrire la post condition dune mthode salarisTris dans le contexte de la classe Entreprise. Cette mthode retourne les employs ordonns suivant leur salaire. Rponse 6.3 (Question 6.3) context Entreprise : : salariesTries() :OrderedSet(Personne) post : result = self.employe->sortedBy(p | p.contrat.salaire)

any(uneExpression :OclExpression) :T Retourne nimporte quel lment de la collection qui vrie uneExpression. one(uneExpression :OclExpression) :Boolen Vrai si et seulement si un et un seul lment de la collection vrie uneExpression. 6.3.3 Oprations sur tous les types de collections, dnies spciquement sur chaque type

Le lecteur doit tre averti du fait que la prsentation des oprateurs propose ci-dessous privilgie la concision de lexpos. Certaines oprations ont des signatures plus prcises que celles mentionnes ici. Par exemple select, commune aux trois types de collection concrets, nest pas dnie dans Collection, mais seulement dans les types concrets avec des signatures spciques : 16

select(expr select(expr select(expr select(expr

:BooleanExpression) :BooleanExpression) :BooleanExpression) :BooleanExpression)

: : : :

Set(T) OrderedSet(T) Bag(T) Sequence(T)

Dans un tel cas, nous prsentons une gnralisation de ces oprations select(expr :BooleanExpression) : Collection(T) Le lecteur est renvoy la documentation OCL [OMG03a] pour les signatures prcises. select(expr :BooleanExpression) : Collection(T) reject(expr :BooleanExpression) : Collection(T) Retourne une collection du mme type construite par slection des lments vriant (resp. ne vriant pas) expr. Lexpression reprsentant dans le contexte dune entreprise les employs gs de plus de 60 ans serait la suivante : self.employ->select(p :Personne|p.age>=60) collect(expr :BooleanExpression) : Collection(T) Retourne une collection compose des rsultats successifs de lapplication de expr chaque lment de la collection. La manire standard datteindre les mots dun texte scrit ainsi dans le contexte dun texte (Figure 12) : self.occurrence->collect(mot) self.occurrence->collect(o | o.mot) self.occurrence->collect(o :Occurrence | o.mot) Comme nous lavons voqu prcdemment, cette notation admet un raccourci : self.occurrence.mot including(unObjet :T) :Collection(T) excluding(unObjet :T) :Collection(T) Retourne une collection rsultant de lajout (resp. du retrait) de unObjet la collection. On peut ainsi dcrire la post-condition dune opration embauche(p :Personne) de la classe Entreprise. context Entreprise : :embauche(p :Personne) post : self.employ=self.employ@pre->including(p) opration = union(c :Collection) :Collection

17

6.4

Oprations de conversion

Chaque sorte de collection (set, orderedSet, sequence, bag) peut tre transforme dans nimporte quelle autre sorte. Par exemple un Bag peut tre transform en : sequence par lopration asSequence() :Sequence(T) ; lordre rsultant est indtermin ensemble par lopration asSet() :Set(T) ; les doublons sont limins ensemble ordonn par lopration asOrderedSet() :OrderedSet(T) ; les doublons sont limins ; lordre rsultant est indtermin. A titre dillustration, si nous voulons exprimer le fait que le nombre de mots dirents dun texte est plus grand que deux (gure 12) : context Texte inv : self.occurrence->collect(mot)->asSet()->size() >= 2

6.5

Oprations propres Set et Bag

intersection

6.6

Oprations propres OrderedSet et Sequence

ajout dun objet la n append(unObjet : T) : OrderedSet(T) pour les ensembles ordonns append(unObjet : T) : Sequence(T) pour les squences ajout dun objet au dbut prepend(unObjet : T) : OrderedSet(T) pour les ensembles ordonns prepend(unObjet : T) : Sequence(T) pour les squences objets dun intervalle subOrderedSet(inf :Entier, sup :Entier) : OrderedSet(T) pour les ensembles ordonns subSequence(inf :Entier, sup :Entier) : Sequence(T) pour les squences at(inf :Entier) : T first() : T last() : T insertion dun objet un certain indice insertAt(i :Integer, o :T) : OrderedSet(T) pour les ensembles ordonns insertAt(i :Integer, o :T) : Sequence(T) pour les squences indexOf(o :T) : Integer Question 6.4 Ecrire la post-condition de sortedBy

6.7

Relation de conformance de type

La gure 15 prsente les relations de conformance de type prvues en OCL. Si la classe Assiette est sous-classe de Vaisselle, on peut en dduire : 18

Collection(X)

Type2

Set(Type2)

Soustypes

Soustypes

Soustypes

Set(X)

OrderedSet(X)

Bag(X)

Sequence(X)

Type1

Set(Type1)

Fig. 15 Sous-typage de types paramtrs Set(Assiette) se conforme Collection(Assiette) Set(Assiette) se conforme Set(Vaisselle) Set(Assiette) se conforme Collection(Vaisselle) OCL parle mme de relation de sous-typage. Nous tudions la question de la substituabilit sur un bref exemple qui peut tre gnralis et qui illustre le fait que, les collections tant constantes, la conformance rejoint ici la substituabilit. Prenons le cas dun Set(Assiette). Considr comme un Set(Vaisselle), on peut lui appliquer lopration including(object :Vaisselle) :Set(Vaisselle) o object peut tre tout fait autre chose quune assiette. Ce faisant on cre et retourne un Set(Vaisselle) (et non un Set(Assiette)), ce qui nest pas problmatique (il ny a pas derreur de type, on na pas introduit un verre dans un ensemble dassiettes).

Utilisation dOCL pour les gardes et les actions

De manire gnrale, OCL est un langage de navigation qui peut tre utilis dans dirents points des diagrammes UML. Nous allons illustrer cet aspect dOCL dans le cadre des diagrammes dtats, pour exprimer des gardes et prciser des actions.

7.1

Gardes

Les gardes sont des expressions boolennes utilises dans le cadre des diagrammes UML bass sur les automates dtat nis : diagrammes dtats et diagrammes dactivits. Elles conditionnent le dclenchement dune transition lors de loccurrence dun vnement. En UML elles sont notes entre crochets. Les diagrammes dtats modlisent le comportement dlments UML (le plus souvent le comportement dune instance dune classe donne). Ils se composent dtats et de transitions. Un tat est un moment de la vie dune instance dtermin par le fait quelle vrie une condition particulire, est en train deectuer une opration ou attend un vnement. Il est reprsent en UML par une bote aux angles arrondis. Une transition reprsente le passage dun tat un autre. Ce passage est dclench par un vnement : une modication (une condition sur linstance devient vraie), lappel dune opration, la rception dun signal asynchrone, la n dune priode de temps. Les gardes sont associes aux transitions, elles sont values lorsquun vnement survient.

19

CompteBancaire * solde : Rel + dposer(m:Rel) + retirer (m:Rel) + fermer()

gre

Banque fraisDcouvert:Rel dcouvertMax:Rel

Fig. 16 Comptes bancaires La gure 17, tire de [OMG00], prsente un diagramme dtats simple pour un compte bancaire dont le diagramme de classes est dcrit sur la gure 16. Un compte bancaire peut avoir deux tats, ouvert ou ferm. Il passe de ltat ouvert ltat ferm lorsque lopration fermer() est appele sur lobjet. Il reste dans ltat ouvert lorsque deux oprations, respectivement dposer et retirer sont appeles. La garde qui suit lopration retirer indique que cette dernire na deet que si le montant retir est positif et infrieur au solde du compte auquel on ajoute une somme reprsentant le dcouvert autoris.
dposer(m)

Ouvert

fermer()

Ferm

retirer(m) [m<=solde+banque.dcouvertMax and m>=0]

Fig. 17 Etats principaux dun compte bancaire

7.2

Actions

OCL peut tre utilis galement dans la description dactions qui tiquettent les transitions. Ces actions prennent place dans ltiquette derrire le symbole /. Dans ce cas on se sert dOCL comme dun langage de navigation, mais on ncrit pas forcment une expression boolenne. La gure 18 dcrit ainsi les sous-tats de Ouvert. Un compte ouvert est dbiteur ou crditeur. Tout dpt sur un solde dbiteur entrane le retrait dune somme forfaitaire pour frais de gestion des dcouverts. Le retrait est impossible sur un compte dbiteur. Dans la situation o le compte est crditeur, un retrait dune somme suprieure au solde sans dpassement du dcouvert autoris fait passer le compte dans ltat dbiteur. Inversement, lorsque le compte est dbiteur, le dpt dune somme suprieure au dbit (augment des frais de dcouvert) fait passer le compte dans ltat crditeur. Les actions sont exprimes laide du symbole := et dexpressions de navigation en OCL, comme par exemple laccs lattribut fraisDcouvert. 20

Le diagramme dtats tant naturellement dcrit pour une instance dune classe (compte bancaire), ces expressions de navigation sont crites comme si nous nous trouvions dans context CompteBancaire.
Ouvert retrait(m) [m<=solde and m>=0] / solde := solde m

retirer(m) [m > solde and m<=solde+dcouvertMax] / solde := solde m Dbiteur dposer(m) [m>=abs(solde+banque.fraisDcouvert)] / solde := solde+m banque.fraisDcouvert

Crditeur

dposer(m) [m<abs(solde+banque.fraisDcouvert) and m>=0] / solde := solde +m banque.fraisDcouvert

dposer(m) [m>=0] / solde := solde+m

Fig. 18 Etat ouvert dun compte bancaire Alternativement ou paralllement, une partie des informations portes sur le diagramme dtats peut apparatre dans le diagramme de classes. La gure 19 prsente ainsi des prcisions sur le diagramme de la gure 16. Les contraintes OCL sont prsentes de manire graphique dans des notes. Ltat apparat comme un attribut (tatSolde) de la classe CompteBancaire. Les gardes du diagramme dtats correspondent dans le diagramme de classes des prconditions ou des conditions dans la post-condition, tandis que les actions sont associes lcriture de la post-condition. Cet exemple doit aussi nous inviter rchir au problme de la cohrence entre diagrammes. En eet, les informations que portent le diagramme dtats et le diagramme de classes se doivent dtre en accord.

OCL dans le mta-modle UML

Dans la premire partie du cours, nous avons abord le mta-modle UML qui est une description du langage dexpression des modles. La description du mta-modle utilise le mme formalisme que celle des modles. Les lments du mta-modle sont les mta-classes dcrivant les classes, les attributs, les associations, les oprations, les composants : Class, Attribute, Operation, etc. Les lments dun modle sont des instances de ces mtaclasses. Dans la documentation qui dcrit le mta-modle UML, les contraintes sont utilises pour prciser des invariants sur les mta-classes et notamment pour dcrire des extensions du mta-modle laide de strotypes. Notez cependant que ces rgles ne dcrivent pas toute la smantique UML. Une partie de cette smantique reste crite en langue naturelle, et une partie nest pas dcrite du tout. Dans cette partie nous allons en donner quelques exemples lis aux proprits, la relation de spcialisation/gnralisation, aux associations et enn aux contraintes.

21

{<<invariant>> (solde<0 and tatSolde=#dbiteur) or (solde>=0 and tatSolde=#crditeur)}

CompteBancaire solde : Rel tatSolde : enum{crditeur,dbiteur} + dposer(m:Rel) + retirer (m:Rel) + fermer() * gre 1

Banque fraisDcouvert:Rel dcouvertMax:Rel

{<<prcondition>> m>=0 <<postcondition>> if (tatSolde@pre=#crditeur) then solde =solde@pre+m else tatSolde@pre=#dbiteur (m > abs(Solde) implies tatSolde=#crditeur) ( and solde=solde@pre+mbanque.fraisDcouvert }

Fig. 19 Comptes bancaires dtaills Le document utilis est [OMG03b]. Nous ajoutons la partie context pour plus de clart.

8.1

Contraintes sur les proprits

Rgle 8.1 Quelques contraintes tablissent des rgles sur la multiplicit (Figure 10 du mta-modle [OMG03b]). context MultiplicityElement inv : lower = lowerBound() lowerBound()->notEmpty() implies lowerBound() >= 0 lowerBound()->notEmpty() and upperBound()->notEmpty() implies upperBound() >= lowerBound()

context MultiplicityElement : :lowerBound() : Integer inv : result=if lowerValue->isEmpty() then 1 else lowerValue().integerValue() endif upperBound() est dnie de manire similaire.

8.2

Contraintes sur la spcialisation/gnralisation

Nous montrons tout dabord comment les super-classes directes dune classe sont obtenues (gure 22 dans [OMG03b]). context Classier::parents() :Set(Classier) post : result = self.generalization.parent 22

Cette opration se gnralise facilement pour obtenir toutes les superclasses dune classe. context Classier::allParents() :Set(Classier) post : result = self.parents()->union(self.parents()->collect(p | p.allParents())) Rgle 8.2 La relation de spcialisation/gnralisation ne peut induire un circuit. context Classier inv : not self.allParents() -> includes(self )

8.3

Contraintes sur les associations

Les associations sont dcrites dans la gure 30 du document [OMG03b]. Rgle 8.3 endType est driv partir des types des memberEnd context Association inv : self.endType = self.memberEnd -> collect(e | e.type) La multiplicit dans une composition ne peut dpasser 1. context Property inv : isComposite implies (upperBound()->isEmpty() or upperBound() <= 1)

8.4

Contraintes sur les contraintes

Daprs le diagramme 14 du mta-modle UML [OMG03b]. Rgle 8.4 Une contrainte ne peut pas sappliquer elle-mme. context Constraint inv : not constrainedElement->include(self )

Sur ce diagramme, nous voyons apparatre une limitation dOCL dans lexpression des contraintes. La smantique voudrait notamment que : la spcication de valeur pour une contrainte soit de type boolen ; lvaluation dune contrainte ne devrait pas avoir deet de bord. Daprs la documentation, ces deux contraintes ne peuvent tre exprimes en OCL.

23

Rfrences
[CD94] Steve Cook and John Daniels. Designing Object Systems : Object-Oriented Modelling with Syntropy. Prentice Hall, http ://www.syntropy.co.uk/syntropy/, 1994. ISBN 0-13203860-9. Pierre-Alain Muller and Nathalie Gaertner. Modlisation objet avec UML. Eyrolles, 2000. Jan Pettersen Nytun. OCL, The Object Constraint Language. Slides. http :// fag.grm.hia.no/ ikt2340/ year2002/ themes/ executableUML/ executableUML.html. OMG. Unied modeling language v1.3. Technical report, Object Management Group, 2000. UML Semantics. OMG. Unied modeling language v1.4. Technical report, Object Management Group, 2001. chap. 6 - Object Constraint Language Specication.

[MG00] [Nyt]

[OMG00] [OMG01]

[OMG03a] OMG. Uml 2.0 ocl specication. Technical report, Object Management Group, 2003. ptc/03-10-14. [OMG03b] OMG. Uml 2.0 superstructure specication. Technical report, Object Management Group, 2003. ptc/03-08-02. [RBE+ 97] James Rumbaugh, Michel Blaha, Frederick Eddy, William Premerlani, and W. Lorensen. OMT, Modlisation et conception orientes objet. MASSON, 1997. Edition franaise.

24