Injection de dépendances manuelle
Un point d’assemblage unique et substituable.
Objectifs
À la fin de cette leçon, vous saurez :
- composer un graphe d'objets à la main, du repository au contrôleur ;
- substituer des implémentations sans toucher aux classes ;
- préparer mécaniquement NestJS.
🔗 Pour vous rafraîchir la mémoire : modules : import/export · Pool pg et requêtes paramétrées ($1, $2)
Le graphe de dépendances
Votre application a une chaîne naturelle :
UserController
↓ dépend de
UserService
↓ dépend de
UserRepository
↓ dépend de
Pool PostgreSQL
La question DIP (chapitre précédent) : qui construit quoi ? Réponse : personne ne se construit lui-même — UN point unique assemble tout :
// main.js — la racine qui connaît TOUT
import { Pool } from "pg";
import { UserRepository } from "./user-repository.js";
import { UserService } from "./user-service.js";
import { UserController } from "./user-controller.js";
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const userRepository = new UserRepository(pool);
const userService = new UserService(userRepository);
const controller = new UserController(userService);
controller.enregistrerRoutes(serveur);
Chaque classe reçoit ses collaborateurs par constructeur ; le sens de lecture est limpide : controller → service → repo → pool. C'est l'injection de dépendances manuelle — trois lignes d'assemblage, zéro framework.
Ce que ça change concrètement
Tests instantanés :
const fakeRepo = {
creer: async (d) => ({ id: 1, ...d }),
};
const service = new UserService(fakeRepo); // pas de base, pas de réseau
Substitution en production :
new UserService(new PgUserRepository(pool)); // prod
new UserService(new FileUserRepository("./data.json")); // environnement léger
Le service n'a JAMAIS changé pendant ces substitutions : il dépend d'un contrat implicite (« quelque chose avec creer/trouver »), pas d'une implémentation.
La règle d'or de l'assemblage
Les classes ne créent PAS leurs dépendances ; elles les REÇOVENT.
Un seul endroit (le point d'entrée) connaît les constructions.
Symptôme de violation à traquer : new dans le corps d'une classe métier (hors DTO/objets-valeurs). Chaque new interne fige une implémentation et enterre un couplage que les tests paieront.
Vers l'automatisation
À dix services, votre main.js devient un registre verbeux mais toujours simple. NestJS résoudra cette verbosité : vous décorerez les classes (@Injectable()), listerez les modules, et le conteneur fabriquera le graphe seul — en résolvant exactement ce même ordre controller → service → repo. Vous saurez donc TOUJOURS lire ce qu'il fait derrière.
Exercice
- Assemblez manuellement votre todo API : db.js → TaskService → routes.
- Écrivez un test du service avec un fake repository.
- Traquez tous les
newinternes de vos classes métier : lesquels sont légitimes ?
Résumé
- Un point d'assemblage unique ; les classes reçoivent par constructeur.
- Substitution = paramètre différent, zéro modification des classes.
- Le conteneur NestJS automatisera ce graphe que vous savez déjà écrire.
Correction disponibleCherchez d’abord par vous-même.Voir la correction
Correction
Réponses détaillées
Question 3. Légitimes : objets-valeurs créés pour soi ({id: Date.now()}), erreurs spécialisées (throw new ErreurValidation()). Illégitimes : repositories, clients HTTP, connexions — tout ce qui touche l'extérieur ou porte une logique substituable.