Devo scendere a compromessi: DRY, o Command-Query-Separation?

10

Recentemente ho refactoring un metodo che era sia un comando che un metodo di query.

Dopo averlo separato in un metodo a un comando e in un metodo di query, ho scoperto che ora ci sono più posti nel codice in cui sto chiamando il comando, ottenendo il valore dalla query, che sembra una violazione del principio DRY .

Ma se dovessi avvolgere quel codice comune in un metodo, quel metodo sarebbe sia un comando che una query. È accettabile?

    
posta Kris Welsh 31.07.2013 - 18:37
fonte

3 risposte

11

Ci sono sempre compromessi da considerare tra principi di progettazione in conflitto. Il modo per risolverlo è guardare le ragioni sottostanti ai principi. In questo caso, non essere in grado di eseguire una query senza eseguire il comando è problematico, ma non essere in grado di eseguire un comando senza eseguire la query è generalmente innocuo. Finché c'è un modo per eseguire la query standalone, non vedo alcun motivo per non aggiungere il risultato della query al comando, specialmente se fatto qualcosa di simile:

QueryResult command()
{
   // do command stuff
   return query();
}
    
risposta data 31.07.2013 - 19:07
fonte
4

Non ho mai sentito parlare di Command-Query-Separation (CQS), ma sembra che si riferisca al Single Responsibility Principle (SRP), che afferma che idealmente una funzione / classe dovrebbe essere responsabile di fare una cosa e solo una cosa.

Se il tuo codice di comando è di 20 righe di codice e il codice di query è di altre 30 righe e sono tutte in un corpo di una funzione, chiaramente stai violando SRP e assumerei anche CQS e questi due pezzi di logica dovrebbero essere separati gli uni dagli altri.

Tuttavia, andando con il tuo esempio ipotetico, molto probabilmente creerei un metodo wrapper che combinerebbe il tuo comando e query in modo che DRY non venga violato in numerose parti del codice. Inoltre, non considererei la violazione SRP (e forse CQS), perché il wrapper ha ancora una sola responsabilità: combinare il comando con una query e creare un'astrazione di livello superiore che sia più facile da utilizzare.

Penso che il metodo wrapper sia una soluzione perfettamente accettabile e per illustrare ciò, facciamo del tuo esempio un ulteriore passo avanti. Cosa fare se si dovessero eseguire 2 query invece di 1 e quindi eseguire un'azione di comando in base a tale. Quindi le tue 2 linee di codice sarebbero 6 o 8. Cosa accadrebbe se ci fosse qualche convalida / verifica dei dati tra l'una e l'altra, quindi ora hai 15 linee di codice. Ci penseresti due volte sulla creazione di un wrapper che faccia tutto questo, invece di cospargere quelle 15 righe in più file?

    
risposta data 31.07.2013 - 21:40
fonte
-3

L'ASCIUTTO è più importante, poiché risolve un bisogno molto più fondamentale, evitando sforzi inutili e ridondanti. Questa è una cosa fondamentale: non è necessario essere un programmatore per capirlo.

CQS è una risposta alla difficoltà, in lingue senza supporto per gli effetti di tracciamento, di comprensione del codice che viene eseguito sia per i suoi risultati sia per i suoi effetti. Tuttavia:

  1. La necessità di eseguire codice per i suoi risultati non può essere evitata, perché questa è la base per comporre programmi di grandi dimensioni da piccole unità.

  2. La necessità di eseguire il codice per i suoi effetti non può essere evitata, perché, al di fuori della matematica e dell'informatica teorica, il valore dell'esecuzione di un programma dipende da ciò che è in grado di fare per noi.

  3. La necessità di causare effetti e produrre risultati nello stesso codice non può essere evitata, perché, in pratica, abbiamo bisogno di effetti e composizionalità, non solo uno o l'altro.

La vera soluzione al problema degli effetti di tracciamento essendo troppo difficile per gli umani non assistiti è, naturalmente, per avere computer Aiuta noi umani ! Una cosa simile si può dire su tenere traccia di relazioni complesse tra i valori di runtime (come la validità degli indici di array), per le quali eccezioni e i contratti imposti dal runtime costituiscono (non) soluzioni.

In conclusione, le "soluzioni" come CQS si limitano a progettare programmi in base a principi validi basati sulla realtà. Vai a DRY.

    
risposta data 01.08.2013 - 05:36
fonte

Leggi altre domande sui tag