Assegnazione booleana delle migliori pratiche [chiuso]


10

Mi sono imbattuto nel seguente condizionale 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 cambiato in quello che pensavo fosse un semplice compito booleano basato su un confronto:

obj.NeedsChange = obj.Performance <= LOW_PERFORMANCE;

Vedendo ciò, qualcuno che ha esaminato il mio codice ha commentato che sebbene la mia modifica sia funzionalmente corretta, potrebbe confondere qualcun altro che lo sta guardando. Crede che l'uso di un operatore ternario renda più chiaro questo compito, mentre non mi piace l'aggiunta di un codice più ridondante:

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

Il suo ragionamento è che fare qualcosa nel modo più conciso non ne 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 per assegnare un valore al booleano obj.NeedsChangeè il più chiaro e il più mantenibile?


25
La terza forma è ridicola; sta solo affermando ciò che dovrebbe già essere palesemente ovvio nella seconda forma.
Robert Harvey,

6
Questo dipende interamente dalle preferenze personali. Possiamo fingere altrimenti, ma poiché sono tutti funzionalmente equivalenti, si riduce allo stile . Certo, c'è una differenza nella leggibilità, ma il mio "leggibile e trasparente" potrebbe essere il tuo "ottuso e opaco"
MetaFight,

3
@scriptin 5-8 righe v 1 riga è più che una preferenza, il 5-8 di solito è più chiaro e migliore. In questo semplice esempio, preferisco la 1 linea, ma in generale ho visto troppe 10 fodere che sono state offuscate in 1 linea per il massimo comfort. Detto questo, non mi sarei mai lamentato della variante 1, potrebbe non essere carino ma fa il lavoro altrettanto chiaramente e ovviamente.
gbjbaanb,

4
Le opzioni 1 e 3 mi dicono "L'autore non capisce davvero la logica booleana".
17 del 26

2
La variante 1 può essere utile se è necessario impostare spesso un punto di interruzione che dipende dal valore.
Ian,

Risposte:


39

Preferisco 2, ma potrei fare una piccola modifica:

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

Per me le parentesi facilitano l'analisi della linea e chiariscono a colpo d'occhio che si sta assegnando il risultato di un confronto e non si sta eseguendo una doppia assegnazione. Non sono sicuro del perché (in quanto non riesco a pensare a una lingua in cui le parentesi impedirebbero effettivamente un doppio incarico), ma se devi soddisfare il tuo recensore, forse questo sarà un compromesso accettabile.


4
questa è la risposta corretta - sebbene il codice nella domanda sia corretto, l'aggiunta delle parentesi indica al lettore che non è un compito. Se cercavi rapidamente il codice, le parentesi ti forniscono quell'informazione extra istantanea che ti impedisce di guardare più da vicino per vedere se il codice voleva essere così, e non era un errore accidentale. Ad esempio, immagina che la linea fosse a = b == c, intendevi assegnare un bool o intendevi assegnare c sia a b che a.
gbjbaanb,

Le parentesi impedirebbero una doppia assegnazione in Python. Anche nelle lingue in cui non impediscono la doppia assegnazione, le parentesi aiutano sicuramente a indicare che hai a che fare con due tipi di operazioni.
user2357112 supporta Monica il

23

La variante 1 è facilmente comprensibile, ma è l'unico vantaggio. Suppongo automaticamente che chiunque scriva in questo modo non capisca veramente di cosa si tratti i booleani e scriverà codice altrettanto infantile sotto molti altri aspetti.

La variante 2 è ciò che scrivo 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 1 e 2. 'Nuff ha detto.


Bene, la variante 1 condivide il suo vantaggio con la variante 2 ...
Deduplicator,

1
+1 per il codice infantile. Ho cercato questo codice per anni, mi mancava solo la parola giusta per identificarlo.
Lilienthal,

1
La mia prima ipotesi con codice come Variant 1 è che i due rami in un punto del passato erano più complicati e qualcuno non prestava attenzione durante il refactoring. Se tuttavia è così che è stato scritto la prima volta, sono d'accordo con "non capire i booleani"
Izkata,

13

Ogni volta che il codice è più complicato di quello che deve essere innesca un "cosa dovrebbe fare questo?" odore nel lettore.

Ad esempio, il primo esempio mi fa meravigliare: "c'erano altre funzionalità nell'istruzione if / else a un certo punto che è stata rimossa?"

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

La lanugine in più in (3) mi farebbe chiedermi perché l'autore lo abbia scritto in questo modo invece di (2). Ci dovrebbe essere una ragione, ma in questo caso non sembra essere, quindi non è utile a tutti e più difficile da leggere perché suggerisce qualcosa di presente, che non c'è la sintassi. Cercare di imparare ciò che è presente (quando non c'è nulla) rende il codice più difficile da leggere.


2

È facile vedere che la variante 2 e la variante 1 sono correlate tramite una serie di refactoring ovvi e semplici:

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

Qui, abbiamo inutili duplicazioni di codice, possiamo scomporre l'assegnazione:

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à vero se la condizione è vera e assegnerà falso 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 il tipico codice da principiante scritto da qualcuno che non capisce quale sia il valore di ritorno di un confronto.


Vorrei aggiungere la tua parte falsa if (...) ... come commento appena prima di quella carina, quindi otterrai la semplice scansione attraverso la chiarezza del codice e il codice migliore.
DaveM,

2

Mentre la programmazione dovrebbe tendono verso esplicito sopra implicito "come se il ragazzo che finisce per mantenere il vostro codice sarà uno psicopatico violento che sa dove si vive", si può supporre alcune cose di base che il vostro successore psico sarà competente.

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

obj.NeedsChange = obj.Performance <= LOW_PERFORMANCE;

è molto chiaro a 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 incline 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 di sbagliato nella sintassi simil-C di molte lingue: ordine delle operazioni incoerente, associatività sinistra / destra incoerente, usi sovraccarichi di simboli, duplicazione parentesi graffe / rientri, operatori ternari, notazione infissi, ecc.

Ma la soluzione non è inventare la tua versione proprietaria. In questo modo risiede la follia, poiché ognuno crea il proprio.


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

Tra un programma non patologico a 200 linee e un programma banalmente identico a 1.600 linee, quello più corto sarà quasi sempre più facile da analizzare e comprendere. Gradirei il tuo cambiamento ogni giorno.


1

La maggior parte degli sviluppatori sarà in grado di comprendere la seconda forma con uno sguardo. A mio avviso, la semplificazione come nella prima forma è semplicemente superflua.

È possibile migliorare la leggibilità aggiungendo spazi e parentesi graffe come:

obj.NeedsChange =    obj.Performance <= LOW_PERFORMANCE;

o

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

come menzionato da Jacob Raihle.

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.