• Aucun résultat trouvé

4.2 D´ efinitions d’attributs

4.2.1 Langage

4.2.1.2 D´ efinition d’attribut non cl´ e

Acquire(bId , ) : bookKey(front (s))∪{bId }, Discard(mId ) : bookKey(front (s))−{bId },

: bookKey(front (s)) ;

La fonction bookKey a un unique param`etre d’entr´ee s ∈ T (main), o`u T (main) repr´esente l’ensemble des traces accept´ees par le processus main, et elle retourne l’ensemble des valeurs de cl´e de book . Informellement, cela signifie que si la trace est vide (last (s) = ⊥), alors : bookKey = ∅. Si le dernier ´ev´enement de la trace est Acquire, alors bId est ajout´e `a l’ensemble bookKey calcul´e r´ecursivement sur front (s). De mani`ere analogue, bId est supprim´e de bookKey(front (s)) lorsque le dernier ´ev´enement de la trace est Discard. Enfin, si last (s) ne correspond `

a aucun de ces cas, alors la fonction bookKey est appel´ee r´ecursivement sur front (s), par la derni`ere clause avec le symbole “ ”. L’ex´ecution d’une telle fonction est d´etaill´ee dans la section4.2.2.

Soit asc une association l -aire entre l types d’entit´e e1, . . . , el. Par d´efinition, la cl´e d’une association asc est form´ee avec les cl´es des types d’entit´e correspon-dants. Pour chaque j ∈ {1, 2, . . . , l }, on note k1j, . . . , kj

mj les attributs cl´e du type d’entit´e ej. La cl´e de asc est alors d´efinie par l’ensemble de tous les attributs cl´e des types d’entit´e e1, . . . , el :

asc : T (main) → F(Tk1

1× · · · ×Tk1

m1× · · · ×Tkl

1× · · · ×Tkl ml) Par exemple, la cl´e de l’association reservation est de type :

reservation : T (main) → F(bookKey Set×memberKey Set)

Lorsque la cardinalit´e de l’association est 0..1 ou 1, la cl´e de l’association est alors plus simple. Les algorithmes de normalisation peuvent ˆetre trouv´es dans [EN04]. Par exemple, la cl´e de l’association loan est de type :

loan : T (main) → F(bookKey Set)

parce que le type d’entit´e member a une multiplicit´e de 0..1 et que le rˆole borrower repr´esente l’unique emprunteur d’un livre.

4.2.1.2 D´efinition d’attribut non cl´e

La fonction r´ecursive associ´ee `a un attribut non cl´e, appel´ee d´efinition d’at-tribut non cl´e, retourne la valeur de l’attribut pour la cl´e et la trace donn´ees en param`etre. La fonction d’un attribut non cl´e bi d’un type d’entit´e ou d’une association est de type :

bi : T (main)×T1× · · · ×Tm → Ti

o`u T1, . . . , Tmsont les types des attributs cl´e du type d’entit´e ou de l’association et le codomaine Ti est le type de l’attribut non cl´e bi. Le codomaine d’une d´efinition d’attribut non cl´e peut inclure ⊥, afin de repr´esenter le fait qu’un

4.2. D ´EFINITIONS D’ATTRIBUTS 85 attribut n’est pas d´efini. Par exemple, le type de la fonction associ´ee `a l’attribut nbLoans est :

nbLoans : T (main) × memberKey Set → N

