SRP et OCP : les deux premiers principes
Une raison de changer ; étendre sans modifier.
Objectifs
À la fin de cette leçon, vous saurez :
- formuler le Single Responsibility Principle et l'appliquer ;
- comprendre l'Open/Closed Principle et ses exemples concrets.
S — Single Responsibility Principle
Une unité de code doit avoir UNE seule raison de changer.
« Responsabilité » se lit ici « raison de changer » : qui demandera la modification de cette classe ?
// Trois raisons de changer = trois responsabilités = violation
function rapportUtilisateur(user) {
// 1. règle métier (format du nom)
const nom = user.prenom + " " + user.nom.toUpperCase();
// 2. présentation (HTML)
return `<div class="user">${nom}</div>`;
}
Si le marketing change le format, ou si le design change le HTML — deux raisons indépendantes — vous modifiez la même fonction. Découpage honnête :
function nomComplet(user) { ... } // métier
function htmlUtilisateur(nom) { ... } // présentation
Le SRP n'impose pas « une classe = une méthode » : il impose qu'une classe n'ait pas plusieurs clients aux intérêts divergents. C'est la formalisation de la cohésion vue au chapitre 28.
O — Open/Closed Principle
Ouvert à l'extension, fermé à la modification : ajouter un comportement sans réécrire l'existant.
Version fragile :
function calculerFrais(moyen) {
if (moyen === "carte") return 0.29;
if (moyen === "virement") return 0.50;
if (moyen === "paypal") return 0.35; // chaque nouveau moyen = modifier ici
}
Chaque ajout rouvre ce code (et ses tests). Version fermée à la modification :
const FRAIS = {
carte: 0.29,
virement: 0.50,
paypal: 0.35,
};
function calculerFrais(moyen) {
return FRAIS[moyen] ?? null; // nouveau moyen = nouvelle entrée, zéro modification
}
Pour des comportements plus riches, même idée avec des objets interchangeables :
const transporteurs = { standard: new Standard(), express: new Express() };
// ajouter "relais" = ajouter une entrée, jamais toucher calculerLivraison()
Les deux principes en pratique
| Principe | Question à se poser | Signal d'alerte |
|---|---|---|
| SRP | Qui va demander ce changement ? | « et » dans la description |
| OCP | Puis-je étendre sans rouvrir ? | if/else qui s'allonge à chaque évolution |
Exercice
- Identifiez les violations SRP :
class FactureService { calculerTVA(); envoyerEmail(); genererPdf(); }. - Refactorez le calculateur de frais pour supporter
cryptosans modifier la fonction. - Dans votre API todo : quelles sont les raisons de changer du contrôleur ? Du repository ?
Résumé
- SRP : une raison de changer par unité ; découpe par clients distincts.
- OCP : extension par ajout de données/composants, pas par édition du cœur.
- Les deux préparent directement NestJS (services spécialisés injectés).
Correction disponibleCherchez d’abord par vous-même.Voir la correction
Correction
Réponses détaillées
Question 1. Trois clients distincts (comptabilité, marketing, juridique sur les PDF) → trois classes : TvaService, NotificationService, PdfService ; FactureService orchestre seulement.
Question 3. Le contrôleur change si : routes nouvelles, format d'entrée/sortie, règles de statut. Le repository si : requêtes SQL, schéma, optimisations. Deux raisons disjointes = deux fichiers séparés : votre db.js respectait déjà le SRP sans le savoir.