A16 Std 982.2 Complexité cyclomatique

 

Application : « Cette mesure est employée pour déterminer la complexité structurelle du code d’un module. L’emploi de cette mesure est conçu pour limiter la complexité d’un module, le rendant ainsi plus facile à comprendre ». Cette mesure donne donc une indication de la qualité interne du module (complexité structurelle) qui est censée influencer la qualité externe (maintenabilité).

Primitives : « N = nombre de sommets (groupe d’énoncés séquentiels)
E = nombre d’arêtes (flux du programme entre les nœuds)
SN = nombre de sommets de partage (nœuds qui ont plus qu’une arête en sortie)
RG = nombre de régions (aires délimitées par des arêtes et qui ne sont pas traversées par d’autres arêtes »
 

Mise en œuvre : « Employant les nœuds et les arêtes construire un graphe fortement connexe. Un graphe fortement connexe est un graphe dont un sommet peut être atteint en partant de n’importe quel sommet. (…) Une fois le graphe construit, la mesure est calculée comme suit
 C = E – N + 1 (…) C’est aussi égal au nombre de régions ou au nombre de sommets de partage plus 1 (…)
 » Pour des modules moindrement longs et complexes la construction du graphe n’est pas simple surtout si l’expression évaluée par les sélections est complexe, le calcul n’est pas immédiat mais il existe des programmes (certains gratuits sur Internet) qui calculent la complexité cyclomatique pour des programmes en C++, en Java…

Interprétation : « Pour un module typique, une complexité maximum idéal est 10 (…). »

Considérations : « (…) La complexité cyclomatique peut être employée pour diminuer la complexité interne d’un module [¨ce qui] peut augmenter la complexité entre les modules (…) »

 

{

    int i;

 

    if (pInfoLien==NULL) {

        return(clcoms_NON_INIT);   

    }

    for (i=0;i<nbCannauxDisponible;i++ ) {

        if (pInfoLien[i].canalHandle!=(HANDLE)-1) {

            if (pInfoLien[i].conf.noApplication==noApplication) {

                clcoms_FermerCanal(i);

             }

        }

    }

    return (clcoms_OK);

}

 

Ce module a complexité 5 (quatre sommets de partage (3 IF et un FOR))

 

Pédalogue.

Qualitatif : Tu devrais m’expliquer quelque chose. Pour toi c’est sans doute très simple, mais pour moi c’est complètement flou : qu’est-ce que la complexité ?

Quantitatif : Simple. Je cite par cœur la définition du Std. IEEE 610.12 : « Le degré de difficulté de compréhension et de vérification de la conception ou de la mise en œuvre d’un système ou d’un composant. » C’est assez clair, n’est-ce pas ?

Qualitatif : Ouais… C’est une difficulté d’ordre cognitif : elle donne une indication de la difficulté qu’un humain a à saisir quelque chose.

Quantitatif : Parfaitement dit !

Qualitatif : Merci, mais comment mesures-tu la complexité ?

Quantitatif : On vient de le voir. En considérant le nombre de sommets, etc… en peu de mots, avec la CC (complexité cyclomatique).

Qualitatif : Ce qui veut dire qu’on a prouvé expérimentalement qu’il y a une loi qui relie le nombre de sélections dans un programme avec la difficulté psychologique de comprendre.

Quantitatif : Je ne connais pas de références précises, mais cela me semble évident. Il est bien plus facile de comprendre un programme sans IF qu’un avec une trentaine d’IF imbriqués !

Qualitatif : Ouais…

Quantitatif : Oui.

Qualitatif : Oui mais, étant donné qu’un module est en relation avec d’autres modules il est possible qu’un module hypercomplexe « absorbe » toute la complexité et permette ainsi d’avoir une complexité au niveau du système plus faible.

Quantitatif : Oui. C’est possible. Mais il ne faut pas faire dire à la CC plus que ce qu’elle veut dire. Et puis si tu veux que je te dise le fond de ma pensée, la CC est surtout utile pour déterminer le nombre minimal de cas à tester pour une unité.

Qualitatif : Est-ce une autre mesure de la norme 982 ?

Quantitatif : Oui, la A17.

Qualitatif : Je ne suis pas très difficile à convaincre, quand les choses sont simples. Imaginons que je veuille connaître la CC d’une méthode d’une classe, que cette classe commence avec une séquence d’une dizaine d’instruction, qu’il y ait ensuite un While avec à son intérieur une séquence de 50 instructions. Puisque j’ai un seul While, ma CC vaut 2. Ce qui veut dire que cette méthode à la même complexité qu’une méthode avec une instruction suivie d’un While qui contient à son tour une seule instruction !

Quantitatif : Non ! Elle n’a pas la même complexité elle a la même CC !

Qualitatif : Donc la complexité d’une méthode est quelque chose de différent de la CC.

Quantitatif : Certes. La CC donne une indication de la complexité structurelle de ta méthode. Imagine que tu introduises un IF à l’intérieur de ton While, ta complexité augment de 1.

Qualitatif : Si j’ajoute un autre IF, elle augmente encore de 1. J’ai bien compris. Mais… mais… ta CC ne tient pas compte des niveaux d’imbrication. Selon toi, les deux programmes suivants ont-ils la même complexité ?

 

Programme avec deux IF non imbriqués

Programme avec deux IF imbriqués

BEGIN

A := 87

IF A > x

     ALORS A := 37

IF A < y

     ALORS A := 16

END

BEGIN

A := 87

IF A > x

     ALORS A := 37

     SINON IF A < y

                       ALORS A := 16

END

 

Quantitatif : Je comprends où tu veux en venir. Tu veux me faire dire que le programme avec les IF imbriqués est plus complexe du point de vue cognitif et que la CC ne le montre pas.

Qualitatif : Tu as très bien saisi. Mais, mois aussi je crois d’avoir bien saisi. La CC a une certaine corrélation avec la complexité structurelle qui, à son tour, a une certaine corrélation avec la complexité cognitive.

Quantitatif : Parfait ! Ce n’est pas la solution de tous nos problèmes de complexité mais… Mais, c’est un petit pas en avant.

Qualitatif : D’accord. D’accord si on reste avec les pieds par terre et on ne se laisse pas prendre par la fascination des nombres.