Sie sind auf Seite 1von 13

Spécications formelles : objectifs

 Montrer comment les techniques de spécication formelles aident


Spécications formelles à découvrir des problèmes dans la conception d'un système.
 Dénir et utiliser des techniques algébriques pour spécier les
interfaces d'un système.

Méthodes formelles Coût de la spécication formelle


 Les spécications ou méthodes formelles sont des techniques
 La spécication formelle demande plus d'eort dans les phases
informatiques utilisant des représentations mathématiques du
avant du projet.
logiciel et du matériel.
 Elle réduit les erreurs (incomplétude ou inconsistance) de la
 Elles ne sont utilisées que dans des domaines critiques à cause
spécication des charges.
de leur coût (matériel, en temps et humain).
 Ainsi, le nombre de changements du projet à cause d'un
 Le principal bénéce de leur utilisation est la réduction du
problème de spécication de charges est réduit.
nombre d'erreurs dans le logiciel.

2 3
Dierentes classes de spécications formelles Spécication formelle d'interfaces

 Algébriques : le système est spécié en termes d'ensembles,  Les grands systèmes sont décomposés en sous-systèmes qui se
d'opérations et de leur relation. composent à travers d'interfaces bien dénies.
Ex. séquentiel : Act One, Larch, OBJ.  La spécication des interfaces des sous-systèmes permet leur
Ex. concurrent : Lotos. développement indépendant.
 Les interfaces peuvent être dénies comme des types de données
abstraits ou des interfaces de classes.
 Basés sur les modèles : le système est spécié en termes de  L'approche algébrique pour la spécication formelle des
modèle à états et utilisent des opérations qui changent l'état du interfaces permet pour les opérations de l'interface :
sytème.  de les dénir formellement,
Ex. séquentiel : Z, VDM, B.  d'analyser formellement (preuve) leur comportement,
Ex. concurrent : CSP, réseaux de Pétri, automates hiérarchiques  de dériver l'implémentation d'un objet ou d'un type en
(statecharts ). partant de sa dénition formelle.

4 5

Types abstraits de données Exemple : jour


 Manipulation de domaines complexes. Domaine :
 La manipulation est indépendante de la représentation jour (jours vus comme des entiers de 1 à 31)
particulière du domaine.
Opérations de construction :
 On se donne :
cons_jour : {x : entier | 1 ≤ x ≤ 31} → jour
 Un nom pour domaine abstrait
 Des opérations de construction d'une représentation concrète Opérations de construction étendue :
vers le domaine abstrait entier_to_jour : entier → jour
 Des opérations de test pour les diérents constructions. Opérations d'accès :
 Des opérations d'accès d'un objet abstrait vers les
numéro_jour : jour → {x : entier | 1 ≤ x ≤ 31}
composantes d'une représentation concrète.

6 7
Exemple : exemplaire
Exemple : argent
Domaine :
Domaine :
exemplaire
argent
Opérations de construction :
Opérations de construction :
cons_livre : livre → exemplaire
francs : entier → argent
cons_dvd : dvd → exemplaire
euros : entier → argent
Opérations de test :
Opérations de test :
est_livre, est_dvd : exemplaire → bool
est_francs, est_euros : argent → bool
Opérations d'accès :
Opérations d'accès :
ex_livre : {x : exemplaire | est_livre(x)} → livre
val_argent : argent → entier
ex_dvd : {x : exemplaire | est_dvd(x)} → dvd

8 9

Exemple : Les cartes de couleur

Domaine : Domaine :
couleur figure
Constantes : Constantes :
pique, coeur, carreau, trèfle : couleur as, roi, dame, cavalier, valet, dix, neuf, huit, sept : figure
Opérations de test : Opérations de test :
est_pique : couleur → bool est_as, est_roi, est_dame : figure → bool
est_coeur : couleur → bool est_cavalier, est_valet : figure → bool
est_carreau : couleur → bool est_dix, est_neuf, est_huit, est_sept : figure → bool
est_trèfle : couleur → bool

