Aller au contenu principal

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

Le besoin, point de départ de la méthode

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 matinle 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.

StructureIndice dans le besoinIci
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
Fonctionun calcul qui revient à plusieurs endroitsinutile : 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.

Organigramme, tel que l'affiche Flowgorithm
Exécuter comme dans Flowgorithm, en continu ou forme par forme.
FalseTrueNextDoneFalseTrueMainInteger stock, seuil, nbSorties, i, quantiteInput stockInput seuilInput nbSortiesi = 1 to nbSortiesInput quantitequantite > stockstock = stock - quantiteOutput "Stock : " & stockOutput "Sortie refusée"stock <= seuilOutput "Stock suffisant"Output "Commander"End

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

Définition

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 :

CasQuantitéSortie attendueSortie obtenue
Limite : stock final égal au seuil25Stock : 15, CommanderStock : 15, Commander
Juste au-dessus du seuil24Stock : 16, Stock suffisantStock : 16, Stock suffisant
Erreur : sortie supérieure au stock50Sortie refusée, Stock suffisantSortie refusée, Stock suffisant
Erreur : quantité négative-5Sortie refusée, Stock suffisantStock : 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.

Un programme qui s'exécute sans erreur peut être faux

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.

Organigramme, tel que l'affiche Flowgorithm
Exécuter comme dans Flowgorithm, en continu ou forme par forme.
MainInteger stock, quantiteInput stockInput quantitestock = stock - quantiteOutput "Stock : " + stockEnd

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 :

  1. Prédire : avant chaque forme, noter la valeur que la variable devrait prendre, d'après le calcul à la main.
  2. Observer : exécuter la forme et lire la fenêtre des variables.
  3. 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.

Organigramme, tel que l'affiche Flowgorithm
Exécuter comme dans Flowgorithm, en continu ou forme par forme.
FalseTrueNextDoneMainReal pression, miniInteger imini = 0i = 1 to 5Input pressionpression < minimini = pressionOutput "Pression minimale : " & ToFixed(mini, 1) & " bar"End

Une recherche du minimum qui donne un résultat faux. Dérouler en pas à pas en surveillant mini.

Tourpression luemini prédit après le losangemini observé
16,26,20
25,85,80

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 FlowgorithmPythonCe qui change
Declarerienla variable naît à sa première affectation
Inputstock = int(input())input() rend du texte : int(...) le convertit en entier, float(...) en réel
Outputprint(f"Stock : {stock}")& devient + entre textes, ou une f-string
Assignstock = stock - quantitela flèche devient =
Ifif condition: puis else:chaque branche devient un bloc indenté
Whilewhile condition:le corps est le bloc indenté
For i = a to bfor i in range(a, b + 1):la borne de fin de range est exclue
Dopas d'équivalentun while précédé d'une première lecture
Fonction avec variable de retourdef Nom(parametres): et return resultatle 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.

main.py
Sortie
>_ Prêt à exécuter…

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).

Organigramme, tel que l'affiche Flowgorithm
Exécuter comme dans Flowgorithm, en continu ou forme par forme.
FalseTrueFalseTrueFalseTrueFalseTrueMainReal capacite, volume, tauxBoolean vanneFermeecapacite = pi * 1.5 ^ 2 * 4 * 1000Input volumeInput vanneFermeevolume < 0 or volume > capacitetaux = CalculerTaux(volume, capacite)Output "Taux : " & ToFixed(taux, 1) & " %"AfficherEtat(taux)taux < 90 and vanneFermeeOutput "Pompe interdite"Output "Pompe autorisée"Output "Volume hors limites"EndCalculerTauxReal resultatresultat = volume / capacite * 100Return resultatAfficherEtattaux > 90taux < 10Output "Niveau normal"Output "Niveau bas"Output "Débordement imminent"End

Le jeu d'essai. Chaque ligne a été calculée avant d'exécuter, puis vérifiée.

CasSaisiesSorties attendues
Nominal21000, trueTaux : 74.3 %, Niveau normal, Pompe autorisée
Niveau haut27000, trueTaux : 95.5 %, Débordement imminent, Pompe interdite
Niveau bas2000, trueTaux : 7.1 %, Niveau bas, Pompe autorisée
Erreur : volume négatif-5, trueVolume hors limites
Erreur : au-delà de la capacité30000, trueVolume 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.

Organigramme, tel que l'affiche Flowgorithm
Exécuter comme dans Flowgorithm, en continu ou forme par forme.
FalseTrueFalseTrueMainReal tauxInput tauxAfficherEtat(taux)EndAfficherEtattaux > 90taux < 10Output "Niveau normal"Output "Niveau bas"Output "Débordement imminent"End

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.

main.py
Sortie
>_ Prêt à exécuter…

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 :

CasMasses saisiesSorties attendues
Nominal12, 15, 02 véhicules, 27.0 t
Limite : total égal à la charge25, 15, 02 véhicules, 40.0 t, sans alarme
Dépassement25, 16, 0Alarme : surcharge, 2 véhicules, 41.0 t
Erreur : masse négative-30 véhicules, 0.0 t
Organigramme, tel que l'affiche Flowgorithm
Exécuter comme dans Flowgorithm, en continu ou forme par forme.
FalseTrueTrueFalseMainReal chargeMax, masse, totalInteger nbVehiculesInput chargeMaxtotal = 0nbVehicules = 0Input massemasse > 0nbVehicules = nbVehicules + 1total = total + massetotal > chargeMaxOutput "Alarme : surcharge"Input masseOutput nbVehicules & " véhicules, " & ToFixed(total, 1) & " t"End

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.

Organigramme, tel que l'affiche Flowgorithm
FalseTrueNextDoneMainReal tension, miniInteger i, celluleInput tensionmini = tensioncellule = 1i = 2 to 5Input tensiontension < minimini = tensioncellule = iOutput "Cellule " & cellule & " : " & ToFixed(mini, 2) & " V"End

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 :

itension luecellule préditcellule observé
23,6422
33,6923

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

Vérification rapideon peut se reprendre

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

  1. Lister les entrées et les sorties, avec le type de chaque variable.
  2. Calculer deux cas à la main, puis écrire les grandes étapes en français.
  3. Repérer les structures : séquence, décision, répétition, tableau, fonction, en écartant celles qui ne servent pas.
  4. Traduire en formes, puis exécuter sur les cas calculés à la main.
  5. Écrire le jeu d'essai avant d'exécuter : cas nominal, cas limites exactement sur les frontières, cas d'erreur.
  6. Au premier écart, passer en pas à pas : prédire, observer, repérer la première divergence, puis remonter aux valeurs qu'utilise la forme.
  7. Relire le code Python forme par forme : indentation pour les flèches, range(a, b + 1) pour un For, conversion après chaque input().

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()) ou float(input()), print(), l'indentation à la place des flèches, for i in range(a, b + 1) pour un For, return pour la valeur d'une fonction.

Mettre en pratique