Les changements de performances violent-ils le principe de substitution de Liskov?

14

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?

ConditionRacer
la source
GetThingFromDatabase()n'est pas assez lent pour rendre cela controversé. Factor4096BitPublicKey();return 1;rendrait les choses un peu plus intéressantes.
Patrick
1
Si vous remplacez FastThingpar SlowThing, le LSP ne s'applique pas. Si vous ajoutez un commentaire Thing::GetThingqui dit "est très rapide", la question peut être discutée.
Céphalopode

Réponses:

14

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.

DeadMG
la source
3
Les performances ne sont pas exécutoires via une vérification de type. C'est une promesse de l'implémenteur / mainteneur de bibliothèque.
dietbuddha
3
Je l'ai dit explicitement dans ma réponse?
DeadMG
1
Mon point était que dès que vous incluez autre chose que taper dans les critères, vous ne parlez plus de Liskov car il est spécifique au type. Bien que la «pratique» de ne pas remplacer les objets à exécution différente puisse être bonne, Liskov lui-même n'a rien à dire à ce sujet.
dietbuddha
7
Liskov déclare que pour le dérivé, il devrait être utilisable partout où se trouve une base. Cela pourrait ne pas être vrai si la Base garantit certaines performances ou caractéristiques. Par exemple, s'il s'agit de blocs dérivés, il peut y avoir un risque de blocages.
DeadMG
8

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.

Dietbuddha
la source
3
Je n'ai eu qu'un bref aperçu de ce document, mais êtes-vous sûr que les contraintes de temps ne peuvent pas être formellement prouvables? Et même si Liskov ne voulait pas dire cela en termes de mots, y compris les contraintes de temps pourraient être considérées comme une bonne extension du LSP classique qui peut être pertinente pour la programmation du monde réel.
Doc Brown
@Doc Brown: si le timing est utile comme considération pour substituer ou non un objet est orthogonal à Liskov. Pour pouvoir l'ajouter comme un précepte sperate, mais il ne peut pas et ne fera jamais partie de Liskov. C'est comme avoir une équation logique booléenne et dire! Faux ne peut être remplacé par Vrai que s'il est assez rapide. La vitesse n'a rien à voir avec les mathématiques ou la logique.
dietbuddha
Contre-exemple: ce code est appelé dans l'EDT de Java ou dans la boucle d'événements de Node. Les performances radicalement plus lentes de la version lente vont briser le logiciel. Je pense que la bonne réponse à cette question est "probablement pas, mais il y a des exceptions".
user949300
6

Quelles garanties offre l'interface? Puisque GetThingne donne aucune garantie, les sous-types n'ont pas besoin de le respecter.

Si l'interface était quelque chose comme GetThingInLinearTimeou 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.

Telastyn
la source
4

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.

Reactgular
la source
1

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' Thinginterface 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.

trptcolin
la source
2
pour autant que je sache, l'exemple publié n'est pas Java
gnat
0

L'oncle Bob a répondu à une question très similaire où il déclare qu'une violation de LSP nécessite 3 parties:

Le type T, le sous-type S et le programme P qui utilise T mais reçoit une instance de S.

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)

TMc
la source
1
comment cela répond-il à la question posée?
moucher
@gnat Parce que la question, telle que posée, est incomplète. Il faut 3 parties pour déterminer une violation LSP. Dont, il n'a fourni que 2 des parties.
TMc