Principes SOLID en C++ : théorie et pratique de niveau avancé

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

Introduction : SOLID dans le contexte du C++

\n

SOLID est l'acronyme de cinq principes fondamentaux de conception orientée objet, formulés par Robert Martin. Pour le C++, en tant que langage doté d'un typage statique puissant, d'héritage multiple et de RAII, ces principes revêtent une importance particulière. Au niveau avancé, la compréhension de SOLID permet de créer des systèmes flexibles, testables et extensibles, en évitant les anti-patrons tels que la « classe divine » ou le couplage rigide.

\n

Dans cet article, nous analyserons chaque principe à l'aide d'exemples pratiques de code C++ (17/20), en mettant l'accent sur les nuances d'implémentation : utilisation de std::unique_ptr, std::function, CRTP, destructeurs virtuels et idiomes modernes.

\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 pratique, cela signifie qu'une classe est responsable d'une seule entité métier ou d'une seule opération. La violation du SRP entraîne un « couplage » des responsabilités, ce qui complique les tests et la modification.

\n

Exemple de violation

\n
class Report {\npublic:\n    void generate() { /* création des données */ }\n    void saveToFile(const std::string& path) { /* écriture dans un fichier */ }\n    void sendEmail(const std::string& to) { /* envoi */ }\n};
\n

Ici, Report est responsable à la fois de la génération, de la sauvegarde et de l'envoi — trois raisons de changer.

\n

Refactorisation avec SRP

\n
class Report {\npublic:\n    void generate() { /* création des données */ }\n};\n\nclass ReportSaver {\npublic:\n    void save(const Report& report, const std::string& path);\n};\n\nclass EmailSender {\npublic:\n    void send(const Report& report, const std::string& to);\n};
\n

Désormais, chaque classe a une responsabilité unique. Cela simplifie les tests unitaires et la réutilisation.

\n\n

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

\n

Formulation : Les entités logicielles doivent être ouvertes à l'extension, mais fermées à la modification.

\n

En C++, cela est souvent implémenté via le polymorphisme (fonctions virtuelles) ou via les templates (CRTP). Pour le niveau avancé, examinons les deux techniques.

\n

Approche polymorphe (fonctions virtuelles)

\n
class Shape {\npublic:\n    virtual double area() const = 0;\n    virtual ~Shape() = default;\n};\n\nclass Circle : public Shape {\n    double r;\npublic:\n    Circle(double r) : r(r) {}\n    double area() const override { return 3.14 * r * r; }\n};\n\nclass Rectangle : public Shape {\n    double w, h;\npublic:\n    Rectangle(double w, double h) : w(w), h(h) {}\n    double area() const override { return w * h; }\n};
\n

L'ajout d'une nouvelle forme (par exemple, Triangle) ne nécessite pas de modifier les classes existantes — seulement la création d'un nouvel héritier.

\n

Approche par template (CRTP — Curiously Recurring Template Pattern)

\n
template<typename Derived>\nclass ShapeBase {\npublic:\n    double area() const { return static_cast<const Derived*>(this)->area_impl(); }\n};\n\nclass Circle : public ShapeBase<Circle> {\n    double r;\npublic:\n    Circle(double r) : r(r) {}\n    double area_impl() const { return 3.14 * r * r; }\n};
\n

Le CRTP offre un polymorphisme statique sans les frais généraux des appels virtuels, ce qui est crucial pour le C++ haute performance.

\n\n

3. Liskov Substitution Principle (LSP) — Principe de substitution de Barbara Liskov

\n

Formulation : Les objets de la classe de base doivent pouvoir être remplacés par des objets des classes dérivées sans altérer la correction du programme.

\n

La violation classique du LSP en C++ est la redéfinition d'une méthode virtuelle avec un affaiblissement des préconditions ou un renforcement des postconditions. Prenons l'exemple de la hiérarchie « Rectangle — Carré ».

\n

Anti-patron

\n
class Rectangle {\nprotected:\                

Blogs

Book Recommendations