Principios SOLID en C++: teoría y práctica para código limpio

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Principios SOLID en C++: de la teoría a la práctica



SOLID es un acrónimo de cinco principios fundamentales de la programación orientada a objetos, formulados por Robert Martin (Tío Bob). En el contexto de C++, estos principios ayudan a crear código flexible, mantenible y testeable. En este artículo, analizaremos cada principio con ejemplos prácticos en C++.



1. Single Responsibility Principle (SRP) — Principio de responsabilidad única



Esencia: Cada clase debe tener una única razón para cambiar. En palabras simples: la clase se ocupa de una sola tarea.



Ejemplo incorrecto (violación de SRP):

class Report {public:    void generateReport() { /* generación del informe */ }    void saveToFile(const std::string& filename) { /* guardar en archivo */ }    void printReport() { /* imprimir informe */ }};


Aquí la clase Report se encarga de la generación, el guardado y la impresión: tres responsabilidades diferentes.



Ejemplo correcto (cumpliendo SRP):

class Report {public:    std::string generate() { /* generación del informe */ return "report data"; }};

class ReportSaver {public: void save(const std::string& data, const std::string& filename) { // guardar en archivo }};

class ReportPrinter {public: void print(const std::string& data) { // imprimir informe }};


Ahora cada clase tiene una responsabilidad clara, lo que simplifica las pruebas y la modificación.



2. Open-Closed Principle (OCP) — Principio de abierto/cerrado



Esencia: Las clases deben estar abiertas para la extensión, pero cerradas para la modificación. Debe poder agregar nueva funcionalidad sin cambiar el código existente.



Ejemplo incorrecto:

enum class ShapeType { Circle, Rectangle };

class Shape {public: ShapeType type;};

class AreaCalculator {public: double calculateArea(const Shape& shape) { if (shape.type == ShapeType::Circle) { // cálculo del área del círculo return 3.14 * radius * radius; } else if (shape.type == ShapeType::Rectangle) { // cálculo del área del rectángulo return width * height; } return 0.0; }};


Al agregar una nueva figura (por ejemplo, un triángulo), sería necesario modificar AreaCalculator.



Ejemplo correcto (mediante polimorfismo):

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(); }};


Ahora, para agregar una nueva figura, basta con crear una nueva clase derivada, sin tocar AreaCalculator.



3. Liskov Substitution Principle (LSP) — Principio de sustitución de Barbara Liskov



Esencia: Los objetos de las subclases deben ser intercambiables con los objetos de la clase base sin alterar la corrección del programa.



Violación clásica (rectángulo-cuadrado):

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