• Aucun résultat trouvé

Structures de contrôle

Chapitre 5 EVOLUTION DU PROJET EM2

5.3. l Implantation du noyau

7.1.3 Structures de contrôle

Les métriques précédentes ne tiennent pas compte de la structure d'un programme formée par les diverses instructions de contrôle. Ces instructions ont pour conséquence de définir les chemins à l'intérieur d'un programme. L'hypothèse de base des métriques basées sur les structures de contrôle est la suivante: la complexité est fonction du nombre de chemins possibles d'exécution dans le programme et la difficulté à déterminer le chemin pour un ensemble arbitraire de données d'entrée.

Ainsi, un programme de 50 lignes comprenant 25 instructions du type IF-THEN-ELSE permet plus de 33 millions de chemins possibles [Mec 76].

Dans un tel cas, il est difficile d'arriver à une bonne compréhension du programme.

Le nombre cyclomatique selon McCabe

La métrique de McCabe [Mec 76], le nombre cyclomatique, repose sur le nombre de chemins indépendants d'un programme. Selon lui, la complexité est déterminée par la difficulté à tester le programme. Cette métrique repose sur la théorie des graphes.

Dans un graphe fortement connexe, le nombre cyclomatique est égal au nombre maximum de chemins linéairement indépendants. Le nombre cyclomatique V(G) d'un graphe comportant n noeuds, e arcs et p points d'entrée et de sortie, est défini comme: V(G)

=

e - n + p.

On trouve aussi une variante de cette formule sous la forme suivante: V(G) = e - n + 2p. Dans ce cas, p représente le nombre de composantes connexes. Ainsi, on peut tenir compte des procédures indépendantes. En réalité, le graphe d'un l)rogramme n'est pas une composante connexe puisqu'il n'y a pas de chemin entre le point de sortie et le point d'entrée, mais il suffit de rajouter un arc entre ces noeuds pour qu'il le devienne.

Un programme peut se représenter par un graphe comportant un unique point d'entrée et un unique point de sortie, où noeud correspond à un bloc d'instructions du programme dont l'exécution est séquentielle, et où Les arcs correspondent aux branchements du programme. Ce graphe est connu sous le nom de graphe de contrôle du programme. Il possède la particularité suivante: tous les noeuds peuvent être atteints depuis le noeud d'entrée et peuvent atteindre le noeud de sortie. La mesure V(G) dépend uniquement de la structure de contrôle du programme, puisque si l'on modifie le programme en ajoutant ou en enlevant des instructions qui ne sont pas des instructions de contrôle, alors le nombre cyclomatique ne change pas.

La figure 7.1 nous montre le nombre cyclomatique associé aux structures de contrôle de base.

Instruction de contrôle

SEQUEl\CE

IFTHENELSE

BOUCLE

Structure

()...__._...,

9 ~

Nombre cyclomatique associé

V=e-n+p

V=1-2+2=1

V=4-4+2=2

V=3-3+2=2

Figure 7.1 : Quelques exemples de calcul du nombre cyclomatique On s'aperçoit que les structures répétitives produisent des arcs qui remontent, donc le nombre de chemins généré par ces structures est infini.

C'est pourquoi la métrique définit la complexité en termes de chemins de base.

L'évaluation du nombre cyclomatique est relativement difficile à effectuer puisque l'on doit calculer une matrice d'atteignabilité où les éléments sont des blocs d'instructions séquentiels limités par des instructions conditionnelles. C'est une matrice (n,n) remplie de 0 et de 1;

la position (i,j) contient un 1 s'il existe un arc entre le ième et le jème bloc, sinon elle contient la valeur O.

Une autre technique, beaucoup plus simple, permettant de calculer le nombre cyclomatique est la suivante: V(G) = P + 1, où P représente le nombre de prédicats ou de conditions du programme. La figure 7 .2 montre l'exemple d'une procédure Modula-2, du graphe de contrôle associé et de son nombre cyclomatique.

PROCEDURE Exemple ( • •• ) ; Dans la pratique, on considère que le nombre cyclomatique ne doit pas dépasser ln valeur limite 10 [Mc.c 7f,\]. TI y a encore des problèmes à régler dans l'évaluation du nombre cyclomatique des structu.res de base.

Ainsi, supposons qu'une instruction conditionnelle porte sur plusieurs conditions (par exemple IF a AND b THEN .... ), quel doit être le nombre cyclomatique associé? De même, deux instructions condiLionnelles mises en séquence ou emboîtées ont-elles la même complexité?

