Article

principes SOLID

Cours complet – Principes SOLID en .NET

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 :

LettreNomDescription
SSingle Responsibility PrincipleUne classe doit avoir une seule responsabilité
OOpen/Closed PrincipleOuvert à l’extension, fermé à la modification
LLiskov Substitution PrincipleUne sous-classe doit pouvoir remplacer sa classe mère
IInterface Segregation PrinciplePréférer plusieurs interfaces spécifiques à une interface générale
DDependency Inversion PrincipleDé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.

Cet article vous a aidé ?

J’accompagne les équipes et les indépendants sur ces sujets : audit d’architecture, formation .NET, développement sur mesure. Parlons de votre besoin.

Réserver un appel découverte — 30 min, gratuit

Sans engagement · Réponse sous 24h ouvrées

← Voir les formations