Principios SOLID - Explicación y Ejemplos
1. Single Responsibility Principle (SRP)
Este principio establece que una clase debe tener una única responsabilidad, lo que significa que
debería haber una sola razón para que la clase cambie. En otras palabras, cada clase debe estar
enfocada en hacer solo una cosa, de manera que si se requiere un cambio en una funcionalidad
específica, solo afectará a la clase que tiene esa responsabilidad.
Ejemplo: Imagina que estás creando una aplicación que maneja pedidos. Podrías tener una clase
Order que se encarga de los detalles del pedido. Si esta clase también maneja la lógica para
calcular impuestos y enviar notificaciones por correo electrónico, estaría rompiendo el SRP. En
lugar de eso, podrías tener una clase Order, otra clase TaxCalculator, y una clase EmailNotifier. De
esta manera, si cambian las reglas de impuestos, solo necesitas modificar TaxCalculator.
2. Open/Closed Principle (OCP)
Según el OCP, las entidades de software (clases, módulos, funciones, etc.) deben estar abiertas
para extensión, pero cerradas para modificación. Esto significa que deberías poder añadir nuevas
funcionalidades sin alterar el código existente, lo que ayuda a evitar la introducción de errores en un
código que ya funciona.
Ejemplo: Supón que tienes una clase Shape con un método area() para calcular el área de
diferentes formas geométricas. En lugar de modificar la clase Shape cada vez que añades una
nueva forma (como un rectángulo o un círculo), podrías extenderla creando subclases específicas
para cada forma.
3. Liskov Substitution Principle (LSP)
Este principio establece que las subclases deben ser sustituibles por sus clases base sin alterar el
comportamiento del programa. En otras palabras, si una clase B hereda de una clase A, entonces
deberías poder usar un objeto de tipo B en lugar de un objeto de tipo A sin que el programa falle.
Ejemplo: Imagina que tienes una clase base Bird y una subclase Penguin. Si Bird tiene un método
fly(), sería incorrecto que Penguin herede este método si los pingüinos no pueden volar. Esto
violaría el LSP. En su lugar, podrías diseñar la jerarquía de clases de manera diferente para no
obligar a Penguin a tener un método fly().
4. Interface Segregation Principle (ISP)
Este principio sugiere que es mejor tener muchas interfaces pequeñas y específicas que una sola
interfaz grande y general. Las clases no deberían estar obligadas a implementar métodos que no
usan. Esto mantiene el código limpio y evita la implementación de métodos innecesarios.
Ejemplo: Supón que tienes una interfaz Worker con métodos como work() y eat(). Si implementas
esta interfaz en una clase Robot, que solo puede trabajar pero no comer, estarías violando el ISP.
En lugar de eso, podrías dividir la interfaz en dos: Worker para trabajar y Eater para comer.
5. Dependency Inversion Principle (DIP)
El DIP establece que las clases deben depender de abstracciones (interfaces o clases abstractas) y
no de implementaciones concretas. Esto ayuda a desacoplar componentes en el sistema, lo que
facilita el mantenimiento y la evolución del código.
Ejemplo: Imagina que tienes una clase LightSwitch que controla una LightBulb. Si LightSwitch
depende directamente de LightBulb, cada vez que cambies la implementación de LightBulb,
tendrías que cambiar también LightSwitch. En lugar de eso, podrías usar una interfaz Switchable
que LightBulb implemente, de manera que LightSwitch dependa de la abstracción Switchable y no
de la clase concreta LightBulb.