Principes SOLID en Java

Les principes SOLID sont des bonnes pratiques en programmation orientée objet qui permettent d'avoir un code plus modulaire, maintenable et extensible. 1️⃣ S - Principe de Responsabilité Unique (Single Responsibility Principle - SRP) Une classe ne doit avoir qu'une seule raison de changer. ❌ Mauvais exemple (Violation du SRP) Une classe qui gère les informations du salarié et le calcul de la paie : class Employe { private String nom; private double salaire; public Employe(String nom, double salaire) { this.nom = nom; this.salaire = salaire; } public void genererFichePaie() { System.out.println("Fiche de paie générée pour " + nom); } } ✅ Bon exemple (Respect du SRP) Séparer les responsabilités : class Employe { private String nom; private double salaire; public Employe(String nom, double salaire) { this.nom = nom; this.salaire = salaire; } } class PaieService { public void genererFichePaie(Employe employe) { System.out.println("Fiche de paie générée pour " + employe.getNom()); } } 2️⃣ O - Principe Ouvert/Fermé (Open/Closed Principle - OCP) Une classe doit être ouverte à l'extension mais fermée à la modification. ❌ Mauvais exemple Ajouter une nouvelle réduction oblige à modifier le code existant : class Facture { public double calculerRemise(double montant, String typeClient) { if (typeClient.equals("VIP")) { return montant * 0.9; } else if (typeClient.equals("Fidèle")) { return montant * 0.95; } return montant; } } ✅ Bon exemple (Respect de l’OCP) Utilisation du polymorphisme : interface Remise { double appliquerRemise(double montant); } class RemiseVIP implements Remise { public double appliquerRemise(double montant) { return montant * 0.9; } } class Facture { public double appliquerRemise(double montant, Remise remise) { return remise.appliquerRemise(montant); } } 3️⃣ L - Principe de Substitution de Liskov (Liskov Substitution Principle - LSP) Une classe dérivée doit pouvoir remplacer sa classe mère sans effet indésirable. ❌ Mauvais exemple Un carré ne peut pas toujours remplacer un rectangle : class Rectangle { protected int largeur, hauteur; public void setLargeur(int largeur) { this.largeur = largeur; } public void setHauteur(int hauteur) { this.hauteur = hauteur; } } class Carre extends Rectangle { @Override public void setLargeur(int largeur) { this.largeur = this.hauteur = largeur; } } ✅ Bon exemple Utiliser des classes distinctes : interface Forme { int getAire(); } class Rectangle implements Forme { private int largeur, hauteur; public int getAire() { return largeur * hauteur; } } class Carre implements Forme { private int cote; public int getAire() { return cote * cote; } } 4️⃣ I - Principe de Ségrégation des Interfaces (Interface Segregation Principle - ISP) Une classe ne doit pas être forcée à implémenter des méthodes inutiles. ❌ Mauvais exemple Une interface trop large : interface Oiseau { void voler(); void nager(); } class Pingouin implements Oiseau { public void voler() { throw new UnsupportedOperationException(); } public void nager() { System.out.println("Le pingouin nage"); } } ✅ Bon exemple Créer plusieurs interfaces : interface OiseauVolant { void voler(); } interface OiseauMarin { void nager(); } class Aigle implements OiseauVolant { public void voler() { System.out.println("L'aigle vole"); } } class Pingouin implements OiseauMarin { public void nager() { System.out.println("Le pingouin nage"); } } 5️⃣ D - Principe d'Inversion des Dépendances (Dependency Inversion Principle - DIP) Une classe doit dépendre d’abstractions et non d’implémentations concrètes. ❌ Mauvais exemple Dépendance directe à une implémentation : class MySQLDatabase { public void sauvegarderCommande(String commande) { System.out.println("Commande enregistrée en MySQL"); } } class ServiceCommande { private MySQLDatabase db = new MySQLDatabase(); public void traiterCommande(String commande) { db.sauvegarderCommande(commande); } } ✅ Bon exemple Utiliser une interface pour découpler : interface BaseDeDonnees { void sauvegarderCommande(String commande); } class MySQLDatabase implements BaseDeDonnees { public void sauvegarderCommande(String commande) { System.out.println("Commande enregistrée en MySQL"); } } class ServiceCommande { private BaseDeDonnees db; public ServiceCommande(BaseDeDonnees db) { this.db = db; } public void traiterCommande(String commande) { db.sauvegarderCommande(commande)

Feb 27, 2025 - 00:05
 0
Principes SOLID en Java

Les principes SOLID sont des bonnes pratiques en programmation orientée objet qui permettent d'avoir un code plus modulaire, maintenable et extensible.

