DEV Community

khalil la
khalil la

Posted on

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

✅ 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());
    }
}
Enter fullscreen mode Exit fullscreen mode

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;
    }
}
Enter fullscreen mode Exit fullscreen mode

✅ 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);
    }
}
Enter fullscreen mode Exit fullscreen mode

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é est un rectangle qui a ses quatre côtés de même longueur.
Mais, un carré ne peut pas toujours remplacer un rectangle : un carré a un coté et un rectangle a une longueur et une largeur

class Rectangle {
    protected int largeur, longueur;

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

class Carre extends Rectangle {
    @Override
    public void setLargeur(int largeur) {
        this.largeur = this.longueur = largeur;
    }
}
Enter fullscreen mode Exit fullscreen mode

✅ Bon exemple

Utiliser des classes distinctes :

interface Forme {
    int getAire();
}

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

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

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"); }
}
Enter fullscreen mode Exit fullscreen mode

✅ 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"); }
}
Enter fullscreen mode Exit fullscreen mode

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

✅ 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);
    }
}
Enter fullscreen mode Exit fullscreen mode

🎯 Conclusion

Les principes SOLID en Java permettent d’avoir un code modulaire, maintenable et extensible. Respecter ces bonnes pratiques améliore la qualité du code et évite les problèmes à long terme ! 🚀

Top comments (0)