1. Introduction aux principes SOLID
Les principes SOLID sont les fondations du développement orienté objet moderne. Ils visent à améliorer la qualité du code, à le rendre plus lisible, modulaire, et facilement testable. Voici un résumé des 5 principes :
| Lettre | Nom | Description |
|---|---|---|
| S | Single Responsibility Principle | Une classe doit avoir une seule responsabilité |
| O | Open/Closed Principle | Ouvert à l’extension, fermé à la modification |
| L | Liskov Substitution Principle | Une sous-classe doit pouvoir remplacer sa classe mère |
| I | Interface Segregation Principle | Préférer plusieurs interfaces spécifiques à une interface générale |
| D | Dependency Inversion Principle | Dépendre d’abstractions, pas de classes concrètes |
2. Les principes SOLID expliqués avec cohérence
2.1 – SRP : Une seule responsabilité
Un service de commande ne devrait pas gérer l’envoi d’email, ni la génération de factures. Chaque classe a une seule tâche.
Mauvais exemple
public class CommandeService {
public void CréerCommande() {}
public void EnvoyerConfirmationEmail() {}
public void GénérerFacture() {}
}
Bon exemple
public class CommandeService {
public void CréerCommande() {}
}
public class EmailService {
public void EnvoyerConfirmationEmail() {}
}
public class FactureService {
public void GénérerFacture() {}
}
2.2 – OCP : Ouvert à l’extension, fermé à la modification
Si on veut ajouter un nouveau type de livraison, on ne devrait pas modifier le service existant.
public class CalculateurLivraison {
public double CalculerFrais(string type) {
if (type == "standard") return 5;
if (type == "express") return 10;
return 0;
}
}
public interface ICalculateurFrais {
double Calculer();
}
public class LivraisonStandard : ICalculateurFrais {
public double Calculer() => 5;
}
public class LivraisonExpress : ICalculateurFrais {
public double Calculer() => 10;
}
2.3 – LSP : Substitution cohérente
Une classe enfant ne doit pas casser les attentes de la classe parent.
public class MoyennePaiement {
public virtual void EffectuerPaiement() {}
}
public class PaiementTest : MoyennePaiement {
public override void EffectuerPaiement() {
throw new NotSupportedException();
}
}
public interface IPaiement {
void EffectuerPaiement();
}
public class PaiementCarte : IPaiement {
public void EffectuerPaiement() {}
}
public class PaiementVirement : IPaiement {
public void EffectuerPaiement() {}
}
2.4 – ISP : Interfaces spécifiques
Les interfaces doivent être courtes et ciblées.
public interface IServiceClient {
void Commander();
void Payer();
void NotifierClient();
}
public interface ICommandable {
void Commander();
}
public interface IPayable {
void Payer();
}
public interface INotifiable {
void NotifierClient();
}
2.5 – DIP : Dépendre d’abstractions
Une classe ne doit pas créer ses dépendances mais les recevoir de l’extérieur.
public class NotificationService {
private EmailService email = new EmailService();
}
public class NotificationService {
private readonly IEmailService _emailService;
public NotificationService(IEmailService emailService) {
_emailService = emailService;
}
}
3. Énoncé de l’exercice
Vous avez un service qui gère la commande, l’envoi d’email, le stockage et la génération de facture. Ce service viole plusieurs principes SOLID. Refactorez-le en respectant chaque principe un par un.
public class CommandeService {
public void CréerCommande() {}
public void EnvoyerEmail() {}
public void SauvegarderCommande() {}
public void GénérerFacture() {}
}
4. Correction étape par étape
Étape 1 – SRP
On sépare chaque action dans sa propre classe.
public class CommandeService { public void CréerCommande() {} }
public class EmailService { public void EnvoyerEmail() {} }
public class FactureService { public void GénérerFacture() {} }
public class CommandeRepository { public void SauvegarderCommande() {} }
Étape 2 – OCP
On permet l’ajout de nouvelles stratégies de facturation sans modifier le code existant.
public interface IStrategieFacture {
void Générer();
}
public class FacturePDF : IStrategieFacture {
public void Générer() {}
}
Étape 3 – LSP
Les classes de notifications respectent l’interface et peuvent être substituées.
public interface INotification {
void Envoyer();
}
public class EmailNotification : INotification {
public void Envoyer() {}
}
Étape 4 – ISP
On découpe les interfaces pour que chaque classe n’implémente que ce dont elle a besoin.
public interface ICommandeService { void CréerCommande(); }
public interface IFacturation { void GénérerFacture(); }
Étape 5 – DIP
On injecte les dépendances via le constructeur plutôt que de les instancier directement.
public class GestionCommande {
private readonly ICommandeService _commande;
public GestionCommande(ICommandeService commande) {
_commande = commande;
}
}
5. Conclusion
Les principes SOLID vous aident à concevoir des architectures logicielles évolutives et robustes. En appliquant ces principes au quotidien, vous améliorez la qualité de vos projets, la collaboration en équipe et la maintenabilité de votre code.

