Organiser un projet modulaire
Découper serveur, db et utilitaires en modules cohérents.
Objectifs
À la fin de cette leçon, vous saurez :
- découper votre serveur en fichiers aux responsabilités claires ;
- appliquer une arborescence qui grandit sans se dégrader ;
- circuler entre les modules sans dépendances circulaires.
🔗 Pour vous rafraîchir la mémoire : serveur HTTP manuel (createServer)
De monolithe à modules : l'état cible
Partez de votre serveur HTTP manuel (un seul fichier) et visez :
projet/
├── serveur.js ← createServer + listen + appel du routeur
├── routeur.js ← table des routes → handlers
├── taches/
│ ├── handlers.js ← fonctions par route (contrôleur)
│ └── service.js ← règles métier (validation, tri...)
├── db.js ← TOUT l'accès PostgreSQL (repository)
└── http-utilitaires.js ← repondreJSON, lireCorps
Le sens des dépendances est strictement descendant :
serveur → routeur → handlers → service → db
↘ http-utilitaires
Aucune flèche ne remonte : db.js ne connaît ni les routes ni le HTTP. C'est la séparation des préoccupations rendue physique par les fichiers.
La marche à suivre
- Extraire d'abord les utilitaires purs (
repondreJSON,lireCorps) : zéro risque. - Extraire
db.js(déjà fait au chapitre driver) : vérifier que le serveur démarre. - Extraire les handlers : chaque fonction prend
(requete, reponse)et appelle service/db. - Extraire le routeur : il importe les handlers et exporte une fonction
router(requete, reponse). - Le serveur final devient minuscule :
import { createServer } from "node:http";
import { router } from "./routeur.js";
createServer(router).listen(3000);
Détecter une dépendance circulaire
Si handlers.js importe routeur.js ET que le routeur importe les handlers : cycle. Symptôme : import indéfini ou comportement bizarre selon l'ordre de chargement. Remède structurel : extraire ce qu'ils partagent dans un troisième module (souvent le service ou les utilitaires). Les cycles signalent presque toujours une responsabilité mal placée.
Test d'architecture : la règle du commentaire
En tête de chaque fichier, écrivez sa responsabilité en UNE phrase. Puis relisez tous les imports : chaque flèche doit se justifier par cette phrase. Un import qui ne se justifie pas = couplage accidentel à supprimer.
// db.js — TOUT l'accès SQL vit ici ; aucun code HTTP ne doit y apparaître.
Si vous trouvez un repondreJSON dans db.js, l'extraction précédente était incomplète.
Exercice
- Refactorez votre API complète selon cette arborescence ; testez chaque étape avec curl avant de continuer.
- Ajoutez une ressource
users: quels fichiers toucher ? Vérifiez que la liste est courte et prévisible. - Tracez toutes les flèches d'import sur papier : y a-t-il un cycle ? Une flèche qui remonte ?
Résumé
- Un fichier = une responsabilité exprimée en une phrase.
- Dépendances strictement descendantes ; cycles interdits.
- Nouvelle ressource = nouveaux fichiers dans le même motif, jamais du fouillis.
Correction disponibleCherchez d’abord par vous-même.Voir la correction
Correction
Réponses détaillées
Question 2. Fichiers attendus : users/handlers.js, users/service.js, extension de db.js (ou users/db.js), ajout de routes dans routeur.js. Quatre points de contact, toujours les mêmes — c'est la définition d'une architecture qui passe à l'échelle : ajouter ne demande pas de réfléchir OÙ mettre les choses.