Principes SOLID en C++ : théorie et pratique pour un code propre

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 C++ : de la théorie à la pratique



SOLID est un acronyme désignant cinq principes fondamentaux de la programmation orientée objet, formulés par Robert Martin (Oncle Bob). Dans le contexte du C++, ces principes aident à créer un code flexible, maintenable et testable. Dans cet article, nous allons analyser chaque principe avec des exemples pratiques en C++.



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



Essence : Chaque classe ne doit avoir qu'une seule raison de changer. En termes simples, la classe s'occupe d'une seule tâche.



Mauvais exemple (violation du SRP) :

class Report {public:    void generateReport() { /* génération du rapport */ }    void saveToFile(const std::string& filename) { /* sauvegarde dans un fichier */ }    void printReport() { /* impression du rapport */ }};


Ici, la classe Report est responsable de la génération, de la sauvegarde et de l'impression — trois responsabilités différentes.



Bon exemple (respect du SRP) :

class Report {public:    std::string generate() { /* génération du rapport */ return "report data"; }};

class ReportSaver {public: void save(const std::string& data, const std::string& filename) { // sauvegarde dans un fichier }};

class ReportPrinter {public: void print(const std::string& data) { // impression du rapport }};


Maintenant, chaque classe a une responsabilité claire et unique, ce qui simplifie les tests et les modifications.



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



Essence : Les classes doivent être ouvertes à l'extension, mais fermées à la modification. Vous devez pouvoir ajouter de nouvelles fonctionnalités sans modifier le code existant.



Mauvais exemple :

enum class ShapeType { Circle, Rectangle };

class Shape {public: ShapeType type;};

class AreaCalculator {public: double calculateArea(const Shape& shape) { if (shape.type == ShapeType::Circle) { // calcul de l'aire du cercle return 3.14 * radius * radius; } else if (shape.type == ShapeType::Rectangle) { // calcul de l'aire du rectangle return width * height; } return 0.0; }};


Lors de l'ajout d'une nouvelle forme (par exemple, un triangle), il faudra modifier AreaCalculator.



Bon exemple (via le polymorphisme) :

class Shape {public:    virtual double area() const = 0;    virtual ~Shape() = default;};

class Circle : public Shape { double radius;public: explicit Circle(double r) : radius(r) {} double area() const override { return 3.14159 * radius * radius; }};

class Rectangle : public Shape { double width, height;public: Rectangle(double w, double h) : width(w), height(h) {} double area() const override { return width * height; }};

class AreaCalculator {public: double calculateArea(const Shape& shape) { return shape.area(); }};


Maintenant, pour ajouter une nouvelle forme, il suffit de créer une nouvelle classe dérivée, sans toucher à AreaCalculator.



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



Essence : Les objets des sous-classes doivent être interchangeables avec les objets de la classe de base sans compromettre la correction du programme.



Violation classique (rectangle-carré) :

class Rectangle {protected:    int width, height;public:    void setWidth(int w) { width = w; }    void setHeight(int h) { height = h; }    int area() const { return width * height; }};

class Square : public Rectangle {public: void setWidth(int w) override { width = w; height

Blogs

Book Recommendations