Principios SOLID en TypeScript: teoría y práctica de la A a la Z

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 TypeScript: teoría y práctica de la A a la Z

\n\n

SOLID es el acrónimo de cinco principios fundamentales de la programación orientada a objetos, formulados por Robert Martin (tío Bob). Estos principios ayudan a crear código flexible, mantenible y escalable. En este artículo, analizaremos en detalle cada principio SOLID con ejemplos en TypeScript, desde definiciones simples hasta escenarios de uso reales.

\n\n

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

\n\n

Definición: Cada clase debe tener una única razón para cambiar. En otras palabras, la clase debe ser responsable de una tarea claramente definida.

\n\n

Problema: Cuando una clase asume múltiples responsabilidades, se vuelve difícil de probar, extender y mantener. El cambio de una función puede romper otra.

\n\n

Ejemplo de violación de SRP:

\n
// ❌ Violación de SRP: la clase se encarga del almacenamiento, formateo y envío\nclass UserService {\n    saveUser(user: User): void {\n        // Guardar en BD\n        console.log('User saved');\n    }\n\n    formatUserData(user: User): string {\n        return `Name: ${user.name}, Email: ${user.email}`;\n    }\n\n    sendWelcomeEmail(user: User): void {\n        // Enviar email\n        console.log('Email sent');\n    }\n}
\n\n

Solución con SRP:

\n
// ✅ Cada clase es responsable de su tarea\nclass UserRepository {\n    save(user: User): void {\n        console.log('User saved');\n    }\n}\n\nclass UserFormatter {\n    format(user: User): string {\n        return `Name: ${user.name}, Email: ${user.email}`;\n    }\n}\n\nclass EmailService {\n    sendWelcome(user: User): void {\n        console.log('Email sent');\n    }\n}
\n\n

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

\n\n

Definición: Las clases deben estar abiertas para la extensión, pero cerradas para la modificación. Esto significa que debe poder agregar nueva funcionalidad sin cambiar el código existente.

\n\n

Ejemplo de violación de OCP:

\n
// ❌ Al agregar un nuevo tipo de figura, habrá que modificar el método calculateArea\nclass AreaCalculator {\n    calculateArea(shape: any): number {\n        if (shape.type === 'circle') {\n            return Math.PI * shape.radius ** 2;\n        } else if (shape.type === 'rectangle') {\n            return shape.width * shape.height;\n        }\n        throw new Error('Unknown shape');\n    }\n}
\n\n

Solución con OCP (usamos polimorfismo):

\n
// ✅ Usamos interfaz y herencia\ninterface Shape {\n    area(): number;\n}\n\nclass Circle implements Shape {\n    constructor(private radius: number) {}\n    area(): number {\n        return Math.PI * this.radius ** 2;\n    }\n}\n\nclass Rectangle implements Shape {\n    constructor(private width: number, private height: number) {}\n    area(): number {\n        return this.width * this.height;\n    }\n}\n\nclass AreaCalculator {\n    calculateArea(shape: Shape): number {\n        return shape.area(); // No requiere cambios al agregar nuevas figuras\n    }\n}
\n\n

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

\n\n

Definición: Los objetos de un programa deben ser reemplazables por instancias de sus subtipos sin alterar la corrección del programa. La clase hija no debe violar el contrato de la clase padre.

\n\n

Ejemplo de violación de LSP:

\n
// ❌ Violación: la subclase cambia el comportamiento del ancestro\nclass Bird {\n    fly(): void {\n        console.log('Flying');\n    }\n}\n\nclass Penguin extends Bird {\n    fly(): void {\n        throw new Error('Penguins cannot fly!'); // Violación del contrato\n    }\n}
\n\n

Solución con LSP:

\n
// ✅ Separación                

Blogs

Book Recommendations