Assegnazione booleana delle migliori pratiche [chiusa]

11

Mi sono imbattuto in quanto segue in un programma che ho rilevato da un altro sviluppatore:

if (obj.Performance <= LOW_PERFORMANCE)
{
    obj.NeedsChange = true;
}
else
{
    obj.NeedsChange = false;
}

Credo che questo codice sia ridondante e brutto, quindi l'ho modificato in quello che pensavo fosse un semplice compito booleano basato su un confronto:

obj.NeedsChange = obj.Performance <= LOW_PERFORMANCE;

Dopo aver visto ciò, qualcuno che ha revisionato il mio codice ha commentato che sebbene il mio cambiamento sia funzionalmente corretto, potrebbe confondere qualcun altro a guardarlo. Crede che l'uso di un operatore ternario renda questo compito più chiaro, mentre non mi piace l'aggiunta di un codice ridondante:

obj.NeedsChange = (obj.Performance <= LOW_PERFORMANCE) ? true : false;

Il suo ragionamento è che fare qualcosa nel modo più conciso non vale la pena, se fa sì che un altro sviluppatore debba fermarsi e risolvere esattamente ciò che hai fatto.

La vera domanda qui è quale di questi tre metodi di assegnazione di un valore al% booleano% co_de è il più chiaro e il più mantenibile?

    
posta Zach Posten 17.06.2015 - 16:41
fonte

6 risposte

40

Preferisco 2, ma potrei fare un piccolo aggiustamento ad esso:

obj.NeedsChange = ( obj.Performance <= LOW_PERFORMANCE );

Per me le parentesi rendono la linea più facile da analizzare e chiariscono a colpo d'occhio che stai assegnando il risultato di un confronto e non esegui un doppio incarico. Non sono sicuro del motivo (non potrei pensare a una lingua in cui le parentesi impediscono effettivamente un doppio incarico), ma se devi soddisfare il tuo revisore, forse questo sarà un compromesso accettabile.

    
risposta data 17.06.2015 - 17:09
fonte
23

La variante 1 è facilmente comprensibile, ma questo è il suo unico vantaggio. Assumo automaticamente che chiunque scriva in questo modo non capisca veramente cosa siano i booleani, e scriverà un codice simile a quello infantile sotto molti altri aspetti.

La variante 2 è ciò che scriverò sempre e mi aspetto di leggere. Penso che chiunque sia confuso da quell'idioma non dovrebbe essere uno scrittore professionista di software.

La variante 3 combina gli svantaggi di entrambi 1 e 2. "nuff said.

    
risposta data 17.06.2015 - 16:46
fonte
13

Ogni volta che il codice è più complicato di quanto non debba essere attivato un "cosa si suppone stia facendo?" odore nel lettore.

Ad esempio, il primo esempio mi fa meraviglia, "c'era un'altra funzionalità nell'istruzione if / else che è stata rimossa?"

Esempio (2) è semplice, chiaro e fa esattamente ciò che è necessario. L'ho letto e ho capito immediatamente che cosa fa il codice.

L'extra fluff in (3) mi indurrebbe a chiedermi perché l'autore abbia scritto in quel modo invece che in (2). Lì dovrebbe essere una ragione, ma in questo caso non sembra esserci, quindi non è affatto utile e difficile da leggere perché la sintassi suggerisce qualcosa di presente che non è presente. Cercare di sapere cosa è presente (quando nulla è) rende il codice più difficile da leggere.

    
risposta data 17.06.2015 - 16:52
fonte
2

È facile vedere che Variant 2 e Variant 1 sono correlati tramite una serie di refactoring ovvi e semplici:

if (obj.Performance <= LOW_PERFORMANCE)
{
    obj.NeedsChange = true;
}
else
{
    obj.NeedsChange = false;
}

Qui, abbiamo la duplicazione del codice inutile, possiamo calcolare il compito:

obj.NeedsChange = if (obj.Performance <= LOW_PERFORMANCE)
{
    true
}
else
{
    false
}

o scritto in modo più conciso:

obj.NeedsChange = if (obj.Performance <= LOW_PERFORMANCE) true else false

Ora dovrebbe essere immediatamente ovvio che questo assegnerà true se la condizione è vera e assegnerà false se la condizione è falsa, IOW assegnerà semplicemente il valore della condizione, cioè è equivalente a

obj.NeedsChange = obj.Performance <= LOW_PERFORMANCE

Le varianti 1 e 3 sono tipiche codice rookie scritto da qualcuno che non capisce quale sia il valore di ritorno di un confronto.

    
risposta data 17.06.2015 - 18:39
fonte
2

Mentre la tua programmazione dovrebbe tendere verso l'esplicito implicito "come se il ragazzo che finisce per mantenere il tuo codice sarà uno psicopatico violento che sa dove vivi", tu puoi assumere alcuni cose di base in cui il tuo psico successore sarà competente.

Uno di questi è la sintassi della lingua che sta utilizzando.

obj.NeedsChange = obj.Performance <= LOW_PERFORMANCE;

è molto chiaro per chiunque conosca la sintassi C / C ++ / C # / Java / Javascript.

È anche molto più leggibile di 8 righe.

if (obj.Performance <= LOW_PERFORMANCE)
{
    obj.NeedsChange = true;
}
else
{
    obj.NeedsChange = false;
}

e meno inclini agli errori

if (obj.Performance <= LOW_PERFORMANCE)
{
    obj.NeedsChange = true;
}
else
{
    obj.Needschange = false;
}

Ed è meglio che aggiungere caratteri non necessari, come se avessi quasi dimenticato la sintassi della lingua:

obj.NeedsChange = obj.Performance <= LOW_PERFORMANCE ? true : false;

obj.NeedsChange = (obj.Performance <= LOW_PERFORMANCE);

Penso che ci sia molto sbagliato nella sintassi C-like di molte lingue: ordine delle operazioni incoerente, associatività sinistra / destra inconsistente, uso sovraccarico di simboli, parentesi graffe / rientri indentazione, operatori ternari, notazione infisso, ecc.

Ma la soluzione non è inventare la tua versione proprietaria di esso. In questo modo giace la follia, come ognuno crea il proprio.

Generalmente la cosa numero 1 che rende illeggibile il codice TM di Real World è la quantità di esso.

Tra un programma di linea 200 non patologico e un programma di linea di 1.600 banalmente identico, il più breve sarà quasi sempre più facile da analizzare e capire. Sarei felice di dare il cambio ogni giorno.

    
risposta data 17.06.2015 - 19:54
fonte
1

La maggior parte degli sviluppatori sarà in grado di comprendere il 2 ° modulo con un'occhiata. Secondo me, la semplificazione come nella prima forma è semplicemente inutile.

Puoi migliorare la leggibilità aggiungendo spazi e parentesi come:

obj.NeedsChange =    obj.Performance <= LOW_PERFORMANCE;

o

obj.NeedsChange = ( obj.Performance <= LOW_PERFORMANCE );

come citato da Jacob Raihle.

    
risposta data 17.06.2015 - 20:31
fonte

Leggi altre domande sui tag