forked from menault/2026_TD2_DEV51_Qualite_Algo
Tri et maj Compte rendu
This commit is contained in:
+213
-97
@@ -1,139 +1,255 @@
|
||||
# Compte rendu – TD Complexité cyclomatique (R5.A.04)
|
||||
|
||||
## Partie 1 – Graphes de flot de contrôle
|
||||
Formules utilisées :
|
||||
- avec le graphe : **M = E − N + 2P** (E arêtes, N sommets, P = 1)
|
||||
- en comptant : **M = décisions + 1**
|
||||
|
||||
Pour chaque fonction demandée dans l'énnoncé, on construit le graphe de flot de contrôle, puis on applique :
|
||||
Classement selon la grille du cours : 1–10 simple, 11–20 modéré, 21–50 complexe, > 50 très risqué.
|
||||
|
||||
**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**.
|
||||
# Partie C – `exercices.c`
|
||||
|
||||
### C2 – `moyenne` (C)
|
||||
## __C1__ – `carre`
|
||||
- complexite = 0 decisions + 1 = 1
|
||||
|
||||
> **Classement:**
|
||||
|
||||
Simple
|
||||
|
||||
## __C2__ – `moyenne`
|
||||
|
||||

|
||||
|
||||
- N = 8, E = 9, P = 1
|
||||
- **M = 9 − 8 + 2 × 1 = 3**
|
||||
- complexite = 9 aretes − 8 sommets + 2 = 3
|
||||
- complexite = 2 decisions + 1 = 3
|
||||
|
||||
### C4 – `nom_jour` (C)
|
||||
> **Cas particuliers:**
|
||||
- ternaire `n > 0 ? ... : 0` : compte pour 1
|
||||
|
||||
> **Classement:**
|
||||
|
||||
Simple
|
||||
|
||||
## __C3__ – `est_bissextile`
|
||||
- complexite = 2 decisions + 1 = 3
|
||||
|
||||
> **Cas particuliers:**
|
||||
- `&&` et `||` sans `if` : 1 decision chacun (evaluation paresseuse)
|
||||
|
||||
> **Classement:**
|
||||
|
||||
Simple
|
||||
|
||||
## __C4__ – `nom_jour`
|
||||
|
||||

|
||||
|
||||
- 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**
|
||||
- complexite = 16 aretes − 10 sommets + 2 = 8
|
||||
- complexite = 7 decisions + 1 = 8
|
||||
|
||||
### J2 – `estDisponible` (Java)
|
||||
> **Cas particuliers:**
|
||||
- 7 `case` : 1 decision chacun
|
||||
- `default` : ne compte pas
|
||||
|
||||
> **Classement:**
|
||||
|
||||
Simple
|
||||
|
||||
## __C5__ – `compter_mots`
|
||||
- complexite = 7 decisions + 1 = 8
|
||||
|
||||
> **Cas particuliers:**
|
||||
- `while` : 1
|
||||
- `separateur = (... || ... || ... || ... || ...)` : 4 `||` sans `if`
|
||||
- `if` + `else if` : 2
|
||||
|
||||
> **Classement:**
|
||||
|
||||
Simple
|
||||
|
||||
## __C6__ – `date_valide`
|
||||
- complexite = 10 decisions + 1 = 11
|
||||
|
||||
> **Cas particuliers:**
|
||||
- 1er `if` + 3 `||` : 4
|
||||
- `if (mois == 2)` + `if (est_bissextile)` : 2
|
||||
- `else if` + 3 `||` : 4
|
||||
- l'appel a `est_bissextile` ne compte pas (M est calcule par fonction)
|
||||
|
||||
> **Classement:**
|
||||
|
||||
Modéré
|
||||
|
||||
---
|
||||
|
||||
# Partie Java – `Bibliotheque.java`
|
||||
|
||||
## __J1__ – `nombreDeLivres`
|
||||
- complexite = 0 decisions + 1 = 1
|
||||
|
||||
> **Classement:**
|
||||
|
||||
Simple
|
||||
|
||||
## __J2__ – `estDisponible`
|
||||
|
||||

