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

14

Dire che ho:

interface Thing
{
    GetThing();
}

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

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

Si tratta di una violazione del Principio di sostituzione di Liskov?

    
posta ConditionRacer 10.02.2013 - 00:36
fonte

6 risposte

14

Questo dipende davvero. Alcune interfacce hanno, ad esempio, limiti di complessità (ovviamente non possono essere applicate a livello di codice). 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 garanzie di prestazione implicite o espressamente dichiarate, sia in termini di complessità che in termini di tempo. Ad esempio, nello standard C ++, è illegale implementare la libreria con una chiamata bloccante, tranne quando lo standard lo consente espressamente.

    
risposta data 10.02.2013 - 00:42
fonte
8

TL; DR: No

Secondo "Sottotipizzazione comportamentale utilizzando invarianti e vincoli" (la formalizzazione del principio) riguarda principalmente le proprietà di "sicurezza" di un tipo di oggetto. Proprietà che regolano la sostituibilità solo nel contesto delle informazioni sul tipo. Un tipo di oggetto è ortogonale alle sue prestazioni. Pertanto, una differenza nelle prestazioni non è una violazione del Principio di sostituzione di Liskov.

    
risposta data 10.02.2013 - 01:00
fonte
6

Quali garanzie garantisce l'interfaccia? Poiché GetThing non garantisce che i sottotipi non debbano rispettarlo.

Se l'interfaccia era qualcosa come GetThingInLinearTime o se il tipo di base è virtuale e l'implementazione predefinita è una complessità, allora rendere tale complessità algoritmica peggio sarebbe violare LSP.

    
risposta data 10.02.2013 - 03:20
fonte
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 con l'impatto comportamentale di sostituire quell'oggetto solo in termini OOP.

L'input e l'output di getThing() rimangono gli stessi per entrambi i casi, e sia gli oggetti lenti che quelli veloci probabilmente mettono lo stesso stato.

    
risposta data 10.02.2013 - 01:04
fonte
1

È importante ciò che dice lo stesso principio di sostituzione di Liskov? 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 ragionevoli aspettative del consumatore di un'astrazione sono soddisfatte dal sottotipo sembra essere una buona generalizzazione dell'LSP.

Tuttavia, nell'esempio che hai pubblicato e con le interfacce Java in generale, non è chiaro se il consumatore dell'interfaccia Thing abbia una ragionevole aspettativa se debba essere veloce o lento. Se i javadoc dell'interfaccia dovessero includere un linguaggio su ciò che le operazioni sono promesse essere veloci, allora potrebbe esserci un argomento per un problema sulla base delle prestazioni. Ma la convenzione Java è certamente per varie implementazioni con caratteristiche di performance diverse.

    
risposta data 10.02.2013 - 03:32
fonte
-1

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

The Type T, the Subtype S, and the program P that uses T but is given an instance of S.

Mi azzarderei a indovinare che questa domanda ha una struttura simile a quella a cui ha risposto, in quanto non menziona il P che sta usando T e quale comportamento si aspetta P

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

    
risposta data 06.09.2013 - 08:21
fonte

Leggi altre domande sui tag