Concevoir, tester, traduire
Ce que ce chapitre apporte
- Passer d'un besoin écrit en français à un organigramme, en suivant six étapes dans l'ordre.
- Construire un jeu d'essai (cas nominal, cas limites, cas d'erreur) et le calculer avant d'exécuter.
- Distinguer une erreur qui arrête l'exécution d'une erreur de logique.
- Localiser une erreur en pas à pas : prédire, observer, repérer la première divergence.
- Relire en Python, forme par forme, un programme construit dans Flowgorithm.
Connaître les formes ne suffit pas : devant un besoin écrit en français, la difficulté est de savoir par où commencer, puis de savoir si le programme obtenu est juste. Ce chapitre donne une méthode fixe, du besoin jusqu'à l'organigramme, un moyen de le vérifier (le jeu d'essai), un moyen de trouver une erreur (le pas à pas) et la lecture du même programme en Python, le langage de la suite du parcours.
Du besoin à l'organigramme
Un magasin de maintenance suit le stock d'une pièce de rechange. Le magasinier saisit le stock du matin, le seuil de réapprovisionnement, puis le nombre de sorties de la journée et la quantité prélevée à chaque sortie. Après chaque sortie, le programme affiche le stock restant ; une sortie qui dépasse le stock est refusée. En fin de journée, il indique s'il faut commander : c'est le cas quand le stock est inférieur ou égal au seuil.
Étape 1 : identifier les entrées et les sorties. Ce que le magasinier tape est une entrée et deviendra une forme Input ; ce que le programme affiche est une sortie et deviendra une forme Output. Chaque entrée demande une variable déclarée, avec son type.
Entrées (toutes Integer) | Sorties |
|---|---|
stock : stock du matin | le stock restant après chaque sortie |
seuil : seuil de réapprovisionnement | « Sortie refusée » si la quantité dépasse le stock |
nbSorties : nombre de sorties | « Commander » ou « Stock suffisant » en fin de journée |
quantite : quantité d'une sortie |
Étape 2 : calculer deux cas à la main. Avant de placer une seule forme, résoudre le problème sur papier. Ces résultats servent de référence : sans eux, rien ne permet de dire si le programme affiche la bonne chose.
- Cas A : stock 40, seuil 15, trois sorties de 12, 8 et 6. Le stock passe à 28, puis 20, puis 14. Comme 14 est inférieur ou égal à 15 : « Commander ».
- Cas B : stock 40, seuil 15, deux sorties de 10 et 5. Le stock passe à 30, puis 25. Comme 25 dépasse 15 : « Stock suffisant ».
Étape 3 : écrire les grandes étapes en français. Lire le stock, le seuil et le nombre de sorties. Pour chaque sortie, lire la quantité ; si elle dépasse le stock, afficher un refus ; sinon, la retirer du stock et afficher le stock. Enfin, comparer le stock final au seuil et afficher la décision.
Étape 4 : repérer les structures. Les mots du besoin désignent les structures. Les cinq structures du parcours sont passées en revue, et celles qui ne servent pas sont écartées explicitement.
| Structure | Indice dans le besoin | Ici |
|---|---|---|
| Séquence | « d'abord…, puis… » | les trois lectures du début |
| Décision | « si… », « est refusée », « s'il faut » | deux losanges : refus d'une sortie, commande |
| Répétition | « à chaque sortie » | un For, car le nombre de sorties est saisi avant la boucle |
| Tableau | « garder la liste des… » | inutile : aucune quantité n'est réutilisée |
| Fonction | un calcul qui revient à plusieurs endroits | inutile : chaque calcul n'apparaît qu'une fois |
Étape 5 : traduire en formes. Chaque phrase du plan devient une ou plusieurs formes, dans le même ordre.
Première version du suivi de stock. La lecture de la quantité est dans la boucle, la décision de commande après.
Étape 6 : exécuter sur les cas calculés à la main. Les saisies proposées sont celles du cas A. Exécuter : la console affiche Stock : 28, Stock : 20, Stock : 14, puis Commander, le résultat calculé à la main. Relancer avec 40, 15, 2, 10 et 5 (cas B) : Stock : 30, Stock : 25, puis Stock suffisant.
Le jeu d'essai
Un jeu d'essai est une liste de saisies, chacune accompagnée de la sortie attendue, calculée à la main avant d'exécuter. Chaque ligne est ensuite exécutée et la sortie obtenue notée à côté : tout écart signale une erreur.
Deux cas qui passent ne prouvent pas grand-chose : ils ont été choisis parmi les situations auxquelles on pensait en dessinant. Un jeu d'essai contient donc trois familles de cas : le cas nominal, une situation ordinaire comme le cas A ; les cas limites, placés exactement sur une frontière du besoin (ici un stock final égal au seuil) et juste à côté ; les cas d'erreur, des saisies hors du domaine prévu (une sortie plus grande que le stock, une quantité négative). Voici celui de la première version, avec un stock de 40, un seuil de 15 et une seule sortie par cas :
| Cas | Quantité | Sortie attendue | Sortie obtenue |
|---|---|---|---|
| Limite : stock final égal au seuil | 25 | Stock : 15, Commander | Stock : 15, Commander |
| Juste au-dessus du seuil | 24 | Stock : 16, Stock suffisant | Stock : 16, Stock suffisant |
| Erreur : sortie supérieure au stock | 50 | Sortie refusée, Stock suffisant | Sortie refusée, Stock suffisant |
| Erreur : quantité négative | -5 | Sortie refusée, Stock suffisant | Stock : 45, Stock suffisant |
La dernière ligne diverge : une quantité de -5 est « retirée » du stock, qui monte à 45. Exécuter l'organigramme précédent avec 40, 15, 1 et -5 pour le constater. Une simple faute de frappe du magasinier fausse l'inventaire. La correction porte sur un seul losange, qui devient quantite <= 0 or quantite > stock : le programme corrigé affiche alors Sortie refusée pour -5, et les trois autres lignes du jeu d'essai donnent toujours la sortie attendue.
Une erreur qui arrête l'exécution se voit tout de suite : variable non déclarée, variable lue avant d'avoir reçu une valeur, + appliqué à du texte, indice hors du tableau. L'exécution s'interrompt. Une erreur de logique, elle, ne produit aucun message : le programme va jusqu'au bout et affiche un résultat faux, comme le stock de 45. Seul un jeu d'essai calculé d'avance la révèle.
Une erreur qui arrête l'exécution : + n'accepte que des nombres, et "Stock : " est du texte. Exécuter : l'exécution s'interrompt à la forme Output, avant tout affichage. Remplacer + par & corrige l'erreur.
Mettre au point : l'exécution pas à pas
Quand une ligne du jeu d'essai diverge, relire l'organigramme du regard mène rarement à l'erreur : on relit ce qu'on croit avoir dessiné. Il faut regarder le programme s'exécuter.
- L'exécution pas à pas avance d'une forme à la fois et surligne la forme en cours ; sur cette page, le bouton « Pas à pas » de chaque organigramme reproduit ce déroulé.
- La fenêtre des variables (Variable Watch) affiche la valeur de chaque variable à cet instant : entiers en bleu, réels en violet, textes en rouge, booléens en bleu-vert.
- La forme Breakpoint suspend temporairement l'exécution là où elle est placée : le programme avance normalement jusqu'à la zone suspecte, puis la fenêtre des variables s'observe à loisir.
La démarche tient en trois temps :
- Prédire : avant chaque forme, noter la valeur que la variable devrait prendre, d'après le calcul à la main.
- Observer : exécuter la forme et lire la fenêtre des variables.
- Repérer la première divergence : la première forme où l'observation diffère de la prédiction. L'erreur est dans cette forme, ou dans une valeur qu'elle utilise et qui a été préparée plus haut.
Exemple : une pression minimale qui vaut 0
Un technicien relève cinq pressions dans un réseau d'air comprimé : 6,2, 5,8, 6,5, 5,4 et 6,0 bars. À la main, la plus faible est 5,4. Le programme suivant affiche pourtant Pression minimale : 0.0 bar.
Une recherche du minimum qui donne un résultat faux. Dérouler en pas à pas en surveillant mini.
| Tour | pression lue | mini prédit après le losange | mini observé |
|---|---|---|---|
| 1 | 6,2 | 6,2 | 0 |
| 2 | 5,8 | 5,8 | 0 |
La divergence apparaît dès le premier tour, au losange : 6.2 < 0 est faux, la branche True n'est pas prise et mini garde sa valeur de départ. Le losange compare pourtant correctement : c'est la valeur qu'il utilise qui est fausse, et elle vient de l'affectation mini ← 0, placée plus haut. Aucune pression n'étant inférieure à 0, le minimum n'est jamais remplacé. La correction consiste à partir d'une valeur réellement mesurée : remplacer mini ← 0 par une lecture de la première pression suivie de mini ← pression, et faire tourner la boucle de 2 à 5. Le programme affiche alors Pression minimale : 5.4 bar.
De l'organigramme au code Python
Flowgorithm convertit un organigramme en code de plusieurs langages réels, dont Python, par le menu Tools > Source Code Viewer. En choisissant Python, le même programme apparaît en texte. Savoir y reconnaître chaque forme prépare directement la suite du parcours.
| Forme Flowgorithm | Python | Ce qui change |
|---|---|---|
| Declare | rien | la variable naît à sa première affectation |
| Input | stock = int(input()) | input() rend du texte : int(...) le convertit en entier, float(...) en réel |
| Output | print(f"Stock : {stock}") | & devient + entre textes, ou une f-string |
| Assign | stock = stock - quantite | la flèche devient = |
| If | if condition: puis else: | chaque branche devient un bloc indenté |
| While | while condition: | le corps est le bloc indenté |
For i = a to b | for i in range(a, b + 1): | la borne de fin de range est exclue |
| Do | pas d'équivalent | un while précédé d'une première lecture |
| Fonction avec variable de retour | def Nom(parametres): et return resultat | le retour est une instruction explicite |
Voici, écrit à la main, un code Python équivalent au suivi de stock corrigé. Le code du Source Code Viewer peut différer dans sa présentation ; la correspondance forme par forme reste la même.
L'indentation remplace les flèches. Le if stock <= seuil: final est aligné sur le for : il est après la boucle. Décalé de quatre espaces, il serait exécuté à chaque sortie.
Fil rouge : la cuve de traitement
La cuve cylindrique de la station (rayon 1,5 m, hauteur 4 m) a été construite par morceaux au fil des chapitres ; il reste à la reprendre avec la méthode, à la tester et à la relire en Python. Entrées et sorties. Le technicien saisit le volume actuel en litres (Real) et l'état de la vanne de sortie (Boolean, true si elle est fermée). Le programme affiche le taux de remplissage, l'état du niveau (« Débordement imminent » au-dessus de 90 %, « Niveau bas » en dessous de 10 %, « Niveau normal » sinon) et l'autorisation de la pompe (taux sous 90 % et vanne fermée). Un volume négatif ou supérieur à la capacité est refusé.
Cas à la main. La capacité vaut π × 1,5² × 4, soit environ 28,27 m³, ou 28 274 litres. Pour 21 000 litres et une vanne fermée, le taux est d'environ 74,3 % : « Niveau normal », « Pompe autorisée ». Étapes et structures. Calculer la capacité ; lire les saisies ; refuser un volume hors limites (décision) ; calculer le taux avec la fonction CalculerTaux ; afficher l'état avec la procédure AfficherEtat, qui ne retourne rien ; décider de la pompe (condition composée).
Le jeu d'essai. Chaque ligne a été calculée avant d'exécuter, puis vérifiée.
| Cas | Saisies | Sorties attendues |
|---|---|---|
| Nominal | 21000, true | Taux : 74.3 %, Niveau normal, Pompe autorisée |
| Niveau haut | 27000, true | Taux : 95.5 %, Débordement imminent, Pompe interdite |
| Niveau bas | 2000, true | Taux : 7.1 %, Niveau bas, Pompe autorisée |
| Erreur : volume négatif | -5, true | Volume hors limites |
| Erreur : au-delà de la capacité | 30000, true | Volume hors limites |
Les cas limites posent une difficulté : à cause de π, un taux d'exactement 10 % ou 90 % ne correspond à aucun nombre rond de litres. Pour tester les frontières, la procédure AfficherEtat s'essaie seule, dans un petit programme qui lit directement le taux.
Programme de test de la procédure AfficherEtat. Saisir successivement 90, 90.1, 10 et 9.9.
Attendu et obtenu : 90 donne Niveau normal, 90,1 donne Débordement imminent, 10 donne Niveau normal, 9,9 donne Niveau bas. Un losange écrit taux >= 90 donnerait toujours Niveau normal sur le cas nominal, mais Débordement imminent pour la saisie 90 : seul le cas limite détecte l'erreur.
Une erreur à localiser. Dans une version où la forme de capacité s'écrit capacite ← pi * 1.5 ^ 2 * 4, le programme affiche Volume hors limites pour 21 000 litres. En pas à pas, la prédiction après cette forme est d'environ 28 274 ; la fenêtre des variables montre environ 28,27. C'est la première divergence : la capacité est restée en m³ alors que le volume est en litres. Le losange qui refuse le volume ne fait que révéler l'écart.
En Python. Les deux fonctions s'écrivent ainsi (code équivalent, écrit à la main) : la variable de retour devient une instruction return, les losanges imbriqués deviennent des blocs indentés.
Exercices type
Un pont provisoire supporte une charge maximale saisie en tonnes. Les véhicules s'y engagent un par un et y restent pendant le relevé ; un capteur transmet la masse de chacun, et une masse de 0 signale la fin du relevé. Concevoir le programme qui déclenche une alarme dès que la masse totale dépasse la charge maximale, puis affiche le nombre de véhicules et la masse totale.
Entrées : chargeMax, puis une suite de masses (Real) terminée par 0. Sorties : « Alarme : surcharge » chaque fois qu'un véhicule fait dépasser la charge, puis une ligne de bilan. Structures : le nombre de véhicules n'est pas connu d'avance, d'où un While, avec une lecture avant la boucle et une lecture à la fin du corps ; un losange sans branche False contrôle la charge.
Jeu d'essai, calculé avant de dessiner, pour une charge maximale de 40 t :
| Cas | Masses saisies | Sorties attendues |
|---|---|---|
| Nominal | 12, 15, 0 | 2 véhicules, 27.0 t |
| Limite : total égal à la charge | 25, 15, 0 | 2 véhicules, 40.0 t, sans alarme |
| Dépassement | 25, 16, 0 | Alarme : surcharge, 2 véhicules, 41.0 t |
| Erreur : masse négative | -3 | 0 véhicules, 0.0 t |
Les saisies proposées sont celles du dépassement. Relancer avec les autres lignes du jeu d'essai.
La condition est total > chargeMax et non >= : le besoin dit « dépasse », et le cas limite à 40 t le vérifie. Le cas d'erreur a forcé une décision que le besoin ne prenait pas : avec masse > 0, une masse négative termine le relevé comme un 0. Écrire le jeu d'essai avant l'organigramme fait surgir ces questions au moment où elles se tranchent le plus facilement.
Recherche de la cellule la plus faible d'une batterie de cinq cellules.
Le programme ci-dessus doit afficher la cellule la plus faible d'une batterie et sa tension. Pour les tensions 3,71, 3,64, 3,69, 3,58 et 3,66 V, il annonce la cellule 5. Localiser l'erreur.
À la main, la tension la plus faible est 3,58 V, celle de la cellule 4. La tension affichée est juste, le numéro faux : l'erreur porte sur cellule. Prédiction et observation de cellule à la fin de chaque tour :
i | tension lue | cellule prédit | cellule observé |
|---|---|---|---|
| 2 | 3,64 | 2 | 2 |
| 3 | 3,69 | 2 | 3 |
La première divergence est au tour i = 3 : la tension 3,69 ne bat pas le minimum, et pourtant cellule change. La forme fautive est cellule ← i, placée après le losange au lieu d'être dans sa branche True : elle s'exécute à chaque tour, et cellule finit égale au dernier indice. Une fois la forme déplacée sous mini ← tension, dans la même branche, le programme affiche Cellule 4 : 3.58 V. Si la cellule la plus faible avait été la dernière, le programme fautif aurait affiché le bon résultat. Un jeu d'essai doit donc placer la valeur cherchée ailleurs qu'en dernière position.
Vérification
1.Devant un besoin écrit en français, que faire avant de placer la première forme ?
2.En Python, qu'est-ce qui remplace les deux flèches d'une forme If ?
3.Une alarme doit se déclencher quand la température est strictement au-dessus de 100 °C. Quel cas limite tester en priorité ?
4.Un programme calcule la surface d'une parcelle et affiche une valeur négative, sans aucun message. De quel type d'erreur s'agit-il ?
5.Comment déclare-t-on une variable en Python ?
6.À quoi sert l'exécution pas à pas ?
7.Comment s'écrit For i = 1 to 10 en Python ?
La méthode
- Lister les entrées et les sorties, avec le type de chaque variable.
- Calculer deux cas à la main, puis écrire les grandes étapes en français.
- Repérer les structures : séquence, décision, répétition, tableau, fonction, en écartant celles qui ne servent pas.
- Traduire en formes, puis exécuter sur les cas calculés à la main.
- Écrire le jeu d'essai avant d'exécuter : cas nominal, cas limites exactement sur les frontières, cas d'erreur.
- Au premier écart, passer en pas à pas : prédire, observer, repérer la première divergence, puis remonter aux valeurs qu'utilise la forme.
- Relire le code Python forme par forme : indentation pour les flèches,
range(a, b + 1)pour unFor, conversion après chaqueinput().
Synthèse
- Un organigramme se conçoit avant de se dessiner : entrées et sorties, cas à la main, étapes, structures.
- Un jeu d'essai associe à chaque saisie une sortie attendue, calculée avant d'exécuter : cas nominal, cas limites, cas d'erreur.
- Une erreur de logique ne produit aucun message : le programme s'exécute et affiche un résultat faux.
- En pas à pas, la première divergence entre prédiction et observation désigne la forme fautive, ou la valeur préparée plus haut qu'elle utilise ; la forme Breakpoint suspend l'exécution là où l'observation doit commencer.
- En Python : pas de déclaration,
int(input())oufloat(input()),print(), l'indentation à la place des flèches,for i in range(a, b + 1)pour unFor,returnpour la valeur d'une fonction.
Mettre en pratique
Du besoin à l'organigramme, jeux d'essai, localiser une erreur, lire le code exporté.
- Compléter un jeu d'essaiNiveau 1
- Localiser l'erreur d'une peséeNiveau 2
- La première divergenceNiveau 2
- Lire un programme PythonNiveau 2
- Trier les colis d'un tapis roulantNiveau 3