Powiedz, że mam:
interface Thing
{
GetThing();
}
class FastThing : Thing
{
public int GetThing()
{
return 1;
}
}
class SlowThing : Thing
{
public int GetThing()
{
return GetThingFromDatabase();
}
}
Czy jest to naruszenie zasady substytucji Liskowa?
performance
liskov-substitution
ConditionRacer
źródło
źródło
GetThingFromDatabase()
nie jest wystarczająco wolny, aby wywołać to kontrowersje.Factor4096BitPublicKey();return 1;
sprawiłoby, że rzeczy byłyby trochę bardziej interesujące.FastThing
sięSlowThing
, LSP nie ma zastosowania. Jeśli dodasz komentarz,Thing::GetThing
który mówi „Jest bardzo szybki”, pytanie można przedyskutować.Odpowiedzi:
To naprawdę zależy. Niektóre interfejsy mają na przykład ograniczenia złożoności (oczywiście nie można ich egzekwować programowo). Najbardziej podstawowym przypadkiem jest „GetThing () daje
int
- tzn. Zatrzymuje się”, w którym to przypadku odpowiedź brzmiałaby „Nie” - obie wersje GetThing () zatrzymują się i zwracają wartość int.Jednak wiele interfejsów sugeruje lub wyraźnie określa gwarancje wydajności, zarówno w złożoności, jak i w czasie wolnym. Na przykład w standardzie C ++ implementacja biblioteki za pomocą wywołania blokującego jest nielegalna, chyba że standard wyraźnie na to pozwala.
źródło
TL; DR: Nie
Zgodnie z „Subtypingem behawioralnym z wykorzystaniem niezmienników i ograniczeń” (sformalizowanie zasady) chodzi przede wszystkim o „bezpieczeństwo” właściwości typu obiektu. Właściwości regulujące zastępowalność tylko w kontekście informacji o typie. Typ obiektu jest prostopadły do swojej wydajności. Dlatego różnica w wydajności nie stanowi naruszenia zasady zastępowania Liskowa.
źródło
Jakie gwarancje daje interfejs? Ponieważ
GetThing
nie daje żadnych gwarancji, podtypy nie muszą tego przestrzegać.Jeśli interfejs byłby podobny
GetThingInLinearTime
lub jeśli typ podstawowy jest wirtualny, a domyślną implementacją jest jedna złożoność, to pogorszenie złożoności algorytmu naruszy LSP.źródło
Wydajność oprogramowania nie ma nic wspólnego z zasadą substytucji Liskowa.
Zasada ta dotyczy substytucji podtypów i behawioralnego wpływu substytucji tego obiektu wyłącznie w kategoriach OOP.
Dane wejściowe i wyjściowe
getThing()
pozostają takie same w obu przypadkach, a zarówno powolne, jak i szybkie prawdopodobnie wprowadzają obiekty w ten sam stan.źródło
Czy ma znaczenie to, co konkretnie mówi sama zasada substytucji Liskowa? Jeśli podtyp narusza oczekiwania konsumenta nadtypu, wydaje się to złą rzeczą, niezależnie od tego, czy LSP jest bardziej restrykcyjny.
Moim zdaniem więc, czy wszystkie rozsądne oczekiwania konsumenta abstrakcji są spełnione przez podtyp, wydaje się być dobrym uogólnieniem LSP.
Jednak w opublikowanym przykładzie i ogólnie interfejsach Java nie jest jasne, czy użytkownik
Thing
interfejsu ma uzasadnione oczekiwania, czy powinien on działać szybko, czy wolno. Jeśli javadocs interfejsu miałyby zawierać język na temat tego, jakie operacje mają być szybkie, to może istnieć argument za problemem ze względu na wydajność. Ale konwencja Java z pewnością dotyczy różnych implementacji mających różne charakterystyki wydajności.źródło
Wujek Bob odpowiedział na bardzo podobne pytanie, w którym stwierdził, że naruszenie LSP wymaga 3 stron:
Zaryzykowałbym przypuszczenie, że to pytanie ma podobną strukturę jak to, na które odpowiedział, ponieważ nie wspomina o P, które używa T i jakie zachowanie P oczekuje.
Możesz znaleźć jego odpowiedź tutaj . (Musisz przewinąć w dół i poszukać odpowiedzi od użytkownika o nazwisku Robert Martin)
źródło