SOLID es un acrónimo de cinco principios de diseño orientado a objetos introducidos por Robert Martin a principios de la década de 2000. Cada principio aborda un modo de falla específico del diseño orientado a objetos: síntomas que se reconocen en bases de código reales: clases que son imposibles de extender, módulos que se rompen en lugares inesperados cuando se modifican, código que no se puede probar de forma aislada. Los principios SOLID no son reglas para aplicar mecánicamente: son lentes para identificar problemas de diseño y guiar la refactorización. Esta lección cubre cada principio con precisión, muestra la infracción antes de la corrección y explica las implicaciones arquitectónicas.
Formulación de Martin: "Una clase debería tener sólo una razón para cambiar". La palabra "razón" es clave: se refiere a un actor o parte interesada cuyos requisitos podrían impulsar un cambio, no a una regla sintáctica de "un método". Una clase que formatea informes Y los guarda en la base de datos tiene dos motivos para cambiar: el equipo de informes (cambios de formato) y el equipo de operaciones (migración de la base de datos). Cuando esos cambios ocurren simultáneamente, entran en conflicto. SRP dice que estas preocupaciones pertenecen a clases separadas.
La formulación de Bertrand Meyer (1988), reformulada por Martin: "Las entidades de software deberían estar abiertas a la extensión, pero cerradas a la modificación". Una clase está cerrada para modificaciones cuando su código implementado y probado no necesita cambiar para adaptarse al nuevo comportamiento. Está abierto a la extensión cuando se puede agregar un nuevo comportamiento escribiendo un nuevo código (una nueva subclase, una nueva implementación de estrategia, un nuevo decorador) sin tocar la clase existente. El mecanismo más común: depender de abstracciones (interfaces) e inyectar implementaciones concretas.
Formulación de Barbara Liskov (1987): "Si S es un subtipo de T, entonces los objetos de tipo T pueden ser reemplazados por objetos de tipo S sin alterar ninguna de las propiedades deseables del programa". En términos sencillos: una subclase debe respetar el contrato de su superclase, no sólo las firmas de sus métodos, sino también sus expectativas de comportamiento (condiciones previas, condiciones posteriores, invariantes). La violación clásica de LSP es el problema Cuadrado-Rectángulo: Cuadrado extiende Rectángulo, pero anular setWidth para establecer también la altura viola el contrato del rectángulo de que el ancho y la altura son independientes.
Formulación de Martin: "No se debe obligar a los clientes a depender de interfaces que no utilizan". Las interfaces gruesas (interfaces con muchos métodos no relacionados) obligan a los implementadores a proporcionar implementaciones auxiliares de métodos que no necesitan y obligan a los clientes a importar un tipo que incluye capacidades que no utilizan. El ISP dice: prefiera muchas interfaces pequeñas y específicas del cliente a una interfaz grande de propósito general. La presión de diseño del ISP produce naturalmente interfaces de roles: interfaces que describen un rol que desempeña un objeto (imprimible, guardable, auditable) en lugar del menú completo de todo lo que un objeto puede hacer.
Formulación de Martin: '(A) Los módulos de alto nivel no deberían depender de módulos de bajo nivel. Ambos deberían depender de abstracciones. (B) Las abstracciones no deben depender de los detalles. Los detalles deberían depender de abstracciones. DIP es el principio que subyace a la Arquitectura Cebolla, la Arquitectura Hexagonal y la Arquitectura Limpia, todas las arquitecturas tratadas en el capítulo anterior. También es el principio que hace que la inyección de dependencia sea significativa: DI es el mecanismo; DIP es la razón.