Instructions conditionnelles généralement un nombre cyclomatique de N -1, où N représente le nombre de chemins possibles. On peut encore se demander ce qu'il se passe lorsque

une boucle a plusieurs points de sortie (par exemple, plusieurs EXIT en Modula-2)?

Cette métrique est l'une des plus répandues, car elle est simple à calculer et la complexité qu'elle mesure est intuitivement satisfaisante [Kaf 87], [Cur 79]. Diverses extensions ont été réalisées pour définir de nouvelles métriques.

Extension du nombre cyclomatique selon Myers

La métrique définie par Myers [Mye 77] est un raffinement de celle de McCabe. Elle prend en compte les problèmes posés par les prédicats qui portent sur plusieurs conditions. Ce type de prédicat est plus complexe qu'on prédicat portant seulement sur une condition. L'exemple suivant illustre ce point par des petits morceaux de programme.

prédicat simple

Ces deux segments de programmes comportent une seule décision:

ils peuvent donc être représentés par le même graphe orienté, qui possède une complexité cyclomatique V(G) égale à 2. Cependant, leur prédicat diffère en complexité. Myers trouve que la mesure de la complexité n'est pas suffisamment exprimée par une seule valeur. il suggère de l'exprimer par un couple de valeurs sous forme d'un intervalle [x,y]. La valeur limite inférieure x est égale au nombre cyclomatique défini tel que précédemment, et la valeur limite supérieure y est égale au nombre total de conditions + 1.

Cette extension de la métrique de McCabe n'est pas fondamentale, et pose le problème suivant: comment comparer la complexité de deux programmes? Supposons que deux programmes aient une complexité de [5,8] et (6,7]. Lequel des deux est le plus complexe? Il est difficile de comparer deux intervalles. De plus, il n'existe pas ou peu d'évaluations pratiques, ce qui rend incertaine son adéquation.

Basili et Reiter [Bas 79] ont aussi étudié plusieurs variations de la complexité cyclomatique, en essayant d'évaluer leur sensibilité par rapport au logiciel.

Une autre extension [Ste 84], plus récente, se base toujours sur la complexité cyclomatique à laquelle elle adjoint une mesure du flot de données du programme. De manière informelle, cette adjonction consiste

à dénombrer le nom.bre de variables et de constantes suivant leur type d'utilisation (consultation et modification).

Les métriques de McCabe et' de Halstead sont, de loin, les métriques Jes plus rét-andues. Elles ont suscité bien des commentaires et des améliorations. Harrison et Magel [Ifar 81b] ont proposé une métrique basée sur ces deux métriques et qui prend en compte les niveaux d'emboîtement des décisions.

Métrique de c_hen

Chen [Che 78] a aussi été sensibilisé par le problème des instructions conditionnelles emboîtées. Il considère que l'emboîtement des décisions produit une plus grande complexité que leur sérialisation. Sa mesure repose sur le nombre maximal d'intersections (min : maximal intersect number) du graphe de contrôle. Pour calculer cette valeur, le programme doit être mis sous la forme d'un graphe orienté fortement connexe (en ajoutant un arc entre le noeud de sortie et le noeud d'entrée).

La mesure est la suivante: le min est le nombre de fois qu'une ligne intersecte les arcs du graphe, mais cette ligne doit être dessinée de telle manière qu'elle n'entre qu'une seule fois dans les diverses régions fermées du graphe.

Si le graphe a des ponts (voir figure 7.3), alors le min du graphe est égal à la somme des min des sous-graphes, à laquelle on soustrait deux fois le nombre de sous-graphes et on ajoute la valeur 2. La figure 7 .3 montre quelques exemples de cette mesure.

En général, la limite supérieure est n+l, où n est le nombre de décisions, et la limite inférieure 2. La limite supérieure est atteinte quand toutes les décisions sont emboîtées, alors que la limite inférieure correspond à tme siniation où elles sont toutes en série.

min=2 pont pont min=2 chaque sous-graphe a un min=2,

le min du programme = 2 + 2 + 2 - 2 x 3 + 2 = 2 ce qui est le cas le plus simple,

les décisions sont en série

&

min =4

' ' '

c'est la valeur maximale, les décisions sont emboîtées

pont

