En 1988 Barbara Liskov estableció el Principio de Substitución de Liskov o LSP para la definición de subtipos
«What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.1»
Esto hace referencia a la herencia donde una clase A tiene dos subclases B y C y en cualquier parte del programa se puede usar instancias de las subclases B y C como si fueran una instancia de tipo A. Estos dos tipos son sustituibles por una instancia de clase A.
Por ejemplo, si tenemos una clase «Shape» con un método «getArea()» que devuelve el área y un componente «Draw» cuya funcionalidad es dibujar una figura y este hace una llamada a «Shape» para dibujar la figura. Si tenemos dos subclases «OvalShape» y «TriangleShape», que tienen dos maneras distintas de calcular el área, entonces cualquier instancia de estas subclases podría sustituir una instancia del tipo «Shape».
El problema de cuadrado rectángulo
Este problema es un ejemplo de una vulneración del principio ya que un cuadrado no es propiamente un subtipo de un rectángulo ya que los valores de altura y ancho cambian juntos en un cuadrado mientras que en el rectángulo se pueden cambiar por separado.Como el comportamiento es distinto los tipos no son sustituibles.
LSP y la arquitectura
El principio LSP se ha convertido en un concepto más amplio del diseño de software que pertenece a interfaces e implementaciones.El LSP es aplicable a cualquier situación donde haya usuarios que requieran de interfaces bien definidas y que la sustituibilidad de las implementaciones de estas interfaces.
La mejor manera de entender el principio desde el punto de vista de la arquitectura es ver qué ocurre cuando se vulnera el principio.
Vulneración del LSP
En el caso de tener una aplicación android que use una «API Restful» la cual tenga definido en su especificación el siguiente punto de entrada («endpoint»):/setting/account/%s
Este «endpoint» tiene la información de la configuración de la cuenta de usuario.
Si más adelante se saca la versión iOs y esta tiene algunas opciones de configuración distinta por las necesidades propias de cada sistema operativo, se podría dar el caso de abordar la resolución con un «if» en el código del «endpoint»:
if (isAndroid()) { …
Esta estrategia puede llevar a un código oscuro y albergar errores. También se puede dar la situación de tener que contemplar la posibilidad de que surja otra nueva aplicación ya sea web o de escritorio que se comunique con la primera con lo que habría que añadir otro «if».
Un arquitecto podría evitar este tipo de estrategia creando un nuevo «endpoint» específico para esta u otras aplicaciones:
/setting/account/ios/%s
/setting/account/web/%s
La arquitectura ha tenido que añadir una solución más compleja ya que las «interfaces» de los servicios «restful» no son siempre sustituibles.
No hay comentarios:
Publicar un comentario