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é 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;
}
}
✅ 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; }
}
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);
}
}
🎯 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 ! 🚀