Principio de sustitución de Liskov

Buenas prácticas,Desarrollo

Liskov Substitution – SOLID III

14 Oct , 2014  

Liskov Substitution, las clases hijas pueden usarse como los padres sin conocer las diferencias entre ellas

Este principio, desarrollado principalmente por Barbara Liskov, reza lo siguiente:

Debe ser posible utilizar cualquier objeto instancia de una subclase en lugar de cualquier objeto instancia de su superclase sin que la semántica del programa escrito en los términos de la superclase se vea afectado

Fácil, ¿verdad?. Bueno, creo que será mucho más sencillo explicarlo con un ejemplo. Casi todos los ejemplos referentes a Liskov Substitution se centran en un rectángulo y un cuadrado. Probemos algo diferente.

De aves va la cosa…

Supongamos que tenemos una super clase Pájaro, con sus métodos de comer y volar. Por otra parte tenemos un par de clases más, Pingüino y Cuervo, siendo ambas hijas de nuestra clase pájaro:

Liskov Substitution sostiene que si conocemos como funciona la clase Pájaro y sus métodos debemos esperar que tanto Pingüino como Cuervo se comporten de la misma forma. Por tanto, alguien que vaya a trabajar con estas clases podrá crear sendos objetos Pingüino y Cuervo y pretender que coman y vuelen:

Cuando esperamos encontrar un bonito vuelo de nuestro pingüino nos encontramos con un error similar al siguiente:

¿Qué es lo que ha pasado?

La respuesta es simple: un pingüino no es un pájaro. No, no me he vuelto loco. En este contexto un pingüino es una porción de código, o lo que es lo mismo, una representación imaginaria de algo real. Si tenemos en cuenta esto podemos comprender que las relaciones de la vida real pueden no servirnos al realizar sus representaciones programadas. Citando a Bob Martin la explicación más sencilla para entender esto es la siguiente:

Imaginemos que dos personas quieren divorciarse. Cada una de ellas contratará a un abogado que se hará cargo de su representación. Es muy poco probable que esos dos abogados también se estén divorciando porque las representaciones de las cosas no comparte las relaciones de las cosas que representan.

El Duck Typing

Como acostumbro a hacer, el ejemplo anteriormente realizado está escrito en Ruby, algo que hace que este principio pueda ser algo diferente en otros lenguajes orientados a objetos. Ruby es un lenguaje dinámico, lo que implica que hace uso del Duck Typing, un concepto que explicaré en otro artículo ampliamente pero que, en resumidas cuentas, quiere decir que la validez semántica de nuestro código viene definía por los métodos y propiedades que se utilizan en el mismo, y no por la herencia de clases o interfaces del mismo, como ocurriría en otros lenguajes (por ejemplo Java).

Cuando veo un ave que camina como un pato, nada como un pato y suena como un pato, a esa ave yo la llamo pato

El problema del Duck Typing y este principio es que podemos estar cometiendo una violación del mismo pero nuestro código será semánticamente correcto. Por tanto debemos fijarnos más en las respuestas que el código nos devuelve, para comprobar que sea lo que cabría esperar.

En nuestro ejemplo tenemos un pingüino que caminaba como un pingüino, comía como un pingüino, pero pretendía volar, ya que su clase padre permite volar. Para evitar que volara tuvimos que preparar una excepción que se lo impidiera, y esto es una clara violación del principio.

Más información

, , ,


A %d blogueros les gusta esto: