Dis que j'ai:
interface Thing
{
GetThing();
}
class FastThing : Thing
{
public int GetThing()
{
return 1;
}
}
class SlowThing : Thing
{
public int GetThing()
{
return GetThingFromDatabase();
}
}
Est-ce une violation du principe de substitution de Liskov?
performance
liskov-substitution
ConditionRacer
la source
la source
GetThingFromDatabase()
n'est pas assez lent pour rendre cela controversé.Factor4096BitPublicKey();return 1;
rendrait les choses un peu plus intéressantes.FastThing
parSlowThing
, le LSP ne s'applique pas. Si vous ajoutez un commentaireThing::GetThing
qui dit "est très rapide", la question peut être discutée.Réponses:
Cela dépend vraiment. Certaines interfaces ont, par exemple, des contraintes de complexité (celles-ci ne peuvent évidemment pas être appliquées par programme). Le cas le plus élémentaire est "GetThing () donne un
int
- c'est-à-dire qu'il s'arrête", auquel cas, la réponse serait "Non" - les deux versions de GetThing () s'arrêtent et renvoient un int.Mais de nombreuses interfaces impliquent ou expriment expressément des garanties de performances, soit en complexité, soit en temps plat. Par exemple, dans la norme C ++, il est illégal d'implémenter la bibliothèque avec un appel de blocage, sauf lorsque la norme le permet expressément.
la source
TL; DR: Non
Selon le "Sous-typage comportemental utilisant des invariants et des contraintes" (la formalisation du principe), il s'agit principalement des propriétés de "sécurité" d'un type d'objets. Propriétés qui régissent la substituabilité uniquement dans le contexte des informations de type. Un type d'objets est orthogonal à ses performances. Par conséquent, une différence de performance n'est pas une violation du principe de substitution de Liskov.
la source
Quelles garanties offre l'interface? Puisque
GetThing
ne donne aucune garantie, les sous-types n'ont pas besoin de le respecter.Si l'interface était quelque chose comme
GetThingInLinearTime
ou si le type de base est virtuelle et l'implémentation par défaut est une complexité, puis faire que la complexité algorithmique pire serait une violation LSP.la source
Les performances du logiciel n'ont rien à voir avec le principe de substitution de Liskov.
Le principe concerne la substitution des sous-types et l'impact comportemental de la substitution de cet objet uniquement en termes de POO.
L'entrée et la sortie de
getThing()
restent les mêmes dans les deux cas, et à la fois lent et rapide mettent probablement les objets dans le même état.la source
Est-il important de savoir ce que le principe de substitution de Liskov lui-même dit précisément? Si un sous-type viole les attentes du consommateur du supertype, cela semble être une mauvaise chose, que LSP soit plus restrictif ou non.
Donc, à mon avis, le fait que toutes les attentes raisonnables du consommateur d'une abstraction soient satisfaites par le sous-type semble être une bonne généralisation de LSP.
Cependant, dans l'exemple que vous avez publié et avec les interfaces Java en général, il n'est pas clair que le consommateur de l'
Thing
interface ait une attente raisonnable quant à savoir si elle doit être rapide ou lente. Si les javadocs de l'interface devaient inclure un langage sur les opérations promises pour être rapides, alors il pourrait y avoir un argument pour un problème pour des raisons de performances. Mais la convention Java est certainement pour différentes implémentations d'avoir des caractéristiques de performances différentes.la source
L'oncle Bob a répondu à une question très similaire où il déclare qu'une violation de LSP nécessite 3 parties:
Je suppose que cette question a une structure similaire à celle à laquelle il a répondu, en ce qu'elle ne mentionne pas le P qui utilise le T et quel comportement le P attend.
Vous pouvez trouver sa réponse ici . (Vous devrez en faire défiler vers le bas et rechercher la réponse de l'utilisateur nommé Robert Martin)
la source