• Aucun résultat trouvé

Le modele des classes formelles

Types Abstraits Graphiques et Classes Formelles

4.5 Le modele des classes formelles

Le modele des classes formelles (CF en abrege) est issu des travaux de Jean-Claude Royer [Roy92, AR92c, Roy93]. C'est une sorte de langage de speci cation de classes, qui est interme- diaire entre les TAA et les classes concretes. Une CF est une speci cation particuliere de TAA. Le modele doit permettre une transition plus facile des TAA vers les classes mais egalement de de nir des regles d'ecriture et des outils inspires des speci cations algebriques. Une semantique algebrique complete est de nie pour la notion de classe. Une semantique operationnelle abs- traite prend en compte l'heritage. L'evaluation symbolique et la preuve de proprietes se font par un mecanisme simple et naturel de reecriture. Ces divers aspects du modele sont decrits dans le chapitre 6. Une CF est un type et l'heritage implique le sous-typage, un contr^ole de type simple mais s^ur est decrit dans la section 6.5.

La conception d'une CF est inspiree de la programmation a objets (noyau/extension). Une CF est de nie par un aspect et des methodes secondaires. L'aspect est l'ensemble susant des methodes (primitives) qui caracterisent un objet: creation, copie, egalite, accesseurs. Les methodes dites secondaires sont des extensions fonctionnelles de ce noyau.

Hospital

inherits from OBJECT

comments: class for hospital

features: init, admit, urgency, cure, number, urgencyNumber, first

param: Patient

from: Integer import: +, 0, 1, =, >, <=

from: Boolean import:

aspect : hospital

eld selectors constraint

size : Hospital ?! Integer

queue : Hospital ?! List[Patient] size(Self) > 1 and urgencyQueue : Hospital ?! List[Patient] number(Self) <= size(Self)

secondary methods

;; isEmpty : the queues are empty isEmpty : Hospital ?! Integer

isEmpty(Self) == empty?(queue(Self)) and empty?(urgencyQueue(Self)) ;; number : number of admitted patient

number : Hospital ?! Integer number(Self) == length(queue(Self)) ;; isFull : the queue is full

isFull : Hospital ?! Integer isFull(Self) == number(Self) = size(Self) ;; urgencyNumber : number of urgency patient

urgencyNumber : Hospital ?! Integer urgencyNumber(Self) == length(urgencyQueue(Self)) ;; isUrgent : the number of urgency patient is not null

isUrgent : Hospital ?! Boolean isUrgent(Self) == urgencyNumber(Self) > 0 ;; first : patient to be examined

first : Hospital ?! Patient

requires: isEmpty(Self) == false

isUrgent(Self) == true ==> first(Self) == head(urgencyQueue(Self)) isUrgent(Self) == false ==> first(Self) == head(queue(Self)) ;; admit : admit a new normal patient

admit : Hospital Patient ?! Hospital

var: p:Patient

requires: isFull(Self) == false

admit(Self, p) == copy(Self, queue = cons(queue(Self), p)) ;; cure : remove first patient

cure : Hospital ?! Hospital

requires: isEmpty(Self) == false

isUrgent(Self) == true ==> cure(Self) == copy(Self, urgencyQueue = tail(urgencyQueue(Self))) isUrgent(Self) == false ==> cure(Self) == copy(Self, queue = tail(queue(Self)))

Hospital ;; urgency : admit a new urgency patient

urgency : Hospital Patient ?! Hospital

var: p:Patient

urgency(Self, p) == copy(Self, urgencyQueue = cons(urgencyQueue(Self), p))

class methods

;; init : open the hospital init : Integer ?! Hospital

var: max:Integer

init(Xmax) == new(Hospital, size = max, queue = new(EmptyList), urgencyQueue = new(EmptyList))

Figure 31 : Conception plate et intuitive de la classe formelleHospital