1️⃣ S - Principe de Responsabilité Unique (Single Responsibility Principle - SRP)

Une classe ne doit avoir qu'une seule raison de changer.

❌ Mauvais exemple (Violation du SRP)

Une classe qui gère les informations du salarié et le calcul de la paie :

class Employe {
    private String nom;
    private double salaire;

    public Employe(String nom, double salaire) {
        this.nom = nom;
        this.salaire = salaire;
    }

    public void genererFichePaie() {
        System.out.println("Fiche de paie générée pour " + nom);
    }
}

✅ Bon exemple (Respect du SRP)

Séparer les responsabilités :

class Employe {
    private String nom;
    private double salaire;

    public Employe(String nom, double salaire) {
        this.nom = nom;
        this.salaire = salaire;
    }
}

class PaieService {
    public void genererFichePaie(Employe employe) {
        System.out.println("Fiche de paie générée pour " + employe.getNom());
    }
}

2️⃣ O - Principe Ouvert/Fermé (Open/Closed Principle - OCP)

Une classe doit être ouverte à l'extension mais fermée à la modification.

❌ Mauvais exemple

Ajouter une nouvelle réduction oblige à modifier le code existant :

class Facture {
    public double calculerRemise(double montant, String typeClient) {
        if (typeClient.equals("VIP")) {
            return montant * 0.9;
        } else if (typeClient.equals("Fidèle")) {
            return montant * 0.95;
        }
        return montant;
    }
}

✅ Bon exemple (Respect de l’OCP)

Utilisation du polymorphisme :

interface Remise {
    double appliquerRemise(double montant);
}

class RemiseVIP implements Remise {
    public double appliquerRemise(double montant) {
        return montant * 0.9;
    }
}

class Facture {
    public double appliquerRemise(double montant, Remise remise) {
        return remise.appliquerRemise(montant);
    }
}

3️⃣ L - Principe de Substitution de Liskov (Liskov Substitution Principle - LSP)

Une classe dérivée doit pouvoir remplacer sa classe mère sans effet indésirable.

❌ Mauvais exemple

Un carré ne peut pas toujours remplacer un rectangle :

class Rectangle {
    protected int largeur, hauteur;

    public void setLargeur(int largeur) { this.largeur = largeur; }
    public void setHauteur(int hauteur) { this.hauteur = hauteur; }
}

class Carre extends Rectangle {
    @Override
    public void setLargeur(int largeur) {
        this.largeur = this.hauteur = largeur;
    }
}

✅ Bon exemple

Utiliser des classes distinctes :

interface Forme {
    int getAire();
}

class Rectangle implements Forme {
    private int largeur, hauteur;
    public int getAire() { return largeur * hauteur; }
}

class Carre implements Forme {
    private int cote;
    public int getAire() { return cote * cote; }
}

4️⃣ I - Principe de Ségrégation des Interfaces (Interface Segregation Principle - ISP)

Une classe ne doit pas être forcée à implémenter des méthodes inutiles.

❌ Mauvais exemple

Une interface trop large :

interface Oiseau {
    void voler();
    void nager();
}

class Pingouin implements Oiseau {
    public void voler() { throw new UnsupportedOperationException(); }
    public void nager() { System.out.println("Le pingouin nage"); }
}

✅ Bon exemple

Créer plusieurs interfaces :

interface OiseauVolant { void voler(); }
interface OiseauMarin { void nager(); }

class Aigle implements OiseauVolant {
    public void voler() { System.out.println("L'aigle vole"); }
}

class Pingouin implements OiseauMarin {
    public void nager() { System.out.println("Le pingouin nage"); }
}

5️⃣ D - Principe d'Inversion des Dépendances (Dependency Inversion Principle - DIP)

Une classe doit dépendre d’abstractions et non d’implémentations concrètes.

❌ Mauvais exemple

Dépendance directe à une implémentation :

class MySQLDatabase {
    public void sauvegarderCommande(String commande) {
        System.out.println("Commande enregistrée en MySQL");
    }
}

class ServiceCommande {
    private MySQLDatabase db = new MySQLDatabase();
    public void traiterCommande(String commande) {
        db.sauvegarderCommande(commande);
    }
}

✅ Bon exemple

Utiliser une interface pour découpler :

interface BaseDeDonnees {
    void sauvegarderCommande(String commande);
}

class MySQLDatabase implements BaseDeDonnees {
    public void sauvegarderCommande(String commande) {
        System.out.println("Commande enregistrée en MySQL");
    }
}

class ServiceCommande {
    private BaseDeDonnees db;
    public ServiceCommande(BaseDeDonnees db) {
        this.db = db;
    }
    public void traiterCommande(String commande) {
        db.sauvegarderCommande(commande);
    }
}