Principes SOLID en Java : théorie et pratique avancée

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 avancée

\n\n

Les principes SOLID sont le fondement de la conception orientée objet, aidant les développeurs à créer un code résistant aux changements, facilement testable et évolutif. Pour un développeur Java, comprendre ces principes à un niveau avancé ne signifie pas seulement connaître les définitions, mais aussi savoir repérer leurs violations dans un code legacy et appliquer des patrons de conception pour le refactoriser. Dans cet article, nous analyserons chaque principe en mettant l'accent sur des situations complexes mais typiques.

\n\n

1. Single Responsibility Principle (SRP) : La frontière entre responsabilité et cohésion

\n\n

Théorie : Une classe ne doit avoir qu'une seule raison de changer. En pratique, cela signifie qu'une classe doit être responsable d'une seule partie de la fonctionnalité du programme.

\n\n

Pratique avancée : Souvent, la violation du SRP ne se manifeste pas par un mélange explicite de logiques, mais par une responsabilité "floue". Prenons l'exemple d'une classe pour la gestion de rapports :

\n\n
// Violation du SRP : la classe gère à la fois les données, le formatage et l'envoi\npublic class ReportService {\n    public void generateReport(List<Data> data) {\n        // Logique de calcul\n        Map<String, Integer> aggregated = aggregate(data);\n        // Formatage (HTML)\n        String html = formatToHtml(aggregated);\n        // Envoi par email\n        sendEmail(html, "admin@example.com");\n    }\n\n    private Map<String, Integer> aggregate(List<Data> data) {\n        // ...\n        return new HashMap<>();\n    }\n\n    private String formatToHtml(Map<String, Integer> data) {\n        // ...\n        return "<html>...</html>";\n    }\n\n    private void sendEmail(String content, String to) {\n        // ...\n    }\n}
\n\n

Problème : si le format du rapport change (besoin de PDF au lieu de HTML), il faudra modifier cette classe. Si le mode d'envoi change (Telegram au lieu d'email) — encore une fois. Solution : diviser en trois classes :

\n\n
public class ReportAggregator {\n    public Map<String, Integer> aggregate(List<Data> data) { ... }\n}\n\npublic class HtmlReportFormatter {\n    public String format(Map<String, Integer> data) { ... }\n}\n\npublic class EmailSender {\n    public void send(String content, String to) { ... }\n}\n\n// Composition dans un service\npublic class ReportGenerationFacade {\n    private ReportAggregator aggregator;\n    private HtmlReportFormatter formatter;\n    private EmailSender sender;\n\n    public void generateAndSend(List<Data> data) {\n        var aggregated = aggregator.aggregate(data);\n        var html = formatter.format(aggregated);\n        sender.send(html, "admin@example.com");\n    }\n}
\n\n

2. Open-Closed Principle (OCP) : L'art de l'extension via les abstractions

\n\n

Théorie : Les classes doivent être ouvertes à l'extension, mais fermées à la modification.

\n\n

Pratique avancée : Une violation typique est l'utilisation de chaînes if-else ou switch pour différents types d'objets. La méthode avancée consiste à utiliser le patron Stratégie ou la méthode template avec polymorphisme.

\n\n
// Violation de l'OCP : l'ajout d'un nouveau type de paiement nécessite de modifier la classe\npublic class PaymentProcessor {\n    public void processPayment(String type, double amount) {\n        if ("CREDIT_CARD".equals(type)) {\n            // logique pour carte de crédit\n        } else if ("PAYPAL".equals(type)) {\n            // logique pour PayPal\n        } else if ("BITCOIN".equals(type)) {\n            // logique pour Bitcoin\n        }\n    }\n}
\n\n

Correction via une interface et une fabrique :

\n\n
public interface PaymentMethod {\n    void pay(double amount);\n}\n\npublic class CreditCardPayment implements PaymentMethod {\n    public void pay(double amount) { ... }\n}\n\npublic class PayPalPayment implements PaymentMethod                

Blogs

Book Recommendations