10 11
Domaine :
main
Domaine :
Opérations de construction :
carte
cons_main : {⃗n ∈ carte5 | Diff(⃗n)} → main
Opérations de construction :
Opérations de construction étendue :
cons_carte : couleur × figure → carte
cartes_to_main : carte5 → main
Opérations d'accès :
Opérations d'accès :
figure_carte : carte → figure
carte1 : main → carte
couleur_carte : carte → couleur ..
.
carte5 : main → carte

12 13

Domaine :
carte_tarot
Constantes :
excuse : carte_tarot Opérations d'accès : (Première possibilité)
Opérations de construction : carte_carte_tarot : {x : carte_tarot | est_carte_simple(x)}
cons_tarot_simple : carte → carte_tarot → carte
cons_atout : {n : entier | 1 ≤ n ≤ 21} → carte_tarot atout_de_tarot : {x : carte_tarot | est_atout(x)} →
Opérations de construction étendue : {n : entier | 1 ≤ n ≤ 21}
entier_to_carte_tarot : entier → carte_tarot
Opérations de test :
est_excuse, est_carte_simple, est_atout : carte_tarot → bool

14 15
Opérations d'accès : (Deuxième possibilité)
couleur_de_tarot : {x : carte_tarot | est_carte_simple(x)} Relation entre les deux solutions
→ couleur
couleur_de_tarot(c) peut s'obtenir comme
figure_de_tarot : {x : carte_tarot | est_carte_simple(x)} couleur_carte(carte_carte_tarot(c))
→ figure figure_de_tarot(c) peut s'obtenir comme
atout_de_tarot : {x : carte_tarot | est_atout(x)} → figure_carte(carte_carte_tarot(c))
{n : entier | 1 ≤ n ≤ 21}

16 17

Forme générale d'un TDA


Domaine : Opérations de construction étendue :
dom (éventuellement un produit cartésien) dom1 _to_dom : d1 → dom
Constantes : ..
.
c1 , . . . , cn : dom domm _to_dom : dm → dom
Opérations de construction : Opérations de test :
cons_dom1 : {x : d1 | P1 (x)} → dom est_c1 , . . . , est_cn : dom → bool
.. ..
. .
cons_domm : {x : dm | Pm (x)} → dom est_op1 , . . . , est_opm : dom → bool

di est un domaine, Pi (_) est une propriété

18 19
Opérations d'accès : Notation
acces1 : {x : dom | est_op1 (x)} → {x : d1 | P1 (x)}
..
. {x : dom | true} → dom′ est équivalent à
accesm : {x : dom | est_opm (x)} → {x : dm | Pm (x)} {x : dom} → dom′ est équivalent à
Autres opérations : dom → dom′
..
.

20 21

Quelques variantes
On peut omettre ou rajouter quelques items selon les cas :
 Si la propriété Pi (x) est toujours true, alors on l'écrit pas.
 Si le domaine est construit à partir d'une seule constante ou
d'une seule opération de construction, alors inutile d'écrire accesi1 : {x : dom | est_opi (x)} →
l'opération de test car elle est équivalente à est(x) = true. {y : a1 | y = proj1 (x) et x : di et Pi (x)}
 Si le domaine est construit à partir de m opérations de ..
.
construction, alors m − 1 opérations de test susent.
accesik : {x : dom | est_opi (x)} →
 Si un domaine di est un produit cartésien a1 × . . . × ak , alors on
{y : ak | y = projk (x) et x : di et Pi (x)}
peut remplacer l'opération d'accès

accesi : {x : dom | est_opi (x)} → {x : di | Pi (x)}

par k opérations de la forme

22 23
Le Tarot en OCAML (* operations de test du type couleur *)

(* type couleur *) #let est_pique (f) =


match f with Pi -> true | _ -> false;;
#type couleur = Pi | Co | Ca | Tr;;
#let est_coeur (f) =
match f with Co -> true | _ -> false;;
(* Constructeurs pour les constantes de couleur *)
#let est_carreau (f) =
#let pique = Pi;; match f with Ca -> true | _ -> false;;
#let coeur = Co;;
#let carreau = Ca;; #let est_trefle (f) =
#let trefle = Tr;; match f with Tr -> true | _ -> false;;

24 25

(* type figure *) #let huit =Huit;;


