Verstoßen Leistungsänderungen gegen das Liskov-Substitutionsprinzip?

14

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?

ConditionRacer
quelle
GetThingFromDatabase()ist nicht langsam genug, um dies umstritten zu machen. Factor4096BitPublicKey();return 1;würde die Dinge ein bisschen interessanter machen.
Patrick
1
Wenn Sie ersetzen FastThingmit SlowThing, wird der LSP nicht anwendbar. Wenn Sie einen Kommentar hinzufügen, in Thing::GetThingdem "Ist sehr schnell" steht, kann die Frage diskutiert werden.
Kopffüßer

Antworten:

14

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.

DeadMG
quelle
3
Die Leistung ist nicht durch eine Typprüfung durchsetzbar. Es ist ein Versprechen des Implementierers / Bibliotheksverwalters.
Dietbuddha
3
Habe ich das in meiner antwort explizit angegeben?
DeadMG
1
Mein Punkt war, dass, sobald Sie etwas anderes als die Eingabe in die Kriterien aufnehmen, Sie nicht mehr über Liskov sprechen, da es spezifisch für die Eingabe ist. Während die "Praxis", Objekte mit unterschiedlicher Leistung nicht auszublenden, gut sein mag, hat Liskov selbst nichts zu sagen.
Dietbuddha
7
Liskov gibt an, dass es für den Derived überall dort verwendbar sein sollte, wo sich eine Base befindet. Dies kann durchaus nicht zutreffen, wenn die Basis bestimmte Leistungen oder Eigenschaften garantiert. Bei abgeleiteten Blöcken kann es beispielsweise zu Deadlocks kommen.
DeadMG
8

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.

dietbuddha
quelle
3
Ich habe nur einen kurzen Blick auf dieses Papier geworfen, aber sind Sie sicher, dass zeitliche Einschränkungen nicht formal nachweisbar sind? Und selbst wenn Liskov nicht meinte, dass in Worten, einschließlich zeitlicher Einschränkungen, eine gute Erweiterung des klassischen LSP gesehen werden könnte, die für die Programmierung in der realen Welt relevant sein könnte.
Doc Brown
@ Doc Brown: Ob Timing als Überlegung zum Ersetzen eines Objekts nützlich ist oder nicht, ist orthogonal zu Liskov. Es kann als ein einzelnes Gebot hinzugefügt werden, aber es kann und wird niemals Teil von Liskov sein. Es ist, als hätte man eine boolesche Logikgleichung und sagt: Falsch kann nur dann durch Wahr ersetzt werden, wenn es schnell genug ist. Geschwindigkeit hat nichts mit Mathematik oder Logik zu tun.
Dietbuddha
Gegenbeispiel: Dieser Code wird in Javas EDT oder in der Ereignisschleife des Knotens aufgerufen. Die radikal langsamere Leistung der langsamen Version wird die Software teilweise beschädigen. Ich denke, die richtige Antwort auf diese Frage ist "wahrscheinlich nicht, aber es gibt Ausnahmen".
user949300
6

Welche Garantien gibt die Schnittstelle? Da GetThinges keine Garantien gibt, müssen Subtypen diese nicht einhalten.

Wenn die Schnittstelle so etwas wie GetThingInLinearTimeoder der Basistyp virtuell ist und die Standardimplementierung eine Komplexität ist, würde eine Verschlechterung dieser algorithmischen Komplexität den LSP verletzen.

Telastyn
quelle
4

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.

Reactgular
quelle
1

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, Thingob 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.

Trptcolin
quelle
2
Soweit ich das beurteilen kann, ist das gepostete Beispiel kein Java
Gnat
0

Onkel Bob beantwortete eine sehr ähnliche Frage, in der er feststellt, dass eine LSP-Verletzung drei Parteien erfordert:

Der Typ T, der Subtyp S und das Programm P, das T verwendet, aber eine Instanz von S erhält.

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.)

TMc
quelle
1
Wie beantwortet dies die gestellte Frage?
gnat
@gnat Weil die gestellte Frage unvollständig ist. Es sind 3 Parteien erforderlich, um eine LSP-Verletzung festzustellen. Davon lieferte er nur 2 der Parteien.
TMc