¿Los cambios en el rendimiento violan el Principio de sustitución de Liskov?

14

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?

CondiciónRacer
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.
Patrick
1
Si reemplaza FastThingcon SlowThing, el LSP no se aplica. Si agrega un comentario al Thing::GetThingque dice "Es muy rápido", se puede discutir la cuestión.
Cefalópodo

Respuestas:

14

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.

DeadMG
fuente
3
El rendimiento no es algo exigible a través de una verificación de tipo. Es una promesa del implementador / mantenedor de la biblioteca.
dietbuddha
3
¿Lo expliqué explícitamente en mi respuesta?
DeadMG
1
Lo que quiero decir es que tan pronto como incluyes algo más que escribir en los criterios, ya no estás hablando de Liskov, ya que es específico para escribir. Si bien la "práctica" de no someter objetos de rendimiento diferente puede ser buena, Liskov no tiene nada que decir al respecto.
dietbuddha
77
Liskov afirma que para el Derivado, debería ser utilizable en cualquier lugar donde se encuentre una Base. Es muy posible que eso no sea cierto si la Base garantiza ciertas prestaciones o características. Por ejemplo, si los bloques Derivados, pueden existir puntos muertos.
DeadMG
8

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.

dietbuddha
fuente
3
Solo eché un breve vistazo a ese documento, pero ¿estás seguro de que las limitaciones de tiempo no pueden hacerse formalmente comprobables? E incluso si Liskov no quiso decir eso en palabras, incluir restricciones de tiempo podría verse como una buena extensión del LSP clásico que puede ser relevante para la programación del mundo real.
Doc Brown
@Doc Brown: si el tiempo es útil como una consideración para sustituir un objeto o no es ortogonal a Liskov. Puede agregarlo como un precepto sperate, pero no puede y nunca será parte de Liskov. Es como tener una ecuación lógica booleana y decir! Falso solo puede sustituirse por Verdadero si es lo suficientemente rápido. La velocidad no tiene nada que ver con las matemáticas o la lógica.
dietbuddha
Contraejemplo: este código se llama en el EDT de Java o en el bucle de eventos del nodo. El rendimiento radicalmente más lento de la versión lenta hará que el software se rompa por completo. Creo que la respuesta correcta a esta pregunta es "probablemente no, pero hay excepciones".
user949300
6

¿Qué garantías ofrece la interfaz? Como GetThingno ofrece garantías, los subtipos no necesitan respetarlo.

Si la interfaz era algo así GetThingInLinearTimeo 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.

Telastyn
fuente
4

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.

Reactgular
fuente
1

¿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 Thinginterfaz 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.

trptcolin
fuente
2
Por lo que puedo decir, el ejemplo publicado no es Java
mosquito
0

El tío Bob respondió una pregunta muy similar en la que afirma que una violación de LSP requiere 3 partes:

El Tipo T, el Subtipo S y el programa P que usa T pero recibe una instancia de S.

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)

TMc
fuente
1
¿Cómo responde esto a la pregunta que se hace?
mosquito
@gnat Porque la pregunta, tal como se hizo, está incompleta. Se necesitan 3 partes para determinar una violación de LSP. De los cuales, solo suministró 2 de las partes.
TMc