Origine di "un metodo dovrebbe restituire un valore o avere effetti collaterali, ma non entrambi"


12

Ho letto una volta che un metodo dovrebbe avere un valore di ritorno (ed essere referenzialmente trasparente), oppure avere effetti collaterali, ma non entrambi. Non riesco a trovare riferimenti a questa regola, ma voglio saperne di più.

Qual è l'origine di questo consiglio? Da quale persona o comunità è nata?

Credito extra: qual è il vantaggio dichiarato di seguire questo consiglio?


1
@gnat Sì, riguarda principalmente la storia. Temevo che la parte del credito extra fosse troppo soggettiva per resistere da sola, e che la storia avesse maggiori possibilità di sfuggire alla chiusura. Aggiungerò il tag.
Wayne Conrad,

alcune delle risposte che si accumulano mi hanno fatto chiedermi se chiedi dei benefici che sono stati richiesti da un autore di questo consiglio o di un elenco di tutti i benefici che è possibile rivendicare?
moscerino del

@gnat Chiedo il beneficio richiesto dall'autore (di nuovo, temendo la chiusura), ma di sicuro non mi dispiace per i motivi del cumulo: stanno rispondendo alla domanda che volevo davvero fare. Se dovessi rimuovere "rivendicato" dalla mia domanda, facendo le risposte sul tema in questione, ciò spingerebbe la domanda troppo lontano nel soggettivo?
Wayne Conrad,

"ragioni di accumulo" probabilmente spingeranno la domanda a chiudersi come troppo ampia . Se preferisci "rimanere aperto", penso che sarebbe più sicuro restringerlo a beneficio che è stato rivendicato dall'autore
moscerino del

Un vantaggio è che se vieni pagato per volume di codice, questo produce extra. "doSomething; GetResultOfSomething; HandleErrorsFromSomething;"
ღ uі

Risposte:


13

Secondo Greg Young, questa idea è nata da Bertrand Meyer : separazione Command-Query .

Indica che ogni metodo dovrebbe essere un comando che esegue un'azione o una query che restituisce dati al chiamante, ma non entrambi. In altre parole, fare una domanda non dovrebbe cambiare la risposta . 1 Più formalmente, i metodi dovrebbero restituire un valore solo se sono referenzialmente trasparenti e quindi non presentano effetti collaterali.

1: Eiffel: un linguaggio per l'ingegneria del software slide 43-48

In Domain Driven Design, questo è simile a Command-Query-Read Separation / Segregation (CQRS), come nominato da Greg Young.

Greg Young ha preso l'idea di CQS da Bertrand per nominare CQRS come menzionato da Martin Fowler in questo articolo CQRS

Benefici

  • La parte di lettura (query) può essere ridimensionata / ottimizzata in modo diverso dalla parte di scrittura (comando). Separare i due impedirebbe l'uno o l'altro di intralciarsi quando l'ottimizzazione / le prestazioni sono fondamentali.

Leggi l' articolo nel link Martin Fowler per ulteriori informazioni.


1
Naturalmente, in molte situazioni generare un risultato utile e apportare alcune modifiche allo stesso tempo non è più costoso del fare le due cose più difficili separatamente.
Deduplicatore,

1
@Deduplicator Un esempio di cliché è InterlockedCompareExchange?
ღ uі

1
Questo consiglio ovviamente non si applica quando il ritorno è alcune informazioni su ciò che è stato fatto nel comando, tuttavia - un metodo per rimuovere le righe da un set di dati può praticamente cambiare lo stato del set di dati, rimuovendo le righe indicate secondo un determinato criterio, e quindi restituisce il numero di righe rimosse o anche un elenco con tali righe.
T. Sar,

4

Non so da dove venga, ma è un buon consiglio e abbastanza chiaro da capire.

Qualsiasi programma progettato in modo sano verrà suddiviso in varie parti, combinate e composte in vari modi. Più è difficile ragionare su ciò che fa una parte particolare, più sarà difficile assicurarsi che il programma reagisca in modo prevedibile.

L'isolamento delle parti che producono effetti collaterali rende il resto più facile da ragionare, testare ed eseguire il debug. Ridurre il numero di effetti collaterali in ogni parte che genera un effetto collaterale renderà più facile lavorare quella parte nello stesso modo.

Se lo decomponi ulteriormente, un valore restituito è un effetto. Gli effetti collaterali sono un effetto. Una funzione dovrebbe produrre solo 1 effetto (se possibile) perché maggiore è il numero di input ed effetti di una funzione, maggiore è la difficoltà nel ragionare su ciò che effettivamente fa.


questo non tenta nemmeno di rispondere alla domanda posta, vedi Come rispondere
moscerino del

@gnat La mia domanda è arrivata in due parti: la domanda principale ("chi") e il credito extra ("perché). Non affronta questa parte del credito extra?
Wayne Conrad,

secondo la mia lettura (" beneficio dichiarato "), perché una parte dovrebbe essere quella proposta dall'autore della citazione. La domanda non sembra richiedere un elenco di tutti i possibili benefici
moscerino del

2
@gnat Ho capito la domanda come un tentativo di comprendere questo consiglio, sia la ragione che sta dietro sia il contesto in cui è stato dato. Non credo che fosse inappropriato affrontare solo una parte della domanda.
Morgen,

1

Credito extra: qual è il vantaggio inizialmente dichiarato di seguire questo consiglio?

Uno dei vantaggi della separazione del valore di ritorno dagli effetti collaterali è che rimuove un potenziale problema che può essere causato dalla valutazione del corto circuito .

bool FooWithSideEffect() {
    // do query
    // do side effect
    return resultOfQuery;
}

bool BarWithSideEffect() {
    // do query
    // do side effect
    return resultOfQuery;
}

void BadShortCircuitEvaluation()
{
    // the programmer's intent is to have side effects of both functions
    if (FooWithSideEffect() && BarWithSideEffect() ) {
        // do something
    }

    // in case FooWithSideEffect() returns true, 
    // then BarWithSideEffect() is not called at all
    // because of short-circuit evaluation
}

è questo un vantaggio richiesto dall'autore del consiglio ?
moscerino del

@gnat Ho confuso storico e pratico, temo.
Nick Alexeev,

1
il commento e il codice non corrispondono, BarWithSideEffects non viene chiamato se FooWithSideEffects restituisce false
jk.
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.