Corretto il commento per mettere gli argomenti della funzione booleana che sono "falsi"?

18

Da alcuni progetti open source, ho raccolto il seguente stile di codifica

void someFunction(bool forget);

void ourFunction() {
  someFunction(false /* forget */);
}    

Ho sempre dei dubbi su ciò che false significa qui. Significa "dimenticare" o il "dimenticare" si riferisce al parametro corrispondente (come nel caso precedente) e "falso" significa negarlo?

Quale stile viene usato più spesso e qual è il modo migliore (o alcuni dei modi migliori) per evitare l'ambiguità?

    
posta Johannes Schaub - litb 20.09.2013 - 17:23
fonte

12 risposte

33

Nel codice di esempio che hai pubblicato, sembra che forget sia un argomento flag. (Non posso esserne certo perché la funzione è puramente ipotetica.)

Gli argomenti flag sono un odore di codice. Indicano che una funzione fa più di una cosa e una buona funzione dovrebbe fare solo una cosa.

Per evitare l'argomento flag, suddividere la funzione in due funzioni che spiegano la differenza nel nome della funzione.

Argomento flag

serveIceCream(bool lowFat)

Nessun argomento flag

serveTraditionalIceCream()
serveLowFatIceCream()

modifica: Idealmente, non è necessario mantenere una funzione con il parametro flag. Ci sono casi sulla falsariga di ciò che Fowler chiama un'implementazione aggrovigliata dove separare completamente le funzioni crea codice duplicato. Tuttavia, maggiore è la complessità ciclomatica della funzione parametrizzata, più strong è l'argomento per sbarazzarsi di esso.

Questa è solo un'intuizione, ma un parametro chiamato forget suona come l'invidia delle funzionalità. Perché un chiamante dovrebbe dire a un altro oggetto di dimenticare qualcosa? Potrebbe esserci un problema di design più grande.     
risposta data 20.09.2013 - 18:38
fonte
27

In parole semplici:

  • false è un valore letterale.
  • stai passando un valore letterale false
  • stai dicendo someFunction per non dimenticare
  • stai dicendo a someFunction che il parametro dimentica è false
  • stai dicendo a someFunction di ricordare

Secondo me sarebbe meglio se la funzione fosse così:

void someFunction(bool remember);

puoi chiamarlo

void ourFunction() {
  someFunction(true);
} 

o mantieni il vecchio nome ma modifica la funzione wrapper in

void ourFunctionWithRemember() {
  someFunction(false);
} 

Modifica

Come dichiarato da @Vorac, cerca sempre di usare parole positive. La doppia negazione è confusa.

    
risposta data 20.09.2013 - 17:38
fonte
14

Il parametro potrebbe essere ben denominato; è difficile dirlo senza conoscere il nome della funzione. Suppongo che il commento sia stato scritto dall'autore originale della funzione, ed era un promemoria di cosa significa passare false in someFunction , ma per chi arriva dopo, è un po 'poco chiaro a prima vista.

Uso di un nome della variabile positiva (suggerito in < a href="http://www.cc2e.com/"> Codice completo ) potrebbe essere la modifica più semplice che renderebbe più semplice leggere questo frammento, ad esempio

void someFunction(boolean remember);

allora ourFunction diventa:

void ourFunction() {
    someFunction(true /* remember */);
}

Tuttavia, l'utilizzo di una enumerazione rende la chiamata della funzione ancora più semplice da comprendere, a scapito di alcuni codici di supporto:

public enum RememberFoo {
    REMEMBER,
    FORGET
}

...

void someFunction(RememberFoo remember);

...

void ourFunction() {
    someFunction(RememberFoo.REMEMBER);
}

Se non riesci a cambiare la firma di someFunction per qualsiasi motivo, l'uso di una variabile temporanea rende il codice più facile da leggere, un po 'come semplificare i condizionali introducendo una variabile per nessun altro motivo se non quello di rendere codice più facile da analizzare dagli umani.

void someFunction(boolean remember);

...

void ourFunction() {
    boolean remember = false;
    someFunction(remember);
}
    
risposta data 20.09.2013 - 17:54
fonte
10

Rinomina la variabile in modo che il valore bool abbia un senso.

Questo è un milione di volte meglio dell'aggiunta di un commento per spiegare argomenti a una funzione perché il nome è ambiguo.

    
risposta data 20.09.2013 - 17:33
fonte
5

Crea un booleano locale con un nome più descrittivo e assegna il valore ad esso. In questo modo il significato sarà più chiaro.

void ourFunction() {
    bool takeAction = false;  /* false means to forget */
    someFunction( takeAction );
}    

Se non riesci a rinominare la variabile, il commento dovrebbe essere un po 'più espressivo:

void ourFunction() {
    /* false means that the method should forget what was requested */
    someFunction( false );
}    
    
risposta data 20.09.2013 - 17:31
fonte
3

C'è un buon articolo che menziona questa esatta situazione in quanto si riferisce alle API Qt-Style. È chiamato La trappola dei parametri booleani e vale la pena leggerlo.

Il suo significato è:

  1. Il sovraccarico della funzione in modo che il bool non sia necessario è migliore
  2. Usare un enum (come suggerisce Esailija) è il migliore
risposta data 20.09.2013 - 19:42
fonte
2

Questo è un commento bizzarro.

Dal punto di vista del compilatore, someFunction(false /* forget */); è in realtà someFunction(false); (il commento è spogliato). Quindi, tutto ciò che la linea fa è chiamare someFunction con il primo (e unico) argomento impostato su false .

/* forget */ è solo il nome del parametro. Probabilmente non è altro che un veloce (e sporco) promemoria, che non ha davvero bisogno di essere lì. Basta usare un nome di parametro meno ambiguo e non ti servirà affatto il commento.

    
risposta data 20.09.2013 - 17:31
fonte
1

Mi piace la risposta su come rendere il commento sempre vero , ma nonostante ciò penso che manchi il problema fondamentale con questo codice - viene chiamato con un letterale.

Dovresti evitare di usare valori letterali quando chiami metodi. Variabili locali, parametri opzionali, parametri nominati, enumerazioni: il modo migliore per evitarli dipende dal linguaggio e da cosa è disponibile, ma cerca di evitarli. I valori letterali hanno valori, ma non hanno significato.

    
risposta data 21.09.2013 - 05:20
fonte
1

Uno dei consigli di Pulisci codice è di ridurre al minimo il numero di commenti non necessari 1 (perché tendono a marcire) e per denominare correttamente funzioni e metodi.

In seguito, vorrei solo rimuovere il commento. Dopo tutto, gli IDE moderni (come l'eclissi) fanno scoppiare una casella con il codice quando si passa un mouse sopra la funzione. Vedere il codice dovrebbe eliminare l'ambiguità.

1 Commentare un codice complesso è ok.

    
risposta data 20.09.2013 - 20:44
fonte
1

Per giudicare l'ovvio, i commenti possono mentire. Quindi è sempre meglio rendere il tuo codice auto-documentabile senza ricorrere a commenti da spiegare, perché qualcuno (forse tu) cambierà true in false e non aggiornerà il commento.

Se non riesci a modificare l'API, ricorro a 2 opzioni

  • Modifica il commento in modo che sia sempre true, indipendentemente dal codice. Se la chiami solo una volta, questa è una buona soluzione, dal momento che mantiene documention local.
     someFunction( false /* true=forget, false=remember */);'
  • Utilizza #defines, specialmente se lo chiami più di una volta.
     #define FORGET   true
     #define REMEMBER false
     someFunction(REMEMBER);
    
risposta data 20.09.2013 - 23:32
fonte
-1

In C #, ho usato i parametri con nome per renderlo più chiaro

someFunction(forget: false);

O enum :

enum Memory { Remember, Forget };

someFunction(Memory.Forget);

O sovraccarichi:

someFunctionForget();

O polimorfismo ':

var foo = new Elephantine();

foo.someFunction();
    
risposta data 21.09.2013 - 01:18
fonte
-2

La denominazione dovrebbe sempre risolvere l'ambiguità per i booleani. Io nomino sempre qualcosa di booleano come "isThis" o "shouldDoThat", ad esempio:

void printTree(Tree tree, bool shouldPrintPretty){ ... }

e così via. Ma quando fai riferimento al codice di qualcun altro, è meglio lasciare un commento quando passi i valori.

    
risposta data 21.09.2013 - 08:38
fonte

Leggi altre domande sui tag