|
||||
|
||||
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).
|
||||
- complexite = 5 aretes − 4 sommets + 2 = 3
|
||||
- complexite = 2 decisions + 1 = 3
|
||||
|
||||
- N = 4, E = 5, P = 1
|
||||
- **M = 5 − 4 + 2 × 1 = 3**
|
||||
> **Cas particuliers:**
|
||||
- 2 `&&` sans `if` : 1 decision chacun
|
||||
|
||||
### J6 – `importer` (Java)
|
||||
> **Classement:**
|
||||
|
||||
Simple
|
||||
|
||||
## __J3__ – `peutEmprunter`
|
||||
- complexite = 8 decisions + 1 = 9
|
||||
|
||||
> **Cas particuliers:**
|
||||
- 4 `if` + 2 `else if`
|
||||
- ternaire `a.etudiant ? 8 : 5` : +1
|
||||
- `l.reserve && !a.etudiant` : +1
|
||||
|
||||
> **Classement:**
|
||||
|
||||
Simple
|
||||
|
||||
## __J4__ – `calculerPenalite`
|
||||
- complexite = 8 decisions + 1 = 9
|
||||
|
||||
> **Cas particuliers:**
|
||||
- 4 `if` + 1 `else if` + 1 `for`
|
||||
- `joursRetard <= 0 || nbLivres <= 0` : +1
|
||||
- ternaire `penalite > 50 ? 50 : penalite` : +1
|
||||
- `else` : ne compte pas
|
||||
|
||||
> **Classement:**
|
||||
|
||||
Simple
|
||||
|
||||
## __J5__ – `rechercher`
|
||||
- complexite = 10 decisions + 1 = 11
|
||||
|
||||
> **Cas particuliers:**
|
||||
- 1 `for` + 5 `if`
|
||||
- `genre != null && ...` : +1
|
||||
- `disponiblesSeulement && ...` : +1
|
||||
- `motCle == null || ...` : +1
|
||||
- `titre.contains(m) || auteur.contains(m)` : +1
|
||||
- `continue` : ne compte pas
|
||||
- l'appel a `estDisponible` ne compte pas
|
||||
|
||||
> **Classement:**
|
||||
|
||||
Modéré
|
||||
|
||||
## __J6__ – `importer`
|
||||
|
||||

|
||||
|
||||
Les nœuds de décision sont en jaune, et la condition de la boucle `for` est en bleu.
|
||||
- complexite = 21 aretes − 15 sommets + 2 = 8
|
||||
- complexite = 7 decisions + 1 = 8
|
||||
|
||||
- N = 15, E = 21, P = 1
|
||||
- **M = 21 − 15 + 2 × 1 = 8**
|
||||
> **Cas particuliers:**
|
||||
- 2 : `for`
|
||||
- 3/4 : `if` + `||`
|
||||
- 7 : `if`
|
||||
- 10/11 : `if` + `&&`
|
||||
- 13 : `catch`
|
||||
- `continue` : ne compte pas
|
||||
|
||||
### P2 – `signe` (Python)
|
||||
> **Classement:**
|
||||
|
||||
Simple
|
||||
|
||||
---
|
||||
|
||||
# Partie Python – `exercices.py`
|
||||
|
||||
## __P1__ – `celsius_vers_fahrenheit`
|
||||
- complexite = 0 decisions + 1 = 1
|
||||
|
||||
> **Classement:**
|
||||
|
||||
Simple
|
||||
|
||||
## __P2__ – `signe`
|
||||
|
||||

|
||||
|
||||
- N = 6, E = 7, P = 1
|
||||
- **M = 7 − 6 + 2 × 1 = 3**
|
||||
- complexite = 7 aretes − 6 sommets + 2 = 3
|
||||
- complexite = 2 decisions + 1 = 3
|
||||
|
||||
### P3 – `notes_valides` (Python)
|
||||
> **Cas particuliers:**
|
||||
- `if` + `elif`
|
||||
|
||||
> **Classement:**
|
||||
|
||||
Simple
|
||||
|
||||
## __P3__ – `notes_valides`
|
||||
|
||||

