Numérique et sciences informatiques (spécialité) · TerminaleBac
Modularité et API : cours de Terminale NSI
Publié le 7 novembre 2026 · Mis à jour le 7 novembre 2026 · Signaler une erreur
L'essentiel
- Sur un gros projet, on sépare proprement les différentes parties du programme : c'est le principe de la modularité.3
- Un module regroupe des fonctions et des données liées ; les autres parties du programme l'utilisent par son interface, sans connaître son fonctionnement interne.
- Une API est l'ensemble des fonctions (avec leur spécification) qu'un module met à disposition de ses utilisateurs.
- Une bonne API est petite, documentée (docstring, préconditions, postconditions) et testée ; on peut changer l'intérieur sans toucher aux programmes qui l'utilisent.
- Erreurs classiques : exposer trop de détails, oublier de documenter, mélanger calcul et affichage dans une même fonction.
Pourquoi découper un programme
Quand tu écris un petit script de vingt lignes, tout tient dans ta tête. Quand un projet grossit, ce n'est plus possible : plusieurs personnes y travaillent, le code est relu des mois plus tard, une même fonctionnalité sert à plusieurs endroits. Il faut alors séparer proprement les différentes parties du projet.3
Tu as déjà utilisé cette idée en classe de première : tu as écrit des fonctions, importé des bibliothèques comme math ou random. La modularité est une méthode essentielle de programmation, que l'on reprend ici de façon plus approfondie.2 Ce cours explique ce que cela signifie concrètement, comment on le met en œuvre en Python et comment on décrit ce qu'une partie du programme offre aux autres.
Voici ce que le découpage apporte, raisonnement à l'appui :
- Lisibilité : chaque partie a un rôle précis, que l'on résume en une phrase.3
- Réutilisation : une fonction bien isolée sert dans plusieurs programmes sans être recopiée.
- Travail à plusieurs : deux élèves peuvent écrire deux parties en parallèle, à condition de s'être mis d'accord sur ce que chaque partie offre.3
- Maintenance : si un bogue apparaît, on sait dans quelle partie le chercher.
- Tests : on vérifie chaque partie seule, avant de les assembler.
Les modules en Python
Prenons un fichier geometrie.py :
PI_APPROCHE = 3.14
def aire_disque(r):
return PI_APPROCHE * r * r
def aire_rectangle(longueur, largeur):
return longueur * largeur
Un second fichier, main.py, placé dans le même dossier, peut s'en servir :
import geometrie
print(geometrie.aire_rectangle(4, 3))
print(geometrie.aire_disque(2))
Le préfixe geometrie. indique d'où vient la fonction. On évite ainsi de confondre deux fonctions de même nom venant de modules différents.
Interface et API
On peut comparer un module à un distributeur de boissons. Tu vois les boutons, la fente de paiement et le bac de sortie : c'est l'interface. Tu ignores comment fonctionne le mécanisme intérieur, et tu n'as pas besoin de le savoir. Si le fabricant change le mécanisme en gardant les mêmes boutons, tu continues à utiliser la machine comme avant.
En programmation, c'est exactement le but : celui qui utilise le module ne dépend que de l'API, jamais de la façon dont elle est réalisée.
Concevoir une API : l'exemple de la pile
Mettons tout cela en pratique avec une structure que tu connais : la pile, où l'on empile et dépile des éléments, le dernier arrivé étant le premier sorti. Plaçons-la dans un module pile.py. Pour concevoir une API, on commence par se demander : de quoi un utilisateur a-t-il besoin ? On répond par une liste courte d'opérations.2
Ce programme n'utilise que les cinq fonctions de l'API. Il ne manipule jamais directement la liste p avec p.append ou p[0]. C'est ce qui permet de réécrire le module autrement.
Programmation objet et encapsulation
Le même module peut s'écrire avec une classe. Les données internes sont alors rangées dans l'objet, et les méthodes jouent le rôle des fonctions de l'API.
class Pile:
def __init__(self):
self._elements = []
def est_vide(self):
return len(self._elements) == 0
def empiler(self, x):
self._elements.append(x)
def depiler(self):
assert not self.est_vide()
return self._elements.pop()
def taille(self):
return len(self._elements)
L'utilisateur écrit p = Pile(), puis p.empiler(3). Le nom _elements commence par un tiret bas : il appartient à l'intérieur de la classe, l'API se limite aux méthodes.
Documenter, tester et faire évoluer
Une API n'a de valeur que si elle est comprise et fiable. Deux outils y contribuent : la documentation et les tests.
Exercices corrigés
Exercice 1 Utiliser un module de géométrie
Un module geometrie contient la fonction aire_rectangle(longueur, largeur) qui renvoie le produit des deux paramètres. Un programme l'importe avec import geometrie et exécute :
a = geometrie.aire_rectangle(7, 4)
b = geometrie.aire_rectangle(5, 2)
total = a + b
- Pourquoi les appels commencent-ils par
geometrie.? - Quelle est la valeur de
total?
Indice 1
Le module est importé avec import geometrie : l'appel commence donc par le nom du module et un point.
Indice 2
Calcule d'abord a, puis b, puis additionne.
Voir la correction pas à pas
Avec
import geometrie, la fonction s'appellegeometrie.aire_rectangle(...): le préfixe indique la provenance.Calcul de
a: 7 × 4 = 28.Calcul de
b: 5 × 2 = 10.Somme : total = 28 + 10 = 38.
La valeur de total est 38. Le programme n'a eu besoin que du nom et de la spécification de la fonction, pas de son code interne.
Exercice 2 Suivre une pile à travers son API
On utilise le module pile présenté dans le cours. On exécute :
p = pile.creer()
pile.empiler(p, 4)
pile.empiler(p, 6)
pile.empiler(p, 1)
x = pile.depiler(p)
pile.empiler(p, 9)
y = pile.depiler(p)
pile.empiler(p, x + y)
n = pile.taille(p)
- Quelles sont les valeurs de
xet dey? - Quelle est la valeur de
n? - Quelle opération provoquerait l'échec d'un
assertsi on la répétait trop de fois ?
Indice 1
Le dernier élément empilé est le premier à sortir.
Indice 2
Note l'état de la pile après chaque ligne.
Voir la correction pas à pas
Après les trois premiers empilements, la pile contient 4, 6, 1 (le sommet est 1).
depilerretire le sommet : x = 1. La pile contient 4, 6.On empile 9 : la pile contient 4, 6, 9. Puis
depilerretire 9 : y = 9. La pile contient 4, 6.On empile x + y = 1 + 9 = 10 : la pile contient 4, 6, 10.
taillerenvoie le nombre d'éléments : n = 3.Dépiler une pile vide viole la précondition de
depiler: l'assert not est_vide(p)échoue.
On obtient x = 1, y = 9 et n = 3. Dépiler une pile vide enfreint la précondition de la fonction.
Quiz
5 questions · correction immédiate · ton score reste sur ton appareil.
-
Le découpage répond à un besoin d'organisation : chaque partie a une responsabilité précise.3 Il ne rend pas le programme plus rapide (la vitesse dépend des algorithmes, pas du nombre de fichiers). Les fonctions restent indispensables à l'intérieur des modules, et le but n'est pas de cacher le code mais de le structurer.
-
L'API est la face visible du module : ce qu'on peut appeler, avec quelles données et pour quel résultat. Décrire les instructions internes serait justement l'inverse de l'idée d'interface, qui permet d'utiliser un module sans connaître son intérieur.
-
La précondition est un engagement de l'appelant : il doit fournir des données valables. La fonction ne garantit son résultat que si cette condition est remplie. Que Python accepte l'appel ne prouve rien : un
assertpeut justement signaler la violation. -
Avec
import geometrie, le nom du module préfixe chaque appel. L'aliasas gest permis et raccourcit l'écriture. Tout fichier Python peut servir de module. En revancheimport *est déconseillé : il mélange les noms et peut écraser une fonction par une autre de même nom. -
C'est tout l'intérêt d'une API : les utilisateurs ne dépendent que de ce qu'elle promet. Tant que les spécifications sont respectées, la réalisation interne peut changer. Répondre « Vrai » confondrait l'API avec le code interne, ce qui est précisément l'erreur à éviter.
Les questions qu'on se pose
Quelle est la différence entre un module et une API ?
Le module est le fichier (ou l'ensemble de fichiers) qui contient le code. L'API est la description de ce qu'il propose à l'extérieur : fonctions, paramètres, résultats, conditions d'emploi. Un même module peut avoir des fonctions publiques (dans l'API) et des fonctions internes (hors API).
À quoi sert une docstring, puisque le code est déjà écrit ?
Le code dit comment la fonction travaille ; la docstring dit ce qu'elle promet. Un utilisateur lit la docstring (ou appelle help) sans parcourir le code. Elle fixe aussi le contrat : préconditions à respecter, postconditions garanties.
Faut-il toujours utiliser une classe pour faire une API ?
Non. Un module de fonctions convient très bien, comme le module pile du cours. Une classe est utile quand on veut regrouper des données et les opérations qui les manipulent, et protéger ces données. Le choix dépend du problème, pas d'une obligation.
Comment savoir si mes modules sont bien découpés ?
Pose-toi trois questions. Peut-on résumer le rôle de chaque module en une phrase ? Peut-on le tester sans les autres ? Peut-on changer son intérieur sans modifier les autres modules ? Trois « oui » indiquent un bon découpage. Des modules qui s'importent mutuellement en cercle sont, au contraire, un signal d'alerte.
Que fait `if __name__ == "__main__":` ?
Ce bloc ne s'exécute que lorsque le fichier est lancé directement. Quand un autre programme l'importe, le bloc est ignoré. On y place donc des tests ou une démonstration, sans gêner les utilisateurs du module.
Sources
- Modularité et API — Spécialité NSI Terminale 2024-2025, Lycée La Martinière Diderot (ac-lyon.fr). Consulté le 7 novembre 2026.
- Introduction à la Modularité et API — NSI Terminale 2024-2025, Lycée La Martinière Diderot (ac-lyon.fr). Consulté le 7 novembre 2026.
- Modularité en programmation — NSI Terminale 2026-2027, Lycée La Martinière Diderot (ac-lyon.fr). Consulté le 7 novembre 2026.
Les numéros dans le texte renvoient à ces sources. Une source qui ne dit pas ce qu'on lui fait dire ? Signale-le.