Principios SOLID: Qué son y cómo aplicarlos

12 de diciembre de 2024
4 min lectura
By Sly & AI

Table of Contents

This is a list of all the sections in this post. Click on any of them to jump to that section.

Los principios SOLID son un conjunto de buenas prácticas en la programación orientada a objetos que ayudan a escribir código más mantenible, escalable y flexible. Fueron formulados por Robert C. Martin (Uncle Bob) y se consideran fundamentales para el diseño de software. Veamos cada uno de ellos con ejemplos en JavaScript.


1. Principio de Responsabilidad Única (Single Responsibility Principle - SRP)

Un módulo o clase debe tener una única razón para cambiar, es decir, debe realizar una sola tarea o responsabilidad.

Ejemplo incorrecto:

class ReportGenerator {
  generatePDF(data) {
    // Generar PDF
  }
  sendEmail(report) {
    // Enviar por correo
  }
}

Ejemplo correcto:

class PDFGenerator {
  generate(data) {
    // Generar PDF
  }
}
 
class EmailSender {
  send(report) {
    // Enviar correo
  }
}

Al separar la generación del PDF del envío por correo, cumplimos con SRP.


2. Principio de Abierto/Cerrado (Open/Closed Principle - OCP)

Las clases deben estar abiertas para extensión pero cerradas para modificación. Esto significa que debemos poder agregar nuevas funcionalidades sin alterar el código existente.

Ejemplo incorrecto:

class Descuento {
  calcular(monto, tipo) {
    if (tipo === "estudiante") {
      return monto * 0.8;
    } else if (tipo === "vip") {
      return monto * 0.7;
    }
    return monto;
  }
}

Ejemplo correcto (Usando polimorfismo):

class Descuento {
  calcular(monto) {
    return monto;
  }
}
 
class DescuentoEstudiante extends Descuento {
  calcular(monto) {
    return monto * 0.8;
  }
}
 
class DescuentoVIP extends Descuento {
  calcular(monto) {
    return monto * 0.7;
  }
}

De esta forma, podemos agregar nuevos tipos de descuentos sin modificar la clase base.


3. Principio de Sustitución de Liskov (Liskov Substitution Principle - LSP)

Las subclases deben poder sustituir a sus clases base sin afectar el funcionamiento del programa.

Ejemplo incorrecto:

class Pato {
  volar() {
    console.log("Volando...");
  }
}
 
class PatoDeGoma extends Pato {
  volar() {
    throw new Error("Los patos de goma no pueden volar");
  }
}

Ejemplo correcto:

class Pato {
  nadar() {
    console.log("Nadando...");
  }
}
 
class PatoVolador extends Pato {
  volar() {
    console.log("Volando...");
  }
}
 
class PatoDeGoma extends Pato {
  chirriar() {
    console.log("Chirrido");
  }
}

Ahora, todas las clases hijas cumplen con LSP porque respetan el comportamiento de la clase base sin romper funcionalidades.


4. Principio de Segregación de Interfaces (Interface Segregation Principle - ISP)

Una interfaz no debe obligar a sus implementaciones a depender de métodos que no usan.

Ejemplo incorrecto:

class Trabajador {
  trabajar() {}
  comer() {}
}
 
class Robot extends Trabajador {
  comer() {
    throw new Error("Los robots no comen");
  }
}

Ejemplo correcto:

class Trabajador {
  trabajar() {}
}
 
class SerHumano extends Trabajador {
  comer() {}
}

Ahora, Robot no está forzado a implementar comer(), cumpliendo con ISP.


5. Principio de Inversión de Dependencias (Dependency Inversion Principle - DIP)

Los módulos de alto nivel no deben depender de módulos de bajo nivel, sino de abstracciones.

Ejemplo incorrecto:

class MySQLDatabase {
  connect() {
    console.log("Conectado a MySQL");
  }
}
 
class Aplicacion {
  constructor() {
    this.db = new MySQLDatabase();
  }
}

Ejemplo correcto (Usando abstracción):

class Database {
  connect() {}
}
 
class MySQLDatabase extends Database {
  connect() {
    console.log("Conectado a MySQL");
  }
}
 
class Aplicacion {
  constructor(db) {
    this.db = db;
  }
}
 
const database = new MySQLDatabase();
const app = new Aplicacion(database);

De esta forma, podemos cambiar la base de datos sin modificar la Aplicacion.


Aplicar los principios SOLID mejora la estructura de nuestro código, facilitando su mantenimiento y escalabilidad. Adoptar estas buenas prácticas permite desarrollar software más robusto y flexible en el tiempo. 🚀