|
||||
|
||||
La compréhension de liste cache une boucle et un filtre : elle se lit comme un `for` contenant un `if`.
|
||||
- complexite = 6 aretes − 5 sommets + 2 = 3
|
||||
- complexite = 2 decisions + 1 = 3
|
||||
|
||||
- N = 5, E = 6, P = 1
|
||||
- **M = 6 − 5 + 2 × 1 = 3**
|
||||
> **Cas particuliers:**
|
||||
- comprehension de liste = 1 `for` + 1 `if`
|
||||
- `0 <= n <= 20` : comparaison chainee comptee comme 1 seule condition
|
||||
|
||||
### Récapitulatif
|
||||
> **Classement:**
|
||||
|
||||
| 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 |
|
||||
Simple
|
||||
|
||||
## Partie 2 – Comptage des décisions (M = décisions + 1)
|
||||
## __P4__ – `mention`
|
||||
- complexite = 2 decisions + 1 = 3
|
||||
|
||||
### C (`exercices.c`)
|
||||
> **Cas particuliers:**
|
||||
- le dictionnaire remplace une cascade de `if/elif` (qui aurait donne M = 5)
|
||||
|
||||
| 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é |
|
||||
> **Classement:**
|
||||
|
||||
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).
|
||||
Simple
|
||||
|
||||
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).
|
||||
## __P5__ – `analyser_mot_de_passe`
|
||||
- complexite = 15 decisions + 1 = 16
|
||||
|
||||
Détail de C5 :
|
||||
> **Cas particuliers:**
|
||||
- 2 `for`, 8 `if`, 2 `elif`
|
||||
- `majuscule and minuscule` : +1
|
||||
- `login and login.lower() in ...` : +1
|
||||
- ternaire `"moyen" if ... else "faible"` : +1
|
||||
- `else` et `break` : ne comptent pas
|
||||
|
||||
| Ligne | Décision | +1 |
|
||||
> **Classement:**
|
||||
|
||||
Modéré
|
||||
|
||||
---
|
||||
|
||||
# Récapitulatif
|
||||
|
||||
| Fonction | M | Classement |
|
||||
|---|---|---|
|
||||
| `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).
|
||||
| C1 `carre` | 1 | Simple |
|
||||
| C2 `moyenne` | 3 | Simple |
|
||||
| C3 `est_bissextile` | 3 | Simple |
|
||||
| C4 `nom_jour` | 8 | Simple |
|
||||
| C5 `compter_mots` | 8 | Simple |
|
||||
| C6 `date_valide` | 11 | Modéré |
|
||||
| J1 `nombreDeLivres` | 1 | Simple |
|
||||
| J2 `estDisponible` | 3 | Simple |
|
||||
| J3 `peutEmprunter` | 9 | Simple |
|
||||
| J4 `calculerPenalite` | 9 | Simple |
|
||||
| J5 `rechercher` | 11 | Modéré |
|
||||
| J6 `importer` | 8 | Simple |
|
||||
| P1 `celsius_vers_fahrenheit` | 1 | Simple |
|
||||
| P2 `signe` | 3 | Simple |
|
||||
| P3 `notes_valides` | 3 | Simple |
|
||||
| P4 `mention` | 3 | Simple |
|
||||
| P5 `analyser_mot_de_passe` | 16 | Modéré |
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
Comptage décisions J 1 à J6, M = décisions + 1
|
||||
|
||||
J1 : pas de décisions, M = 1
|
||||
J2 : 3 if, M = 4
|
||||
J3 : 8 décisions : 4 if + 2 elseif + ? + &&, M = 9
|
||||
J4 : 8 décisions : 4 if, 1 elseif, 1 for, ||, &&, M = 9
|
||||
J5 : 10 décisions, M = 11
|
||||
J6 : 7 décisions, M = 8
|
||||
|
||||
ordre complexité :
|
||||
J1, J2 : simple
|
||||
J3,J4,J5,J6 : complexe
|
||||
@@ -1,13 +0,0 @@
|
||||
Compter les décisions de chacune des fonctions : M = décisions + 1
|
||||
|
||||
C1 : 0 décisions, M = 1
|
||||
C2 : 2 décisions : for et opérateur ?, M = 3
|
||||
C3 : 2 décisions : && et ||, M = 3
|
||||
C4 : 7 décisions : 7 cases (défault ne comptant pas), M = 8
|
||||
C5 : 7 décisions : 5 conditions dans separateur + 2, M = 8
|
||||
C6 : 10 décisions : premier if + 3 ||, second et troisieme if, else if + 3 ||, M = 11
|
||||
|
||||
classement par complexité :
|
||||
C1, C2, C3 : simple
|
||||
C4, C5 : moyen
|
||||
C6 : complexe
|
||||
Reference in New Issue
Block a user