#let sept =Sept;;
#type figure =
As | Roi | Dame | Cav | Valet | Dix | Neuf | Huit | Sept;;
(* operations de test du type figure *)
(* Constructeurs pour les constantes de figure *)
#let est_as (f) =
#let as =As;; match f with As -> true | _ -> false;;
#let roi =Roi;;
#let dame =Dame;; #let est_roi (f) =
#let cavalier =Cav;; match f with Roi -> true | _ -> false;;
#let valet =Valet;;
#let dix =Dix;; #let est_dame (f) =
#let neuf =Neuf;; match f with Dame -> true | _ -> false;;

26 27
match f with Huit -> true | _ -> false;;
#let est_cavalier (f) =
match f with Cav -> true | _ -> false;;
#let est_sept (f) =
match f with Sept -> true | _ -> false;;
#let est_valet (f) =
match f with Valet -> true | _ -> false;;
(* type carte *)

#let est_dix (f) = #type carte = C of figure * couleur;;


match f with Dix -> true | _ -> false;;

#let est_neuf (f) =


match f with Neuf -> true | _ -> false;; (* operation de construction du type carte *)

#let est_huit (f) = #let cons_carte(f,c) = C(f,c);;

28 29

#let cons_atout (n) = A(n);;


(* operations d'acc\`es du type carte *)
#let figure_carte(e) = match e with C(f,c)->f;;
(* operations de construction du type carte_tarot *)
#let couleur_carte(e) = match e with C(f,c)->c;;
#let int_to_carte_tarot (n) =
(* type carte_tarot *)
if 1 <= n & n <= 21
then cons_atout (n)
#type carte_tarot =
else failwith"numero d'atout invalide";;
Ex | S of carte | A of int;;

(* operations de construction etendue du type carte_tarot *) (* operations de test du type carte_tarot *)

#let excuse = Ex;; #let est_excuse (c) =


#let cons_tarot_simple(c) = S(c);; match c with Ex -> true | _ -> false;;

30 31
| _ -> failwith "Pas une carte simple";;
#let est_carte_simple (c) =
match c with S(_) -> true | _ -> false;;

#let est_atout (c) =


#let figure_de_tarot (e) =
match c with A(_) -> true | _ -> false;;
match e with
S(C(f,_)) -> f
| _ -> failwith "Pas une carte simple";;

(* operations d'acces du type carte_tarot *)


#let atout_de_tarot (e) =
#let couleur_de_tarot (e) = match e with
match e with A(x) -> x
S(C(_,c)) -> c | _ -> failwith "Pas un atout";;

32 33

Les prols de symboles de la signature valet: -> figure


dix: -> figure
pique: -> couleur neuf: -> figure
coeur: -> couleur huit: -> figure
carreau: -> couleur sept: -> figure
trefle: -> couleur est_as: figure -> bool
est_pique: couleur -> bool est_roi: figure -> bool
est_coeur: couleur -> bool est_dame figure -> bool
est_carreau: couleur -> bool est_cavalier: figure -> bool
est_trefle: couleur -> bool est_valet: figure -> bool
as: -> figure est_dix: figure -> bool
roi: -> figure est_neuf: figure -> bool
dame: -> figure est_huit: figure -> bool
cavalier: -> figure est_sept: figure -> bool

34 35
cons_carte: figure * couleur -> carte = <fun>
figure_carte: carte -> figure = <fun>
couleur_carte: carte -> couleur = <fun>
excuse: -> carte_tarot
Codage d'autres opérations d'un TDA
cons_tarot_simple: carte -> carte_tarot = <fun>
cons_atout: int -> carte_tarot = <fun>  Abstrait : on utilise uniquement les opérations abstraites dénies
int_to_carte_tarot:int -> carte_tarot = <fun> dans le TDA.
est_carte_simple: carte_tarot -> bool = <fun>  Concret : on utilise les primitives du langage de programmation
est_atout: carte_tarot -> bool = <fun> associées au domaines concrets utilisés dans le TDA.
figure_de_tarot: carte_tarot -> figure = <fun>
couleur_de_tarot: carte_tarot -> couleur = <fun>
atout_de_tarot: carte_tarot -> int = <fun>

36 37

Codage abstrait
#let points (c) =
then 1.5
if est_excuse(c)
else 0.5
then 4.5
else let n = atout_de_tarot(c) in
else if est_carte_simple (c)
if n=1 or n=21
then let f = figure_de_tarot(c) in
then 4.5
if est_roi(f)
else 0.5;;
then 4.5
else if est_dame(f)
val points : carte_tarot -> float = <fun>
then 3.5
else if est_cavalier(f)
then 2.5
else if est_valet(f)

38 39
Codage concret

#let points(c) = match c with


Ex -> 4.5
| S(C(Roi,_)) -> 4.5
| S(C(Dame,_)) -> 3.5 Exemple : un seul TDA et deux implémentations
| S(C(Cav,_)) -> 2.5 possibles
| S(C(Valet,_)) -> 1.5
| S(C(_,_)) -> 0.5
| A(1) -> 4.5
| A(21) -> 4.5
| _ -> 0.5;;
val points : carte_tarot -> float = <fun>

40 41

Domaine :
Exemple : une première implémentation
pile #type pile = intlist;;
Constantes :
pile_vide : pile #let pile_vide = [];;

Opération de construction :
#let cons_pile(a,p) = a::p;;
cons_pile : entier × pile → pile
Opération de test : #let est_pile_nv(p) =
est_pile_nv : pile → bool match p with a::l -> true | _ -> false;;
Opérations d'accès
#let premier_pile(p) = match p with
premier_pile : {x : pile | est_pile_nv(x)} → entier
a::l -> a
reste_pile : {x : pile | est_pile_nv(x)} → pile | _ -> failwith"Pile Vide";;

42 43
Les prols de symboles de la signature

#let reste_pile(p) = match p with pile_vide: -> intlist


a::l -> l cons_pile : int * intlist -> intlist
| _ -> failwith"Pile Vide";; est_pile_nv : intlist -> bool
premier_pile : intlist -> int
reste_pile : intlist -> intlist

44 45

Exemple : une autre implémentation


#type pile = Pile_Vide | P of int * pile;;

# let pile_vide = Pile_Vide;;


| _ -> failwith "Pas une pile non vide";;

# let cons_pile(t,r) = P(t,r);;


# let reste_pile(p) = match p with
P(t,r) -> r
# let est_pile_nv(p) = match p with
| _ -> failwith "Pas une pile non vide";;
Pile_Vide -> false
| _ -> true ;;

# let premier_pile(p) = match p with


P(t,r) -> t

46 47
Exemple : encore une autre implémentation
#type pile_nv = {tete:int; reste:ma_pile} and
Les prols de symboles de la signature ma_pile = Pile_Vide | P of pile_nv;;

type pile_nv = { tete : int; reste : ma_pile; } and


pile_vide: -> pile
ma_pile = Pile_Vide | P of pile_nv
cons_pile : int * pile -> pile
est_pile_nv : pile -> bool
premier_pile : pile -> int
# let cons_pile_nv(t,r) = { tete=t ; reste = r};;
reste_pile : pile -> pile
val cons_pile_nv : int * ma_pile -> pile_nv = <fun>

# let tete_pile_nv(p) = p.tete;;


val tete_pile_nv : pile_nv -> int = <fun>

48 49

# let reste_pile_nv(p) = p.reste;;


val reste_pile_nv : pile_nv -> ma_pile = <fun> # let premier_pile(p) = match p with
Pile_Vide -> failwith"Pile Vide"
# let pile_vide =Pile_Vide;; | P(x) -> x.tete;;
val pile_vide : ma_pile = Pile_Vide val premier_pile : ma_pile -> int = <fun>

# let cons_pile(a,p) = P(cons_pile_nv(a,p));; # let reste_pile(p) = match p with


val cons_pile : int * ma_pile -> ma_pile = <fun> Pile_Vide -> failwith"Pile Vide"
| P(x) -> x.reste;;
# let est_pile_nv(p) = val reste_pile : ma_pile -> ma_pile = <fun>
match p with Pile_Vide -> false | _ -> true ;;
val est_pile_nv : ma_pile -> bool = <fun>

50 51

Das könnte Ihnen auch gefallen