Dans ce cas, la fonction est totale, car nbLoans est d´efini pour tous les membres de la biblioth`eque.

La d´efinition d’un attribut non cl´e bi a la forme suivante : bi (s : T (main),−→

k : T1× · · · ×Tm) : Ti

= match last (s) with

⊥ : u0, a1(−→p 1) : u1, . . . an(−pn) : un, : bj(front (s),−→ k ) ; (4.2)

o`u bj est un attribut (j peut ˆetre ´egal `a i ). L’expression −→

k repr´esente la liste des attributs cl´e. Les expressions u0, . . . , un sont soit des termes fonctionnels, soit des termes conditionnels. Pour chaque clause d’entr´ee, on a : var (uj) ⊆ var (−→p

j) ∪ var (−→ k ).

Pour les d´efinitions d’attributs non cl´e, un terme fonctionnel de l’expression uj prend l’une des formes suivantes :

– ⊥, soit une valeur ind´efinie pour l’attribut,

– c, une constante de type Ti, qui repr´esente une valeur d’attribut, – v , une variable de var (−→p

j) ∪ var (−→ k ), – g(−→

t ), o`u chaque tit est un terme fonctionnel et g est soit un attribut, soit un op´erateur sur un ou plusieurs types d’attribut.

La derni`ere expression, g(−→

t ), permet de d´efinir des appels r´ecursifs de bi ou des appels d’autres d´efinitions d’attributs. Une r´ef´erence `a une cl´e eKey ou `a un attribut b dans une clause d’entr´ee est toujours de la forme eKey(front (s)) ou b(front (s), ...). De plus, les op´erateurs utilis´es doivent respecter les types des expressions uj.

Par exemple, l’attribut non cl´e nbLoans est d´efini par la fonction suivante : nbLoans(s : T (main), mId : memberKey Set ) : N =

match last (s) with ⊥ : ⊥,

Register(mId , ) : 0,

Lend( , mId , ) : 1 + nbLoans(front (s), mId ), Return(bId ) : if mId = borrower (front (s), bId )

then nbLoans(front (s), mId ) − 1 end, Transfer(bId , mId0, ) : if mId = mId0

then nbLoans(front (s), mId ) + 1 else if mId = borrower (front (s), bId )

then nbLoans(front (s), mId ) − 1 end

end,

Take( , mId , ) : 1 + nbLoans(front (s), mId ), Unregister(mId ) : ⊥,

Cette d´efinition utilise deux termes conditionnels, dans les clauses Return et Transfer. Si les principes d’ex´ecution des d´efinitions d’attributs sont d´etaill´es dans la section 4.2.2, nous pr´esentons maintenant une premi`ere explication, informelle, de l’´evaluation de ces termes conditionnels. La fonction nbLoans a pour param`etre d’entr´ee un membre mId . Le motif Return(bId ) ne permet pas de caract´eriser le membre concern´e par cet ´ev´enement. Dans ce cas, le pr´edicat du terme conditionnel indique quel est le membre dont le nombre de prˆets diminue d’une unit´e : il s’agit de l’emprunteur de bId . De mˆeme, le motif Transfer(bId , mId0, ) n’est pas suffisant pour d´eterminer le ou les membres mId concern´es par cet ´ev´enement. En fait, deux membres distincts sont caract´eris´es par les pr´edicats du terme conditionnel :

– le membre qui fait le transfert : borrower (front (s), bId ), – et le membre qui profite du transfert : mId0.

L’ex´ecution d’un ´ev´enement de la forme Transfer(bId , mId0, ) a pour effet de d´ecr´ementer d’une unit´e le nombre de prˆets (nbLoans) du membre qui fait le transfert et d’incr´ementer d’une unit´e le nombre de prˆets du membre mId0.

Les termes conditionnels sont ´egalement utilis´es lorsque la valeur d’un ou plusieurs param`etres d´etermine la valeur de l’attribut. Par exemple, l’attribut dueDate de l’association loan permet de repr´esenter la date de retour d’un prˆet. On suppose que la date de retour d´epend du type de prˆet : a) s’il est de type “Classic”, alors le prˆet dure le d´elai pr´evu pour le membre, qui est indiqu´e par l’attribut loanDuration du type d’entit´e member ; b) s’il est de type “Permanent ”, alors le prˆet dure une ann´ee. Ce type de prˆet est pr´ecis´e comme param`etre des actions Lend, Transfer et Take. La d´efinition d’attribut de dueDate peut ˆetre sp´ecifi´ee en eb3par la fonction suivante :

dueDate(s : T (main), bId : bookKey Set ) : DATE = match last (s) with

⊥ : ⊥,

Lend(bId , , Permanent ) : CurrentDate+365,

Lend(bId , mId , Classic) : CurrentDate+loanDuration(front (s), mId ), Return(bId ) : ⊥,

Transfer(bId , mId , type) : if type = Permanent then CurrentDate+365 else CurrentDate

+loanDuration(front (s), mId ) end,

Take(bId , , Permanent ) : CurrentDate+365,

Take(bId , mId , Classic) : CurrentDate+loanDuration(front (s), mId ), : dueDate(front (s), bId ) ;

Dans l’exemple ci-dessus, on remarque qu’il existe plusieurs fa¸cons de sp´ecifier les hypoth`eses sur les param`etres d’action comme dans le cas du type de prˆet. D’un cˆot´e, on peut sp´ecifier autant de clauses d’entr´ee qu’il y a de valeurs pour le param`etre comme, par exemple, pour les actions Lend et Take. Dans ce cas, l’analyse des clauses d’entr´ee se fait dans l’ordre qu’elles sont indiqu´ees (voir section4.2.2). D’un autre cˆot´e, il est possible d’utiliser des termes condi-tionnels pour consid´erer les diff´erentes valeurs possibles du param`etre d’action. Cette option est illustr´ee par la clause Transfer. Pour faciliter l’analyse des clauses d’entr´ee lors de l’´evaluation des d´efinitions d’attributs, on se ram`enera de pr´ef´erence `a la deuxi`eme option avec les termes conditionnels. Le passage

4.2. D ´EFINITIONS D’ATTRIBUTS 87

e

1

r

*2

r

1*

e

2

Fig. 4.2 – Rˆoles d’une association de type M : N

e

1

r

12

r

1*

e

2

Fig. 4.3 – Rˆoles d’une association de type 1 : N

d’une ´ecriture `a l’autre se fait ais´ement. Par exemple, dans le cas de la clause Take, il suffit de d´eterminer les diff´erentes valeurs du troisi`eme param`etre et de les retranscrire dans un terme conditionnel :

Take(bId , mId , type) : if type = Permanent then CurrentDate+365 else if type = Classic

then CurrentDate

+loanDuration(front (s), mId ) else dueDate(front (s), bId )

end end,

Pour le nom du param`etre, on utilise celui indiqu´e dans la signature de l’action. En r´esum´e, les termes conditionnels sont principalement utilis´es dans trois cas :

– lorsque le filtrage n’est pas suffisant pour lier les param`etres d’entr´ee de la fonction r´ecursive aux valeurs effectives des motifs (exemple : clause Return dans nbLoans),

– lorsque plusieurs valeurs de cl´e sont concern´ees par le mˆeme motif (exem-ple : Transfer dans nbLoans),

– lorsque l’´evaluation d’un attribut d´epend de la valeur d’un ou plusieurs param`etres d’une action (exemple : Transfer dans dueDate).