Digamos que tengo:
interface Thing
{
GetThing();
}
class FastThing : Thing
{
public int GetThing()
{
return 1;
}
}
class SlowThing : Thing
{
public int GetThing()
{
return GetThingFromDatabase();
}
}
¿Es esto una violación del Principio de sustitución de Liskov?
performance
liskov-substitution
CondiciónRacer
fuente
fuente
GetThingFromDatabase()
No es lo suficientemente lento como para hacer que esto sea controvertido.Factor4096BitPublicKey();return 1;
haría las cosas un poco más interesantes.FastThing
conSlowThing
, el LSP no se aplica. Si agrega un comentario alThing::GetThing
que dice "Es muy rápido", se puede discutir la cuestión.Respuestas:
Eso realmente depende. Algunas interfaces tienen, por ejemplo, restricciones de complejidad (estas obviamente no pueden aplicarse mediante programación). El caso más básico es "GetThing () da un
int
- es decir, se detiene", en cuyo caso, la respuesta sería "No" - ambas versiones de GetThing () detienen y devuelven un int.Pero muchas interfaces tienen garantías de rendimiento implícitas o expresamente establecidas, ya sea en complejidad o en tiempo plano. Por ejemplo, en el Estándar C ++, es ilegal implementar la biblioteca con una llamada de bloqueo, excepto donde el Estándar lo permita expresamente.
fuente
TL; DR: No
De acuerdo con el "Subtipo de comportamiento usando invariantes y restricciones" (la formalización del principio) se refiere principalmente a las propiedades de "seguridad" de un tipo de objeto. Propiedades que rigen la sustituibilidad solo dentro del contexto de la información de tipo. Un tipo de objeto es ortogonal a su rendimiento. Por lo tanto, una diferencia en el rendimiento no es una violación del Principio de sustitución de Liskov.
fuente
¿Qué garantías ofrece la interfaz? Como
GetThing
no ofrece garantías, los subtipos no necesitan respetarlo.Si la interfaz era algo así
GetThingInLinearTime
o si el tipo de base es virtual y la implementación por defecto es uno complejidad, a continuación, hacer que la complejidad algorítmica peor sería violar la LSP.fuente
El rendimiento del software no tiene nada que ver con el Principio de sustitución de Liskov.
El principio tiene que ver con la sustitución de subtipos, y el impacto conductual de sustituir ese objeto solo en términos de POO.
La entrada y la salida de
getThing()
permanecen iguales para ambos casos, y tanto lento como rápido probablemente coloquen los objetos en el mismo estado.fuente
¿Importa lo que el Principio de sustitución de Liskov mismo dice específicamente? Si un subtipo viola las expectativas del consumidor del supertipo, eso parece algo malo independientemente de si LSP es más restrictivo.
Por lo tanto, en mi opinión, si el subtipo cumple todas las expectativas razonables del consumidor de una abstracción, parece ser una buena generalización de LSP.
Sin embargo, en el ejemplo que ha publicado y con las interfaces Java en general, no está claro que el consumidor de la
Thing
interfaz tenga una expectativa razonable de si debe ser rápida o lenta. Si los javadocs de la interfaz incluyesen un lenguaje sobre qué operaciones se prometen ser rápidas, entonces podría haber un argumento para un problema por motivos de rendimiento. Pero la convención de Java es sin duda que varias implementaciones tengan diferentes características de rendimiento.fuente
El tío Bob respondió una pregunta muy similar en la que afirma que una violación de LSP requiere 3 partes:
Me atrevería a suponer que esta pregunta tiene una estructura similar a la que él respondió, en el sentido de que no menciona la P que usa la T y qué comportamiento espera la P.
Puedes encontrar su respuesta aquí . (Deberá desplazarse hacia abajo y buscar la respuesta del usuario llamado Robert Martin)
fuente