1 : min=4 le graphe est composé de 3 sous-graphes, son min = 4 + 4 - 2 x 2 + 2 = 6

Figure 7.3 : Exemples de la métrique de Chen

Graphiquement, cette métrique est façile à appliquer, mais elle devient difficile si on l'essaye à partir du programme. De plus, même sur le dessin, elle peut devenir complexe si l'on a un grand nombre de boucles.

La structure associée à une instruction du type CASE pose aussi un

problème, car il n'est pas normal que le min soit égal à N, le nombre de chemins possibles. Intuitivement, un CASE de 4 branches est moins complexe que 3 décisions emboîtées.

Les deux prochaines métriques (mesure du niveau d'emboîtement et expressions régulières) sont des tentatives pour essayer de tenir compte des différentes strucrures de contrôle et surtout de leur emboîtement.

Mesure du niveau d'emboîtement

La mesure du niveau d'emboîtement [Piw 82] est une métrique basée sur la complexité cyclomatique, à laquelle est rajoutée une mesure de l'emboîtement des prédicats. Elle permet aussi de prendre en considération le problème posé par les instructions CASE. La métrique proposée par Piwowarski est la suivante:

N = V*(G) +

L

P(i)

V*(G) représente la complexité cyclomatique ajustée, dans laquelle une instruction CASE est traitée comme un prédicat. P(i) est le niveau d'emboîtement du ième prédicat.

Cette mesure permet de pondérer la complexité des instructions conditionnelles suivant leur niveau d'emboîtement. Par contre, elle ne tient pas compte explicitement des structures de contrôle telles que les boucles.

Expressions régulières

Un programme est toujours représente par son graphe de contrôle:

les noeuds se composent d'instructions consécutives sans branchements, ceux-ci correspondent aux arcs. A chaque noeud est associé un nom utilisé dans le calcul de l'expression régulière du programme.

L'expression régulière d'on programme [Mag 81] traduit tous les chemins possibles du programme. Elle se compose d'une combinaison d'opérandes (les noms des noeuds) et d'opérateurs. Les opérateurs possibles sont les parenthèses, l'addition pour indiquer un choix et la multiplication pour indiquer une boucle. La figure 7.4 nous montre des exemples sùnples d'expressions régulières.

Un moyen simple de dériver une mesure de complexité est de compter le nombre de symboles (opéirandes et opérateurs) contenus dans une expression régulière. Le premier exemple a une mesure de 7, le deuxième a la valeur 9 et le dernier a la valeur 21.

expression régulière a (b + c) d

expression régulière expression régulière abc (be)* d abc (be)* d ((be (be)* d)*

Figure 7.4 : Exemples d'expressions régulières

Cette approche est la première qui prenne en compte explicitement les structures de boucles. Basée sur cette idée, elle est constituée d'une projection du code sous fonne d'une séquence (expression régulière) de symboles composés de blocs d'instructions ou d'opérateurs traduisant les instructions de contrôle. Evidemment, la longueur de la séquence est directement proportionnelle à la taille du programme. Raisonnablement, elle ne peut pas être considérée comme une mesure. Pour pallier à cela, on se contente de compter le nombre de symboles de cette séquence. En faisant cela, on perd toutes les informations sur la structure du programme.

La prochaine métrique (le polynôme caractéristique) a repris ces idées pour essayer de définir un compromis entre l'expression régulière et le compte de ses symboles.

Polynôme caractéristique

Le polynôme caractéristique [Can 83] est une métrique qui considère toutes les structures de contrôle (boucle, sélection, séquence) et

leur niveau d'emboîtement. De cette manière, elle permet de prendre en considération les caractéristiques structurelles du flot de contrôle du programme et le nombre de ses exécutions possibles.

Pour fonner le polynôme caractéristique d'un programme, il est nécesaire de représenter celui-ci sous la forme d'un graphe particulier: un d-graphe. Un tel graphe comporte deux types de noeuds: les noeuds primitifs, correspondant à des blocs d'instructions dont l'exécution est séquentielle, et les noeuds de structure, correspondant à une des diverses structures de contrôle possibles (boucle, sélection, séquence). Ce dernier type de noeud est en fait la racine d'un sous-graphe contenant les noeuds dépendant de cette structure de contrôle. Les arcs représentent donc des relations d'inclusion entre un noeud du type structure de contrôle et les noeuds, du niveau inférieur, qui lui sont rattachés. Un seul noeud se trouve au niveau 0, il représente le programme lui-même et il p~ssède le type séquence.

Graphe de structure classique

Niveau

0 séq.Jence

-..---2

3

4

n

C:=J

noeud de structure

0

noeud primitif

0-graphe

Figure 7.5: Exemple de programme sous forme de d-graphe

La figure 7.5 montre un exemple de programme sous la forme d'un graphe classique et sa représentation sous la forme d'un d-graphe.

Le polynôme caractéristique se calcule de la façon suivante: on associe un nombre caractéristique (CN) à chaque noeud du d-graphe suivant les critères suivants:

- Pour chaque noeud primitif, le nombre caractéristique (CN) est égal à 1.

- Pour un noeud structure de type séquence, CN est égal au produit des CN des noeuds structure et primitifs du niveau immédiatement en dessous.

- Pour un noeud structure de type sélection, CN est égal à la somme des CN des noeuds du niveau inférieur (excepté le noeud correspondant à la condition). Dans le cas d'une structure IF ...

TIIEN ... sans ELSE, on ajoute 1.

- Pour un noeud structure de type boucle, CN est égal au produit CN du noeud du niveau inférieur (CN+l si c'est une instruction WHILE) par la variable C. Comme pour la structure sélective, on ne compte pas le noeud correspondant à la condition.

On appelle polynôme caractéristique (PCN), le nombre caractéristique du noeud se trouvant au niveau 0 et correspondant au programme lui-même. Ce nombre est, généralement, un polynôme en C.

Il a la forme suivante:

n PCN=

Lai ci

i=O

où ai représente le nombre de chemins possibles empruntant i structures de boucle imbriquées o.u séquentielles et où

L

n aj représente le nombre total de chemins possibles lors de l'exécution.

i=O

La table suivante nous donne les différents nombres caractéristiques (et le polynôme caractéristique final) du programme schématisé dans la figure 7.5.

niveau noeud CN

== = == = = = == ~== = =

-4 g,h 1

3 sélection 2

3 f 1

2 b,c,d,e 1

2 séquence 2

1 a,i 1

1 boucle 3C

0 séquence

(programme) 6C

Ce modèle pennet donc de donner une idée de la complexité de la structure d'un programme en l'exprimant de manière relativement simple. La figure 7 .6 nous montre quelques exemples de structures de programme et leur polynôme caractéristique.

,.*--... \

PCN =2 C2

PCN = C

(c2

+ 2 C) + 2

3 2

=C +2C +2 Figure 7.6 : Exemples de polynômes caractéristiques

'.2C

.,

1 1 1 (

• •

Cette métrique manque encore de raffinement dans certains cas; elle a donné lieu à des extensions, dont nous présentons maintenant une des principales. Nous verrons, dans Je paragraphe 7.2, qu'une des mesures de EM2/Complex est aussi une extension de cette métrique.

Extension du polynôme caractéristique selon Tamine

Tamine [Tarn 83] est sensible au fait que les structures de boucle engendrent la même mesure de complexité, qu'elles soient emboîtées ou mises en série (figure 7. 7). Pourtant, intuitivement, ces structures ont des complexités différentes. Deux boucles emboîtées sont plus complexes que deux boucles en série. Dans le premier cas, le nombre total de chemins possibles est égal à la somme du nombre de chemins possibles de chaque bo.ucle, alors que dans le deuxième cas, il est égal au produit de ces deux nombres.

PCN = C2 PCN =C2

Figure 7.7 : Différentes structures dont le PCN est identique Tamine propose d'utiliser des symboles différents pour identifer des structures emboîtées. Ainsi, dans la figure 7 .7, le premier graphe a un PCN = c2, alors le second a maintenant un PCN =AB. Les symboles différents indiquent donc des boucles emboîtées, alors que les puissances indiquent des boucles en série.

Cette métrique du polynôme caractéristique donne une bonne image de la structure de l'algorithme d'un programme, et, par conséquent, une bonne mesure de sa complexité. Par contre, son évaluation n'est pas très aisée: il faut représenter le programme sous forme de graphe et, ensuite,

calculer le polynôme, ce qui n'est pas toujours simple et qui limite l'utilisation de cette métrique. Wingerter [Win84] a bien proposé une amélioration de la structure du graphe qui permette d'en dé~uire

facilement le polynôme caractéristique, mais il faut toujours convertir le programme en un graphe.