Upload
sylvain-landais
View
113
Download
0
Tags:
Embed Size (px)
1
O.C.L.
Object Constraint Language
Françoise Schlienger
FIIFO4 2004-2005
2
O.C.L. : Object Constraint Language
Langage formel de description des contraintes d'UML, standardisé par l'OMG.
C'est un langage de spécification et non un langage de programmation.
Il permet :
• de modéliser de manière plus précise
• de mieux documenter un modèle
• de rester indépendant de l'implémentation• d'identifier les responsabilités de chaque composant.
Biblio : The Object Constraint Language : getting your models ready for MDA (Model Driven Architecture), Jos Warmer, Anneke Kleppe, (Août 2003)
3
Différentes sortes de contraintes
• Les invariants de classe ou de type :contraintes (expressions booléennes, sans effet de bord) qui doivent être
respectées par toutes les instances de la classe ou du type concerné.
• Les pré- et post-conditions :contraintes qui doivent être respectées respectivement avant ou après
l'exécution d'une opération.
4
Les stéréotypes de contraintes
« invariant » auquel est associé le mot clé inv
« pré-condition » auquel est associé le mot clé pre
« post-condition » auquel est associé le mot clé post
5
Contexte
Chaque contrainte OCL est liée à un contexte définissant l'élément de modélisation auquel la contrainte se rapporte.
Une expression OCL est de la forme :
context nom de l'élément de modélisation concerné inv | pre | post.
Exemple : context Pile inv :
NbEléments>=0
Cette contrainte s’applique à tous les éléments de la classe.
Représentation graphique :
Pile
<<invariant>>
{NbEléments>=0}
Elément
/-NbEléments : integer
+Ajouter(In Elem:Elément)+Retirer()
SesEléments
0..1*
6
Le mot clé : self
Il sert à identifier l’instance contextuelle à laquelle la contrainte se rapporte :
context Pile inv :
self.NbEléments>=0
A la place du mot self, il est possible d’écrire un nom d’instance.
context p : Pile inv :
p.NbEléments>=0
Les 2 expressions sont équivalentes à :
context Pile inv :
NbEléments>=0
7
Attribut d’instance - Attribut de classe
Pour les 2 on utilise la notation pointée.
Attribut d’instance :
context Pile inv :
self.NbEléments>=0
Attribut de classe :
context Pile inv:
self.NbEléments<Pile.NbMax
<<invariant>>{NbElements>=0}{NbElements<Pile.NbMax}
Pile
/-NbEléments : integerNbMax : integer
+Ajouter(In Elem:Elément)+Retirer()
8
Les collections
OCL permet de gérer 3 types de collections.
Set : ensemble non ordonné, sans répétition• résultat d’une navigation• {C1, C2, C3}
Bag: multi-ensemble non ordonné, répétitions possibles• navigations combinées• {P1,P2,P3,P1,P6,P2}
Séquence : ensemble ordonné, répétitions possibles• navigation à travers un rôle ordonné
{ordered}
Pas de collection de collections : mise à plat automatique.
Client Commande1 *
Client Commande Produit1 * * *
9
Opérations prédéfinies sur les collections (1)
cisEmpty() : booléen retourne vrai si la collection c est vide.
cnotEmpty() : booléen retourne vrai si la collection c n’est pas vide.
csize() : entier retourne le nombre d’éléments de la collection c.
ccount(elem) : entier retourne le nombre de fois où elem apparaît dans la collection c.
csum() : T retourne la somme des éléments appartenant à la collection c.
cselect(cond) : retourne un sous-ensemble de la collection c dont chaque élément respecte la condition (cond) passée en paramètre.
creject(cond) : retourne un sous-ensemble de la collection c dont chaque élément ne respecte pas la condition (cond) passée en paramètre.
10
Opérations sur les collections (exemples)
unService.SesEmployés représente la collection des employés de unService unService.SesEmployés isEmpty () retourne vrai si unService n’a pas d’employé.
unService.SesEmployés size() retourne le nombre d’employés de unService.
SERVICE PERSONNES
NomPrénomNbEnfants
1*
SesEmployés
11
Opérations prédéfinies sur les collections (2)
ccollect(cond) : retourne une collection dérivée de la collection c dont chaque élément respecte la condition passée en paramètre. Le résultat est un « bag » (multi-ensemble non ordonné, répétitions possibles).
On veut savoir quel est le nombre total d’enfants des employés d’un service :
unService.SesEmployés collect (P : Personne | P.nbEnfants)ou unService.SesEmployés collect (P | P.nbEnfants)ou unService.SesEmployés collect (nbEnfants)
Notation abrégée :unService.SesEmployés.nbEnfants notation utilisée par la suite
On peut alors calculer le nombre total d’enfants des employés d’un service unService.SesEmployés.nbEnfants sum ()
12
Opérations sur les collections (exemples)
unService.SesEmployés.Prénom count(« Jean ») retourne le nombre de personnes prénommées « Jean »
unService.SesEmployés.NbEnfants sum() retourne le nombre total des enfants de tous les employés de unService
SERVICE PERSONNES
NomPrénomNbEnfants
1*
SesEmployés
13
Opérations sur les collections (exemples)
Sous ensemble des Employés de unService dont l’age est > 50 : (3 solutions équivalentes)
unService.SesEmployés select (p : Personne | p.age >50)ou unService.SesEmployés select (p | p.age >50)ou unService.SesEmployés select (age >50)
On peut combiner les opérations :
Dans l’invariant de la classe SERVICE
context SERVICE inv :self .SesEmployésselect (âge < 25) isEmpty()
signifie que dans chaque service, il n’y a pas d’employé dont l’âge est inférieur à 25 ans.
14
Opérations prédéfinies sur les collections (3)
cincluding(elem) : retourne la collection c en incluant elem.
cexcluding(elem) : retourne la collection c en excluant elem.
cincludes(elem) : booléen retourne vrai si la collection c inclut elem.
cexcludes(elem) : booléen retourne vrai si la collection c n’inclut pas elem.
cincludesAll(coll) : booléen retourne vrai si la collection c inclut tous les éléments de coll.
cexcludesAll(coll) : booléen retourne vrai si la collection c n’inclut aucun des éléments de coll.
15
Opérations propres aux séquences
sfirst() retourne le premier élément de la séquence s
slast() retourne le dernier élément de la séquence s
sat(i: integer) retourne l’élément en position i de la séquence s
sappend(elem) retourne une séquence contenant tous les éléments de la séquence s,suivi de elem.
sprepend(elem) retourne une séquence contenant elem, suivi de tous les éléments de la séquence s.
16
Quantificateurs : universel et existentiel
cforAll(cond) : retourne vrai si tous les éléments de la collection c respectent la condition passée en paramètre.
Exemple : dans le cas d’une association parent / enfant
Chaque parent d’une personne a bien cette personne comme enfant.
PERSONNE
-Nom-Prénom
0..2SesParents
SesEnfants*
context Personne inv :self.SesParents forAll (p : Personne |
p.SesEnfant includes (self))
ou context Personne inv :self.SesParents forAll (p |
p.SesEnfant includes (self))
ou context Personne inv :self.SesParents forAll (SesEnfant includes (self))
17
Quantificateurs : universel et existentiel
Il est possible de parcourir plusieurs variables à la fois .Exemple :
Les enfants d’une personne ont tous des prénoms différents.
context Personne inv : self.SesEnfantsforAll ( e1, e2 : Personne |
e1<>e2 implies e1.Prénom <>e2.Prénom)
cexists(cond) : retourne vrai si au moins un élément de la collection c respecte la condition passée en paramètre.Dans un groupe d’étudiants, il y a au moins un délégué.
context Groupe inv :self.SesEtudiants exists (e : Personne | e.fonction = ‘ Délégué ’)
18
Unicité
cisUnique(expr) : retourne vrai si pour chaque valeur de la collection c l’expressionexpr retourne une valeur différente.
Exemple :
Les enfants d’une personne ont tous des prénoms différents.context Personne inv : self.SesEnfantsisUnique(Prénom)
Autre manière :
context Personne inv : self.SesEnfantsforAll ( e1, e2 : Personne | e1<>e2 implies e1.Prénom <>e2.Prénom)
19
Dépendance de contraintes
Certaines contraintes sont dépendantes d’autres contraintes.
2 formes existent pour gérer cela.
• if expr1 then expr2 else expr3 endif; Si l’expression expr1 est vraie alors expr2 doit être vraie sinon expr3 doit être vraie.
• expr1 implies expr2Cette expression est validée lorsque l’expression expr1 est évaluée à faux ou lorsque expr1est évaluée à vrai et expr2 est également évaluée à vrai.
20
Dépendance de contraintes : exemple 1
Pour traduire la règle : une personne de moins de 18 ans n’a pas de compte en banque alors qu’une personne de plus de 18 ans possède au moins un compte.
PERSONNE SesTitulaires SesComptes
* *-Nom : string-/Age : integer
Ddn : date
COMPTE
-Numéro : integer
BANQUESesClients
SesBanques
*
*SaBanque
SesCompte
1
*
-Numéro : integer
context Personne inv :if Age < 18then SesComptes isEmpty()else SesComptes notEmpty() endif
21
Dépendance de contraintes : exemple 2
Si une personne possède au moins un compte bancaire, alors elle est cliente d’au moins une banque.
PERSONNECOMPTE
SesTitulaires SesComptes
* *-Nom : string-/Age : integer
Ddn : date
-Numéro : integer
BANQUESesClients
SesBanques
*
*SaBanque
SesCompte
1
*
-Numéro : integer
context Personne inv :SesCompte notEmpty() implies SesBanques notEmpty()
22
Dépendance de contraintes : exemple 3
Si un compte appartient à une banque, son titulaire est client de la banque.
PERSONNECOMPTE
SesTitulaires SesComptes
* *-Nom : string-/Age : integer
Ddn : date
-Numéro : integer
BANQUESesClients
SesBanques
*
*SaBanque
SesCompte
1
*
-Numéro : integer
context Compte inv :self.SaBanque.SesClients includes SonTitulaire
23
Exemple 4
Si une personne a des enfants, alors tous ses enfants
ont bien cette personne comme parent.
PERSONNE
-Nom-Prénom
0..2SesParents
SesEnfants*
context Personne inv :self.SesEnfants notEmpty() implies
SesEnfants forAll (p : Personne | p.SesParents includes (self))
24
Opération définie sur les classes
Classe.allInstances : retourne l ’ensemble des instances de la classe.
Exemple : pour spécifier que le nombre de personnes modélisées dans une classeest inférieur à 500.
context Personne inv :Personne. allInstances size < 500
Pour définir un identifiant :
context Personne inv :Personne. allInstances isUnique(numINSEE)
25
Types énumérés
Ils sont autorisés dans les expressions OCL.La valeur d ’un type énuméré est indiquée en faisant précéder son nom du symbole #
Soit le type énuméré Couleur = {bleu, rouge, noir, blanc}La couleur du stylo est noire sauf lorsque la couleur de fond est noire ; dans ce cas la couleur du stylo sera blanche.
context Feuille inv :if CouleurFond <> #noir then CouleurStylo = #noirelse CouleurStylo = #blancendif
FEUILLE
-CouleurFond : Couleur-CouleurStylo : Couleur
26
Éléments particuliers des pré- et post-conditions
Les pré- et post-conditions :contraintes qui doivent être respectées respectivement avant ou après l'exécution d'une opération.
result référence la valeur retournée par une opération.
Pour désigner la valeur d’une propriété avant l’exécution d’une opération, le terme@pre est post-fixé au nom de la propriété.
O.oclIsNew () retourne vrai si l ’objet O a été créé dans l’opération.
Ces opérateurs ne peuvent être utilisés que dans des post-conditions.
27
Éléments particuliers des pré- et post-conditionsExemple
Dans le cas d’un compte bancaire, sur l’opération débiter() on veut que :avant l ’exécution : la somme à débiter soit strictement positive et après l’exécution : l’attribut solde doit avoir pour valeur la différence de sa valeur avant l’appel et de la somme passée en paramètre.
context Compte :: débiter (somme : integer)pre : somme >Opost : solde = solde@pre - somme
Attention : on ne décrit pas comment l’opération est réalisée mais des contraintes sur l’état avant et après son exécution.Dans un autre cas on pourrait avoir post : solde <= solde@pre - somme
COMPTE
-Numéro : integer
+débiter (somme : integer)
28
Exemple 5
PERSONNE
-Nom-Prénom-Sexe
+NbFilles()
0..2SesParents
SesEnfants*
Spécifier NbFilles qui renvoie un entier correspondant aunombre de filles d’une personne.
ou context Personne :: NbFilles () : entierpost : result = self.SesEnfants select (Sexe = #féminin) size()
ou context Personne :: NbFilles () : entierpost : result = self.SesEnfants
select (fille |fille.Sexe = #féminin) size()
context Personne :: NbFilles () : entierpost : result = self.SesEnfants
select (fille : Personne |fille.Sexe = #féminin) size()
29
Associations qualifiées
AVION
Num : int
* SIEGERangée : entierLettre : caractèreCl : Classe
unAvion.SonSiège [uneRangée, uneLettre] désigne un siège donné de manière non ambiguë
Si dans un avion il y a un siège sur la rangée 13, il est de type ’économique’
Classe :{économique, business}
context Avion inv :forAll (lettre : caractère | self.SonSiège [13, lettre] exists()implies self.SonSiège [13, lettre] . Classe = #économique
AVION
Num : intRangée : entierLettre : caractère
0..1 SIEGECl : ClasseSonSiège
30
Types et sous types de classificateurs
O.oclIsTypeOf (t : oclType) : booléen retourne vrai si le type t est le type direct (pas un super-type) de l ’objet O.
unPoidsLourd.oclIsTypeOf(PoidsLourd) retourne vraiunPoidsLourd.oclIsTypeOf(Véhicule) retourne faux
O.oclIsKindOf (t : oclType) : booléen retourne vrai si le type t est le type direct ou un super-type de l ’objet O.
unPoidsLourd.oclIsKindOf(PoidsLourd) retourne vraiunPoidsLourd.oclIsTypeOf(Véhicule) retourne vrai
O.oclAsType (t : oclType) : objet force l ’objet O à être du type t.Le type t est un sous-type du type de l ’objet O.
unPoidsLourd.oclAsType (Camion) est évalué comme un objet de type Camion
… aux risques et périls de l ’utilisateur.
31
Les variables
Lorsqu ’une expression apparaît plusieurs fois dans une condition, il n ’est pas nécessaire de la réécrire plusieurs fois et une variable peut être définie.
let variable : type = expression in
context Personne inv :let Revenus : integer = self.SesEmplois.Salaire sum() in
if Revenus < Personne.Seuil1 then Etat = #niveau1else if Revenus < Personne.Seuil2
then Etat = #niveau2else Etat = #niveau3endif
endif
PERSONNE
-Nom-Prénom-Seuil1-Seuil2-/Etat
ACTIVITE
-Libellé-Salaire
SesEmplois
32
Exemple 6
P1:PERSONNE
C1:COMPTE
P2:PERSONNE
C2:COMPTE
CB1:CARTE-BLEUE
Nom=Marie
Nom=Paul
Numéro=123456
Numéro=345678
SeTitulairesSesComptes
SesComptes
SesTitulaires
SesTitulaires
SesComptes
Numéro=13579
SonSignataire
SesCartes
SesCartes
SonCompte
PERSONNECOMPTE
SesTitulaires SesComptes
1..4 *-Nom : string
-Numéro : integer
CARTE-BLEUESonSignataire
SesCartes
1
*SesCartes
SonCompte
*
1
-Numéro : integer
33
Pour être plus précis …
PERSONNECOMPTE
CARTE-BLEUE
Titulaires SesComptes
1..4 *
Signataire
SesCartes
1
*SesCartes
SonCompte
*
1-Nom : string
-Numéro : integer
-Numéro : integer
context CARTE-BLEUE inv :self.SonCompte.Titulaires includes(self.signataire)oucontext CARTE-BLEUE inv :SonCompte.Titulaires includes(Signataire)
34