Principes SOLID en Java : théorie et pratique de A à Z

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Principes SOLID en Java : de la théorie à la pratique

\n\n

SOLID est l'acronyme de cinq principes fondamentaux de la programmation orientée objet, formulés par Robert Martin (Oncle Bob). Ces principes aident à créer un code flexible, maintenable et évolutif. Dans cet article, nous analyserons chaque principe avec des exemples en Java, montrerons comment les violer et comment les appliquer correctement.

\n\n

Pourquoi les principes SOLID sont-ils nécessaires ?

\n

Sans SOLID, le code se transforme rapidement en « spaghetti ». Avez-vous déjà rencontré une situation où la modification d'une classe en casse trois autres ? Ou une méthode qui en fait trop ? SOLID résout ces problèmes. Chaque principe est une règle qui rend le code :

\n
    \n
  • Résistant aux changements — les nouvelles exigences ne cassent pas l'ancienne logique.
  • \n
  • Compréhensible — chaque classe est responsable d'une seule chose.
  • \n
  • Testable — facile à écrire des tests unitaires.
  • \n
\n\n

1. Single Responsibility Principle (SRP) — Principe de responsabilité unique

\n

Formulation : « Une classe ne doit avoir qu'une seule raison de changer ».

\n

En termes simples : une classe ne doit faire qu'une seule chose. Si une classe a plus d'une responsabilité, elle est difficile à maintenir.

\n\n

Violation du SRP (mauvais code)

\n
public class OrderService {\n    public void createOrder(Order order) {\n        // Logique de création de commande\n        saveToDatabase(order);\n        sendEmailConfirmation(order);\n    }\n\n    private void saveToDatabase(Order order) {\n        // Sauvegarde en BDD\n    }\n\n    private void sendEmailConfirmation(Order order) {\n        // Envoi d'email\n    }\n}
\n

Problème : la classe est responsable à la fois de la logique métier, de l'accès à la BDD et de l'envoi de notifications. Une modification du service email nécessitera de modifier OrderService.

\n\n

Implémentation correcte du SRP

\n
public class OrderService {\n    private final OrderRepository repository;\n    private final EmailService emailService;\n\n    public OrderService(OrderRepository repo, EmailService email) {\n        this.repository = repo;\n        this.emailService = email;\n    }\n\n    public void createOrder(Order order) {\n        repository.save(order);\n        emailService.sendConfirmation(order);\n    }\n}\n\npublic class OrderRepository {\n    public void save(Order order) { /* logique BDD */ }\n}\n\npublic class EmailService {\n    public void sendConfirmation(Order order) { /* logique email */ }\n}
\n

Maintenant, chaque classe a une seule raison de changer. OrderService change uniquement lorsque le processus métier de création de commande est modifié.

\n\n

2. Open/Closed Principle (OCP) — Principe d'ouverture/fermeture

\n

Formulation : « Les classes doivent être ouvertes à l'extension, mais fermées à la modification ».

\n

Cela signifie que vous devez ajouter de nouvelles fonctionnalités via du nouveau code, et non en modifiant le code existant.

\n\n

Violation de l'OCP (mauvais code)

\n
public class AreaCalculator {\n    public double calculateArea(Object shape) {\n        if (shape instanceof Rectangle) {\n            Rectangle r = (Rectangle) shape;\n            return r.width * r.height;\n        } else if (shape instanceof Circle) {\n            Circle c = (Circle) shape;\n            return Math.PI * c.radius * c.radius;\n        }\n        throw new IllegalArgumentException("Forme inconnue");\n    }\n}
\n

Pour ajouter un triangle, il faut modifier la méthode calculateArea — cela viole l'OCP.

\n\n

Implémentation correcte de l'OCP

\n
public interface Shape {\n    double calculateArea();\n}\n\npublic class Rectangle implements Shape {\n    private double width, height;\n    public Rectangle(double w, double h) { this.width = w; this.height = h; }\n    @Override\n    public double calculateArea() { return width * height; }\n}\n\npublic class Circle implements Shape {\n    private double radius;\n                

Blogs

Book Recommendations