Angenommen, ich habe:
interface Thing
{
GetThing();
}
class FastThing : Thing
{
public int GetThing()
{
return 1;
}
}
class SlowThing : Thing
{
public int GetThing()
{
return GetThingFromDatabase();
}
}
Handelt es sich um eine Verletzung des Liskov-Substitutionsprinzips?
performance
liskov-substitution
ConditionRacer
quelle
quelle
GetThingFromDatabase()
ist nicht langsam genug, um dies umstritten zu machen.Factor4096BitPublicKey();return 1;
würde die Dinge ein bisschen interessanter machen.FastThing
mitSlowThing
, wird der LSP nicht anwendbar. Wenn Sie einen Kommentar hinzufügen, inThing::GetThing
dem "Ist sehr schnell" steht, kann die Frage diskutiert werden.Antworten:
Das kommt wirklich darauf an. Einige Schnittstellen weisen beispielsweise Komplexitätsbeschränkungen auf (diese können offensichtlich nicht programmgesteuert erzwungen werden). Der grundlegendste Fall ist "GetThing () gibt ein
int
- dh es hält an". In diesem Fall würde die Antwort "Nein" lauten - beide Versionen von GetThing () halten an und geben ein int zurück.Viele Schnittstellen haben jedoch implizite oder ausdrücklich festgelegte Leistungsgarantien, entweder in Bezug auf die Komplexität oder in Bezug auf die Zeit. Zum Beispiel ist es im C ++ Standard illegal, die Bibliothek mit einem blockierenden Aufruf zu implementieren, sofern der Standard dies nicht ausdrücklich zulässt.
quelle
TL; DR: Nein
Nach der "Behavioral Subtyping Using Invariants and Constraints" (der Formalisierung des Prinzips) handelt es sich in erster Linie um "Sicherheits" -Eigenschaften eines Objekttyps. Eigenschaften, die die Substituierbarkeit nur im Kontext von Typinformationen regeln. Ein Objekttyp ist orthogonal zu seiner Leistung. Daher verstößt ein Leistungsunterschied nicht gegen das Liskov-Substitutionsprinzip.
quelle
Welche Garantien gibt die Schnittstelle? Da
GetThing
es keine Garantien gibt, müssen Subtypen diese nicht einhalten.Wenn die Schnittstelle so etwas wie
GetThingInLinearTime
oder der Basistyp virtuell ist und die Standardimplementierung eine Komplexität ist, würde eine Verschlechterung dieser algorithmischen Komplexität den LSP verletzen.quelle
Die Leistung der Software hat nichts mit dem Liskov-Substitutionsprinzip zu tun.
Das Prinzip hat nur mit dem Ersetzen von Untertypen und den Verhaltensauswirkungen des Ersetzens dieses Objekts in OOP-Begriffen zu tun.
Die Eingabe und Ausgabe von
getThing()
bleiben in beiden Fällen gleich, und sowohl langsam als auch schnell versetzen die Objekte wahrscheinlich in den gleichen Zustand.quelle
Ist es wichtig, was das Liskov-Substitutionsprinzip selbst genau sagt? Wenn ein Subtyp die Erwartungen des Verbrauchers des Supertyps verletzt, scheint dies eine schlechte Sache zu sein, unabhängig davon, ob LSP restriktiver ist.
Ob also alle vernünftigen Erwartungen des Verbrauchers an eine Abstraktion durch den Subtyp erfüllt werden, scheint aus meiner Sicht eine gute Verallgemeinerung von LSP zu sein.
In dem von Ihnen veröffentlichten Beispiel und mit Java-Schnittstellen im Allgemeinen ist jedoch nicht klar,
Thing
ob der Benutzer der Schnittstelle eine vernünftige Erwartung hat, ob sie schnell oder langsam sein sollte. Wenn die Javadocs der Schnittstelle eine Sprache enthalten, die angibt, welche Vorgänge voraussichtlich schnell sind, gibt es möglicherweise ein Argument für ein Problem aus Gründen der Leistung. Aber die Java - Konvention ist sicherlich für verschiedene Implementierungen unterschiedliche Leistungsmerkmale aufweisen.quelle
Onkel Bob beantwortete eine sehr ähnliche Frage, in der er feststellt, dass eine LSP-Verletzung drei Parteien erfordert:
Ich würde vermuten, dass diese Frage eine ähnliche Struktur hat wie die, auf die er geantwortet hat, da sie nicht das P erwähnt , das das T verwendet, und welches Verhalten das P erwartet.
Hier finden Sie seine Antwort . (Sie müssen nach unten scrollen und nach Antworten von Benutzer Robert Martin suchen.)
quelle