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 specication de classes, qui est interme- diaire entre les TAA et les classes concretes. Une CF est une specication particuliere de TAA. Le modele doit permettre une transition plus facile des TAA vers les classes mais egalement de denir des regles d'ecriture et des outils inspires des specications algebriques. Une semantique algebrique complete est denie 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 denie 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 specication algebrique particuliere qui sous certaines hypotheses est susamment complete et non-contradictoire et d'autre part, elle verie 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 Eiel plusieurs originalites exis- tent : la proximite avec les specications 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 denition 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 deni par une seule specication. Une conception est ordonnee lorsqu'un type de donnees est deni par une hierarchie de specication 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 specication 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 denit des outils communs aux deux demarches et permet d'experimenter les dierents 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 dierents choix sont in uences par des criteres de reutilisabilite, de simplicite, de taille des axiomes, etc. Les principales phases sont :
{ Simplication de l'automate par regroupement d'etats connexes. Chaque etat represente un sous-type.
{ Calcul des prols 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 simplications 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 deni.
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 denie 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.