Comprender cómo se relacionan los tipos y subtipos dentro de un sistema es fundamental para escribir código mantenible y extensible. El principio de sustitución de Liskov establece reglas claras sobre esa relación, y dominarlo marca la diferencia entre un diseño frágil y uno robusto.
¿Qué es el principio de sustitución de Liskov?
Este principio, conocido en inglés como Liskov Substitution Principle, fue presentado por primera vez por Barbara Liskov, de ahí su nombre [0:23]. Posteriormente, Robert Martin lo incorporó dentro del grupo de principios SOLID en su libro The Clean Code, lo que lo popularizó ampliamente en la comunidad de desarrollo de software [0:40].
La idea central es directa: cualquier subtipo debe poder reemplazar a su tipo base sin alterar el comportamiento esperado del sistema [0:55]. Esto implica que los subtipos deben implementar todas las propiedades y características del tipo del que derivan, y cada una de esas propiedades debe tener sentido dentro del subtipo.
¿Por qué es importante la relación entre tipo y subtipo?
Cuando un subtipo no cumple con todas las propiedades de su tipo base, el reemplazo se vuelve imposible o genera errores inesperados. El principio exige que:
- Todos los subtipos incluyan las propiedades del tipo base.
- Cada propiedad del tipo base tenga sentido y pertenezca al subtipo.
- El comportamiento sea consistente al sustituir un tipo por cualquiera de sus subtipos.
De esta forma, en cualquier punto del sistema donde se use el tipo base, se puede colocar un subtipo sin que el código se rompa [1:10].
¿Cómo se identifica una violación de este principio?
Un caso práctico ayuda a entenderlo mejor. Imaginemos una aplicación con dos tipos de empleados: Contractor y Full time [1:40]. Solo el empleado full time tiene derecho a horas extra. El valor de la hora es de cincuenta para el full time y cuarenta para el Contractor [1:52].
Si ambos tipos heredan de una clase base "Empleado" que incluye un método para calcular horas extra, el Contractor estaría heredando una propiedad que no le corresponde. Eso viola directamente el principio de sustitución de Liskov, porque no se podría reemplazar el tipo base por el subtipo Contractor sin generar inconsistencias.
¿Cómo se corrige el diseño para cumplir con SOLID?
El ejercicio propuesto consiste en ajustar código existente que ya tiene funcionalidades implementadas pero que no respeta los principios SOLID [2:00]. La corrección implica reorganizar la jerarquía de tipos para que:
- Las propiedades compartidas permanezcan en el tipo base.
- Las propiedades exclusivas, como las horas extra, se manejen solo en los subtipos que realmente las necesitan.
- Cualquier subtipo pueda sustituir al tipo base de manera transparente.
Este enfoque garantiza que el sistema sea extensible. Si en el futuro aparece un tercer tipo de empleado, bastará con definir qué propiedades del tipo base aplican y cuáles son específicas, sin modificar el código existente.
Aplicar correctamente el principio de sustitución de Liskov transforma la arquitectura del software en algo predecible y fácil de escalar. ¿Has encontrado casos en tus proyectos donde un subtipo heredaba propiedades que no le correspondían? Comparte tu experiencia.