Files
2026_TD2_DEV51_Qualite_Algo/COMPTE_RENDU.md
T

5.1 KiB
Raw Blame History

Compte rendu – TD Complexité cyclomatique (R5.A.04)

Partie 1 – Graphes de flot de contrôle

Pour chaque fonction demandée dans l'énnoncé, on construit le graphe de flot de contrôle, puis on applique :

M = E − N + 2P (E = arêtes, N = nœuds, P = 1 pour une fonction)

On vérifie ensuite le résultat avec la règle pratique M = décisions + 1.

C2 – moyenne (C)

Graphe C2

  • N = 8, E = 9, P = 1
  • M = 9 − 8 + 2 × 1 = 3

C4 – nom_jour (C)

Graphe C4

  • N = 10, E = 16 (8 arêtes du switch vers chaque branche + 8 arêtes des branches vers la sortie), P = 1
  • M = 16 − 10 + 2 × 1 = 8

J2 – estDisponible (Java)

Graphe J2

La méthode ne contient aucun if, mais les && sont évalués paresseusement : chaque opérande est une décision (si livre.emprunte est vrai, on sort directement sans évaluer la suite).

  • N = 4, E = 5, P = 1
  • M = 5 − 4 + 2 × 1 = 3

J6 – importer (Java)

Graphe J6

Les nœuds de décision sont en jaune, et la condition de la boucle for est en bleu.

  • N = 15, E = 21, P = 1
  • M = 21 − 15 + 2 × 1 = 8

P2 – signe (Python)

Graphe P2

  • N = 6, E = 7, P = 1
  • M = 7 − 6 + 2 × 1 = 3

P3 – notes_valides (Python)

Graphe P3

La compréhension de liste cache une boucle et un filtre : elle se lit comme un for contenant un if.

  • N = 5, E = 6, P = 1
  • M = 6 − 5 + 2 × 1 = 3

Récapitulatif

Fonction N E M Classe
C2 moyenne 8 9 3 Simple
C4 nom_jour 10 16 8 Simple
J2 estDisponible 4 5 3 Simple
J6 importer 15 21 8 Simple
P2 signe 6 7 3 Simple
P3 notes_valides 5 6 3 Simple

Partie 2 – Comptage des décisions (M = décisions + 1)

C (exercices.c)

Fonction Décisions M Classe
C1 carre aucune 1 Simple
C2 moyenne 1 for, 1 ternaire ?: 3 Simple
C3 est_bissextile 1 &&, 1 || 3 Simple
C4 nom_jour 7 case 8 Simple
C5 compter_mots 1 while, 4 ||, 1 if, 1 else if 8 Simple
C6 date_valide 4 if/else if, 6 || 11 Modéré

Détail de C3 : il n'y a aucun if, mais && et || sont évalués paresseusement : chacun crée un branchement (si annee % 4 == 0 est faux, annee % 100 != 0 n'est pas évalué). 2 décisions + 1 = 3, ce qui correspond au graphe vu en cours (N = 4, E = 5).

Détail de C4 : le default ne compte pas (c'est le « sinon » du switch) et les return non plus. 7 + 1 = 8, comme avec le graphe (16 − 10 + 2).

Détail de C5 :

Ligne Décision +1
while (texte[i] != '\0') while 1
c == ' ' || c == '\t' || c == '\n' || c == ',' || c == '.' 4 || 5
if (separateur) if 6
else if (!dans_mot) else if 7

M = 7 + 1 = 8. Ici aussi les || comptent sans if : ils sont dans une affectation (int separateur = ...), mais restent des branchements.

Détail de C6 :

Ligne Décision +1
if (annee < 1 || mois < 1 || mois > 12 || jour < 1) if + 3 || 4
if (mois == 2) if 5
if (est_bissextile(annee)) if 6
else if (mois == 4 || mois == 6 || mois == 9 || mois == 11) else if + 3 || 10

M = 10 + 1 = 11, soit juste au-dessus du seuil de 10 (McCabe, PMD) : c'est la fonction C la plus complexe. L'appel à est_bissextile ne compte pas : ses décisions appartiennent à est_bissextile (M calculé par fonction).

Python (exercices.py)

Fonction Décisions M Classe
P1 celsius_vers_fahrenheit aucune 1 Simple
P2 signe 1 if, 1 elif 3 Simple
P3 notes_valides 1 for, 1 if (dans la compréhension) 3 Simple
P4 mention 1 for, 1 if 3 Simple
P5 analyser_mot_de_passe 2 for, 8 if, 2 elif, 2 and, 1 ternaire 16 Modéré

Détail de P5 :

Ligne Décision +1
if len(mdp) < 12 if 1
for c in mdp for 2
if c.isupper() if 3
elif c.islower() elif 4
elif c.isdigit() elif 5
if not (majuscule and minuscule) if + and 7
if not chiffre if 8
if not special if 9
if login and login.lower() in mdp.lower() if + and 11
for i in range(len(mdp) - 2) for 12
if mdp[i] == mdp[i + 1] == mdp[i + 2] if 13
if not problemes if 14
"moyen" if len(problemes) <= 2 else "faible" ternaire 15

M = 15 + 1 = 16. Le else final de la cascade if/elif/else et le break ne comptent pas. Comme pour P3, la comparaison chaînée mdp[i] == mdp[i + 1] == mdp[i + 2] est comptée comme une seule condition.

P4 a le même M que la version refactorisée de mention vue en cours : le dictionnaire remplace la cascade de if/elif (qui aurait donné M = 5).