D'une maniere generale, la conception d'une telle classe se focalise d'abord sur la description des objets (l'aspect) puis sur leur utilisation (les methodes secondaires). Cette pratique est conforme a l'usage de la programmation a objets. Elle a plusieurs avantages: d'une part, c'est une speci cation algebrique particuliere qui sous certaines hypotheses est susamment complete et non-contradictoire et d'autre part, elle veri e la propriete naturelle en programmation a objets que l'ajout d'une nouvelle methode secondaire ne change pas le type des instances. Cette classe a ete concue intuitivement. Nous verrons dans la section suivante une demarche pour construire des classes formelles a partir d'un TAG.

Si globalement une classe formelle est proche d'une classe Ei el plusieurs originalites exis- tent : la proximite avec les speci cations algebriques et tous les outils ou techniques qui s'en inspirent, les preconditions sur les selecteurs de champs, qui sans accro^tre la puissance d'ex- pression du langage permettent plus de souplesse dans la de nition des classes.

4.6 Conception d'un TAG en CF

Le probleme du ranement d'un TAG en CF est un probleme classique de representation d'un type de donnees. Une conception est plate lorsqu'un type de donnees est de ni par une seule speci cation. Une conception est ordonnee lorsqu'un type de donnees est de ni par une hierarchie de speci cation basee sur l'heritage et appelee

schema

dans le modele des classes formelles. Les avantages d'une conception ordonnee sur une conception plate sont: plus grande nesse du typage, meilleure reutilisabilite, meilleure coherence des classes, diminution de la complexite de chaque classe.

La conception peut se faire a partir de la partie dynamique ou de la partie fonctionnelle. Il nous semble que la premiere est plus facile pour un specialiste de la programmation a objets. Une facon plus rigoureuse d'operer est de transformer la speci cation algebrique en classes formelles. Cette alternative aurait l'avantage de permettre la preuve de la representation mais une conception ordonnee est dicile. L'approche que nous avons proposee de nit des outils communs aux deux demarches et permet d'experimenter les di erents choix et de mesurer leur in uence au niveau de la reutilisation et de la structuration.

Le processus de representation decrit dans le chapitre 7 n'est evidemment pas completement automatique mais certaines parties le sont. Des choix sont faits par le concepteur au niveau de la sous-hierarchie d'heritage (le schema), du placement des operations, des structures abstraites choisies, etc. Ces di erents choix sont in uences par des criteres de reutilisabilite, de simplicite, de taille des axiomes, etc. Les principales phases sont :

{ Simpli cation de l'automate par regroupement d'etats connexes. Chaque etat represente un sous-type.

{ Calcul des pro ls exacts des generateurs en fonction des regroupements d'etats (union de types).

{ Obtention d'un schema d'utilisation et d'un schema de creation (regroupement sur le receveur ou sur le resultat).

{ Calcul des aspects des classes avec le schema de creation. Un calcul semi-automatique est possible a partir des generateurs mais des simpli cations sont necessaires. Elles sont prou- vables en utilisant un schema inspire de la representation des types de donnees [Hoa72]. { Restructuration de chaque aspect et du schema d'utilisation.

{ Ecriture des axiomes des methodes secondaires de chaque classe en fonction de l'aspect precedemment de ni.

Le resultat obtenu avec notre exemple est une hierarchie a trois niveaux et cinq classes terminales. La restructuration du graphe est possible en une unique classeHospitalBis.

HospitalBis

inherits from OBJECT

aspect : hospital

eld selectors constraint

empty? : HospitalBis ?! Boolean normal? : HospitalBis ?! Boolean

requires: empty?(Self) == false entry : HospitalBis ?! Patient

requires: empty?(Self) == false oldState : HospitalBis ?! Hospital

requires: empty?(Self) == false

Cette representation est equivalente a celle de nie de la gure 31 mais moins naturelle et moins reutilisable. Dans une etude de cas plus complexe comme l'exemple de l'ascenseur de l'annexe C, l'intuition seule ne surait pas a obtenir un tel resultat. Le processus que nous proposons est methodique mais il necessite egalement de l'experience dans les choix de conception comme le montrent les exemples de la section 7.4.1.