I cambiamenti nelle prestazioni violano il principio di sostituzione di Liskov?


14

Dì che ho:

interface Thing
{
    GetThing();
}

class FastThing : Thing 
{
    public int GetThing()
    {
        return 1;
    }
}

class SlowThing : Thing
{
    public int GetThing()
    {
        return GetThingFromDatabase();
    }
}

È una violazione del principio di sostituzione di Liskov?


GetThingFromDatabase()non è abbastanza lento da renderlo controverso. Factor4096BitPublicKey();return 1;renderebbe le cose un po 'più interessanti.
Patrick,


1
Se si sostituisce FastThingcon SlowThing, l'LSP non si applica. Se aggiungi un commento al Thing::GetThingquale dice "È molto veloce", la domanda può essere discussa.
Cefalopode,

Risposte:


14

Dipende davvero. Alcune interfacce hanno, ad esempio, vincoli di complessità (questi ovviamente non possono essere applicati a livello di programmazione). Il caso più semplice è "GetThing () dà un int- cioè si ferma", nel qual caso la risposta sarebbe "No" - entrambe le versioni di GetThing () si fermano e restituiscono un int.

Ma molte interfacce hanno implicito o esplicitamente dichiarato garanzie prestazionali, sia in termini di complessità che di tempo piatto. Ad esempio, nello standard C ++, è illegale implementare la libreria con una chiamata di blocco, tranne nei casi in cui lo standard lo consenta espressamente.


3
Le prestazioni non sono qualcosa di applicabile tramite un controllo del tipo. È una promessa del responsabile dell'attuazione / libreria.
dietbuddha,

3
L'ho dichiarato esplicitamente nella mia risposta?
DeadMG

1
Il mio punto era che non appena includi qualcosa di diverso dal digitare i criteri non stai più parlando di Liskov in quanto è specifico per il tipo. Mentre la "pratica" di non sottrarre oggetti diversamente performanti può essere buona, la stessa Liskov non ha nulla da dire al riguardo.
dietbuddha,

7
Liskov afferma che per i Derivati ​​dovrebbe essere utilizzabile ovunque sia una Base. Ciò potrebbe non essere vero se la Base garantisce determinate prestazioni o caratteristiche. Ad esempio, se i blocchi derivati, potrebbero esserci potenziali deadlock.
DeadMG,

8

TL; DR: No

Secondo il "Sottotipo comportamentale usando invarianti e vincoli" (la formalizzazione del principio) si occupa principalmente delle proprietà di "sicurezza" di un tipo di oggetti. Proprietà che regolano la sostituibilità solo nel contesto delle informazioni sul tipo. Un tipo di oggetto è ortogonale alla sua prestazione. Pertanto, una differenza nelle prestazioni non costituisce una violazione del principio di sostituzione di Liskov.


3
Ho dato solo una breve occhiata a quel documento, ma sei sicuro che i vincoli temporali non possano essere resi formalmente provabili? E anche se Liskov non intendesse questo a parole, compresi i vincoli temporali potrebbero essere visti come una buona estensione del classico LSP che può essere rilevante per la programmazione del mondo reale.
Doc Brown,

@Doc Brown: se il tempismo è utile come considerazione per sostituire un oggetto o no è ortogonale a Liskov. Aggiungerlo come precetto sperato, ma non può e non farà mai parte di Liskov. È come avere un'equazione della logica booleana e dire: False può essere sostituito da True solo se è abbastanza veloce. La velocità non ha nulla a che fare con la matematica o la logica.
dietbuddha,

Controesempio: questo codice viene chiamato nell'EDT di Java o nel loop degli eventi di Node. Le prestazioni radicalmente più lente della versione lenta interromperanno il software. Penso che la risposta corretta a questa domanda sia "probabilmente no ma ci sono eccezioni".
user949300,

6

Quali garanzie offre l'interfaccia? Poiché GetThingnon fornisce garanzie, i sottotipi non devono rispettarlo.

Se l'interfaccia era qualcosa come GetThingInLinearTimeo se il tipo di base è virtuale e l'implementazione di default è una complessità, poi facendo che la complessità algoritmica peggio sarebbe violare LSP.


4

Le prestazioni del software non hanno nulla a che fare con il principio di sostituzione di Liskov.

Il principio ha a che fare con la sostituzione dei sottotipi e l'impatto comportamentale della sostituzione di tale oggetto solo in termini di OOP.

L'input e l'output di getThing()rimangono gli stessi per entrambi i casi e sia lentamente che velocemente mettono gli oggetti nello stesso stato.


1

Importa ciò che il Principio di sostituzione di Liskov stesso afferma specificamente? Se un sottotipo viola le aspettative del consumatore del supertipo, sembra una cosa negativa indipendentemente dal fatto che LSP sia più restrittivo.

Quindi, a mio avviso, se tutte le aspettative ragionevoli del consumatore di un'astrazione siano soddisfatte dal sottotipo sembra essere una buona generalizzazione di LSP.

Tuttavia, nell'esempio che hai pubblicato e con le interfacce Java in generale, non è chiaro che il consumatore Thingdell'interfaccia abbia delle ragionevoli aspettative se debba essere veloce o lento. Se i javadocs dell'interfaccia includessero un linguaggio su quali operazioni promettono di essere veloci, allora potrebbe esserci un argomento per un problema per motivi di prestazioni. Ma la convenzione Java prevede certamente che varie implementazioni abbiano caratteristiche prestazionali diverse.


2
per quanto ne so, l'esempio pubblicato non è Java
moscerino

0

Lo zio Bob ha risposto a una domanda molto simile in cui afferma che una violazione di LSP richiede 3 parti:

Il tipo T, il sottotipo S e il programma P che utilizza T ma riceve un'istanza di S.

Immagino che questa domanda abbia una struttura simile a quella a cui ha risposto, in quanto non menziona la P che sta usando la T e quale comportamento si aspetta la P.

Puoi trovare la sua risposta qui . (Dovrai scorrere alcuni verso il basso e cercare la risposta dell'utente di nome Robert Martin)


1
come risponde alla domanda posta?
moscerino

@gnat Perché la domanda, come posta, è incompleta. Sono necessarie 3 parti per determinare una violazione di LSP. Di cui, ha fornito solo 2 parti.
TMc,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.