La modularité : découper un algorithme
Ce que ce chapitre apporte 5 points
- Définir un module, et distinguer un bon découpage d'un mauvais.
- Organiser un programme en fonctions cohérentes, reliées par leurs seuls paramètres et valeurs de retour.
- Décomposer un problème réel du haut vers le bas : le programme principal d'abord, les fonctions ensuite.
- Concevoir une décomposition hiérarchique, et nommer ce qu'elle interdit.
- Écrire ce qu'un module suppose de ses entrées.
Un programme qui tient en une page se lit. Un programme qui tient en dix ne se lit plus, sauf s'il est découpé. Celui qui surveille la chambre froide d'un entrepôt doit lire les relevés d'un capteur, écarter ceux qu'il a perdus, calculer une moyenne et compter les dépassements de seuil : écrit d'un seul bloc, il mêle tout, et une correction apportée à la moyenne peut casser le comptage sans que rien ne le signale. La modularité consiste à répartir le travail entre des morceaux nommés, les modules, qui font chacun une seule chose et se vérifient chacun à part, puis à écrire un programme principal qui se contente de les enchaîner. Où couper, et à quoi reconnaître un bon découpage ? C'est la différence entre un tas d'instructions et un programme qu'on peut reprendre six mois plus tard.
Le chapitre suppose acquis les fonctions et leurs paramètres : un module n'est rien d'autre qu'une fonction, qui ne communique que par ses paramètres et sa valeur de retour. Les relevés circulent d'un module à l'autre dans des tableaux.
Pourquoi décomposer un programme ?
La décomposition consiste à séparer un problème complexe en sous-problèmes plus simples, et à confier chacun à un module. Chaque module peut ensuite être écrit, testé et corrigé indépendamment des autres.
Un programme complet peut être vu comme une machine composée de plusieurs engrenages : chaque engrenage joue un rôle précis, et l'ensemble ne fonctionne que si chaque partie fait bien son travail. Pour un programme de contrôle qualité en sortie d'une ligne d'ensachage, par exemple :
- un module lit la masse de chaque sachet ;
- un autre calcule la masse moyenne ;
- un troisième affiche le résultat.
Cette approche permet de raisonner par étapes, et de chercher une erreur dans un module de dix lignes plutôt que dans un programme de cent.
« Puis-je expliquer mon algorithme en trois ou quatre grandes étapes claires ? » Si oui, chacune est un module en puissance. Si non, le problème n'est pas encore compris.
Pourquoi découper un programme en modules ?
Qu'est-ce qu'un module ?
Dans ce cours, un module est une fonction qui remplit une tâche précise, et une seule : lire les mesures, calculer une moyenne, afficher un résultat. Qu'elle rende une valeur ou se contente d'agir ne change rien à ce rôle. En Python, le mot désigne un fichier qui regroupe plusieurs fonctions, comme math : c'est la même idée, à une autre échelle.
Voici le programme de contrôle qualité, découpé en trois modules :
programme principal
aucune variable
Le programme principal se limite à enchaîner des modules : la lecture, le calcul et l'affichage. Chaque fonction fait une seule chose, et son nom suffit à le dire : un module qu'on ne peut nommer sans « et » en fait deux.
- Principal vers LireMesures : appel sans argument.
- LireMesures vers Principal, en réponse : le tableau des masses.
- Principal vers Moyenne : le tableau.
- Moyenne vers Principal, en réponse : la moyenne.
- Principal vers AfficherResultat : la moyenne. Note : aucune flèche ne relie deux modules entre eux.
Toutes les flèches partent du programme principal ou y reviennent. Aucun module n'en appelle un autre, et aucune donnée ne circule autrement que par un argument ou une valeur retournée. C'est cette forme en étoile qui rend chaque module utilisable ailleurs, tel quel.
LireMesures construit le tableau et le retourne ; le programme principal le range dans masses et le passe à Moyenne. À aucun moment les deux fonctions ne partagent une variable.
On pourrait croire plus simple de ranger le tableau dans une variable que les deux fonctions liraient directement, ce que certains langages permettent. On gagnerait quelques caractères, et l'on perdrait la propriété qui fait tout l'intérêt du découpage : Moyenne se relit, se teste et se remplace sans savoir qui l'appelle ni d'où vient le tableau. Parce qu'elle parcourt longueur(t) cases, elle calcule la moyenne de n'importe quel tableau de nombres, de cinq sachets comme de cinq cents, et rien d'autre.
1.Deux modules doivent échanger une information. Comment ?
2.Qu'est-ce qui distingue un bon découpage d'un mauvais ?
Communication entre modules
Les modules échangent des données à l'aide de paramètres (les entrées) et de valeurs de retour (les sorties). C'est ce qui permet à chaque fonction de travailler indépendamment tout en participant à la résolution du problème. Un module peut aussi en appeler un autre, pourvu que tout passe par ces deux portes :
programme principal
Le programme principal lit les données, AfficherLigne met en forme une ligne de facture, et Montant effectue le calcul, sans rien lire ni rien afficher. Chacune se teste seule, et Montant resservira pour le total d'une commande entière.
L'erreur consiste à chercher à faire communiquer deux modules par une variable du programme principal. Une variable créée dans une fonction n'existe que dans cette fonction et disparaît quand elle se termine ; une variable du programme principal n'est pas visible non plus depuis une fonction. Dans la convention de ce cours, aucune variable n'est donc commune à deux modules. D'autres langages en admettent, sous le nom de variables globales : Python laisse une fonction lire une variable du programme principal. C'est précisément la dépendance invisible que ce chapitre demande d'éviter.
Le chapitre précédent en donne la démonstration déroulable, dans les deux sens : un algorithme qui réclame, après l'appel, une variable ayant appartenu à la fonction, et une fonction qui réclame une variable du programme principal. Les deux s'arrêtent net à la ligne fautive ; le chapitre Les fonctions et leurs paramètres les contient, et il n'y a pas lieu de les refaire ici.
Ce qui traverse la frontière, c'est ce que Retourner rend, et rien d'autre. Une variable de travail n'a pas à survivre : c'est même ce qui permet à deux modules d'employer le nom i ou somme sans jamais se gêner.
Un même traitement apparaît à trois endroits. Que faire ?
La décomposition hiérarchique
La figure en étoile n'est pas la seule forme possible, et ce n'est pas la plus fréquente. Dès qu'un problème dépasse trois ou quatre étapes, un module se découpe à son tour, et l'on obtient un arbre, ou presque : le programme principal appelle des modules, qui en appellent de plus petits, et une brique commune peut servir à deux parents.
ControlerLotle programme principalLireMassespèse chaque sachet du lotEtablirBilanproduit la moyenne et le verdictMoyennemoyenne d'un tableauCompterConformessachets dans la toléranceEstConformeune masse est-elle entre 495 et 505 gAfficherRapportmet en forme et écritFormaterLigneune ligne du rapportCe qui est permis et ce qui ne l'est pas tient en deux règles.
Un module appelle ce qui est en dessous de lui, jamais au-dessus. CompterConformes peut appeler EstConforme ; EstConforme ne doit rien savoir de CompterConformes, ni du lot, ni du rapport. C'est ce qui permet de réutiliser EstConforme dans un tout autre programme.
Aucun cycle. Si A appelle B et que B finit par rappeler A, le découpage est faux : les deux modules n'en forment qu'un, mal coupé, et aucun des deux ne se teste seul. La seule exception courante est la récursivité, où une fonction s'appelle elle-même volontairement, sujet du chapitre suivant.
La profondeur se lit comme un sommaire : chaque niveau répond à la question « comment ? » posée au niveau du dessus, et chaque niveau du dessus répond au « pourquoi ? » du dessous.
programme principal
CompterConformes qui attend à son tour, et EstConforme qui travaille. Le troisième naît et meurt quatre fois, une par sachet examiné. Remarquer surtout que EstConforme ne voit ni t, ni c, ni i : elle reçoit un nombre et rend un booléen, ce qui est tout ce qu'il faut savoir d'elle pour l'employer ailleurs.
Dans une décomposition hiérarchique, qu'est-ce qui est interdit ?
Décomposer un problème réel, du haut vers le bas
Dans la convention de ce cours, un programme découpé s'écrit dans un ordre fixe : d'abord les fonctions, chacune entre Fonction et FinFonction, puis le programme principal entre Début et Fin, qui se contente de les appeler. Il n'y a pas de partie réservée aux déclarations : une variable naît à sa première affectation. L'ordre de lecture est l'inverse : on lit d'abord le programme principal, comme une table des matières, puis on ne descend que dans les fonctions dont on a besoin, comme on ouvre un chapitre.
Un programme se conçoit lui aussi dans l'ordre inverse de celui où il s'écrit. Le découpage ne se trouve pas en écrivant les fonctions : il se trouve en écrivant d'abord ce qu'on voudrait pouvoir appeler.
Soit une chambre froide dont un capteur relève la température toutes les heures. Quand il perd la mesure, il écrit -99. On veut la température moyenne de la journée et le nombre de relevés au-dessus de 5 degrés, seuil au-delà duquel la marchandise se dégrade.
Le programme principal d'abord, comme si les fonctions existaient. Il tient en quelques lignes et se lit comme l'énoncé : afficher la moyenne des relevés, afficher le nombre de dépassements.
Cette esquisse ne s'exécute pas encore, puisque rien n'y est défini : elle fixe seulement ce qu'il faudra écrire.
Les en-têtes ensuite, avec leurs portes. L'esquisse fait apparaître deux fonctions : MoyenneValides reçoit un tableau et rend un nombre, CompterDepassements reçoit un tableau et un seuil et rend un entier.
Les corps enfin, et ce qu'ils ont en commun. En les écrivant, on s'aperçoit que les deux fonctions doivent écarter les -99 : ce besoin commun devient une troisième fonction, EstValide, que les deux appellent. Chaque fonction s'écrit alors seule, et se vérifie seule, avant l'assemblage.
programme principal
Déroulée, la figure affiche une moyenne de 4,8 degrés et deux dépassements, et trois encadrés sont ouverts à la fois chaque fois qu'EstValide travaille pour l'une ou l'autre fonction. EstValide a deux parents : ce n'est pas un défaut, c'est la réutilisation que le découpage promettait.
La première ligne de MoyenneValides n'est pas une instruction mais une hypothèse, écrite en commentaire : la fonction suppose au moins un relevé valide, faute de quoi n resterait à zéro et elle diviserait par zéro. L'écrire n'est pas une politesse. Un module qui marche seul et échoue une fois assemblé a presque toujours reçu ce qu'il ne prévoyait pas ; l'hypothèse écrite dit à celui qui l'appelle ce qu'il doit garantir.
Un module fonctionne seul mais échoue une fois assemblé. La cause la plus probable ?
Mettre en pratique
Un découpage se lit aussi en nombres : ce que chaque module rend, combien de fois il est appelé, et combien de cadres s'empilent quand le plus petit travaille.
Ce que les modules rendent, et combien de fois ils sont appelés
- 1.
Le programme de la chambre froide reçoit le relevé
[4.5, -99, 6.5, 3, 5.5, -99]. Que rendMoyenneValides, en degrés ? - 2.
Pendant tout ce programme, combien de fois la fonction
EstValideest-elle appelée ? - 3.
Dans la décomposition du contrôle qualité dessinée en arbre, combien de cadres la pile compte-t-elle au plus, programme principal compris, quand
EstConformetravaille ? - 4.
Un lot compte 250 sachets. Combien d'appels de fonction
CompterConformes(masses)déclenche-t-il en tout, le sien compris ? - 5.
Avec
Montant(prix, quantite), quel est le total en euros d'une commande de trois lignes : 4 pièces à 12,5 euros, 10 à 3,2 euros et 2 à 45 euros ?
Le but n'est pas d'écrire le programme le plus court, mais celui dont chaque morceau fait une seule chose et porte un nom qui le dit.
Écrire un programme modulaire qui lit la masse de plusieurs sachets, calcule leur masse moyenne, puis affiche « Lot conforme » si elle est comprise entre 495 et 505 grammes, « Lot à reprendre » sinon.
Trois responsabilités, donc trois modules, et un programme principal qui se contente de les enchaîner.
programme principal
aucune variable
Le Début se lit comme une phrase, sans avoir à regarder le détail des fonctions. C'est exactement ce que la modularité achète. Moyenne est celle du programme de la section « Qu'est-ce qu'un module ? », reprise telle quelle : c'est la réutilisation, sur un autre nombre de sachets.
Peut-on nommer chaque module en quelques mots, sans « et » ? Un verbe pour ce qui agit (LireMasses, AfficherVerdict), ce qu'elle rend pour ce qui calcule (Moyenne, EstConforme). Si l'on doit écrire LireEtCalculer, c'est que le module en fait deux et qu'il faut le couper.
Écrire un programme modulaire qui lit la longueur et la largeur d'une plaque à découper, et affiche son périmètre et sa surface, chaque calcul étant effectué dans une fonction distincte.
programme principal
aucune variable
Ce que Écrire a affiché
Longueur : Perimetre et Surface ne lisent rien et n'affichent rien : elles calculent, et c'est tout. Ce sont les fonctions les plus faciles à réutiliser, parce qu'elles ne dépendent de rien d'autre que de leurs paramètres.
Mettre le Lire à l'intérieur de Surface. La fonction devient alors inutilisable ailleurs : impossible de calculer la surface de deux dimensions déjà connues sans les ressaisir. Une fonction qui calcule ne doit ni lire ni afficher.
Chapitre révisé en octobre 2026 · Une erreur dans ce chapitre ?
Dans la bibliothèque d'exercices
Découper par tâche, ce qui circule entre les modules, et ce qui rend un module réutilisable.
- Découper par tâche2 · Appliquer
- Ce qui circule entre les modules3 · Combiner
- Le module qui lit au clavier3 · Combiner
- Un module par étape5 · Concevoir
- La valeur qui n'est pas passée4 · Analyser
- Le module qui rend sa valeur3 · Combiner