È una cattiva pratica usare un'istruzione if senza parentesi graffe? [chiuso]


130

Ho visto un codice come questo:

if(statement)
    do this;
else
    do this;

Tuttavia, penso che questo sia più leggibile:

if(statement){
    do this;
}else{
    do this;
}

Poiché entrambi i metodi funzionano, è semplicemente una questione di preferenza che usare o sarebbe raccomandata in un modo rispetto all'altro?



Secondo me è negativo, perché inizi a fare affidamento sul rientro degli spazi bianchi che non è quasi mai del tutto coerente. Fa deragliare il filo del pensiero del lettore quando devono preoccuparsi di queste cose.
Sridhar Sarnobat,

Risposte:


212

Il problema con la prima versione è che se torni indietro e aggiungi una seconda istruzione alle clausole if or else senza ricordare di aggiungere le parentesi graffe, il tuo codice si spezzerà in modi inaspettati e divertenti.

Per quanto riguarda la manutenibilità, è sempre più intelligente utilizzare la seconda forma.

EDIT: Ned lo sottolinea nei commenti, ma vale la pena collegarlo anche qui, penso. Questa non è solo un'ipotetica stronzata sulla torre d'avorio: https://www.imperialviolet.org/2014/02/22/applebug.html


17
E dovresti sempre programmare per manutenibilità. Dopotutto, sono abbastanza sicuro che al compilatore non importi quale forma usi. I tuoi colleghi, tuttavia, potrebbero essere pist se introduci un bug a causa di un errore di parentesi graffa riccia sciocca.
Esteban Araya,

12
Oppure potresti usare un linguaggio che non usa parentesi per i blocchi di codice ...
Tor Valamo,

10
@ lins314159 - No, intendo come il pitone. Perché sono sciovinista in questo senso.
Tor Valamo,

17
Ulteriori errori di prova possono (e fanno) accadere: imperialviolet.org/2014/02/22/applebug.html
Ned

8
Affermare che il bug SSL è un argomento a favore delle parentesi graffe è disonesto. Non è come se lo sviluppatore intendesse scrivere if (…) { goto L; goto L; }ma ha dimenticato le parentesi graffe. È puramente casuale che `` if (…) {goto L; vai a L; } `sembra non essere un bug di sicurezza, perché è ancora un bug (ma non uno con conseguenze sulla sicurezza). In un altro esempio, le cose potrebbero andare nella direzione opposta e il codice senza braccia potrebbe essere accidentalmente sicuro. Su un terzo esempio, il codice senza braccia sarebbe inizialmente privo di bug e lo sviluppatore avrebbe introdotto un refuso durante l'aggiunta delle parentesi graffe.
Pascal Cuoq,

112

Un problema con l'esclusione dei blocchi di istruzioni è l'ambiguità else. Cioè le lingue ispirate al C ignorano il rientro e quindi non hanno modo di separarlo:

if(one)
    if(two)
        foo();
    else
        bar();

Da questa:

if(one)
    if(two)
        foo();
else
    bar();

8
Questo è un problema molto più grave di quello menzionato nella risposta in alto (aggiunta di una seconda affermazione).

3
in effetti, questa risposta in realtà mi ha portato dalla lettura di queste risposte cinicamente all'essere leggermente preoccupato che avrei potuto effettivamente commettere questo errore.
omike

2
Se qualcun altro si chiedeva come fossi in che modo C lo interpreta effettivamente, un test che ho fatto con GCC interpreta questo codice nel primo modo. tpcg.io/NIYeqx
horta,

2
"ambiguità" è il termine sbagliato. Non c'è alcuna ambiguità nel modo in cui il parser vedrà questo: il elselegame si avida al più vicino, il più profondo if. Il problema sorge dove la C o linguaggi simili vengono codificati da persone che non lo conoscono, non ci pensano o non hanno ancora abbastanza caffè - quindi scrivono codice che pensano che farà una cosa, ma il la specifica della lingua dice che il parser deve fare qualcos'altro, che potrebbe essere molto diverso. E sì, questo è un altro argomento solido a favore di includere sempre parentesi graffe anche se la grammatica li contrassegna come teoricamente "inutili".
underscore_d

35

Il mio modello generale è che se si adatta su una riga, farò:

if(true) do_something();

Se esiste una clausola else o se il codice su cui voglio eseguire trueè di lunghezza significativa, parentesi graffe fino in fondo:

if(true) {
    do_something_and_pass_arguments_to_it(argument1, argument2, argument3);
}

if(false) {
    do_something();
} else {
    do_something_else();
}

In definitiva, si tratta di una questione soggettiva di stile e leggibilità. Il mondo generale della programmazione, tuttavia, si divide praticamente in due parti (per i linguaggi che usano le parentesi graffe): o usali sempre senza eccezioni, o usali sempre con eccezioni. Faccio parte di quest'ultimo gruppo.


4
Anche se, per quanto sia facile da scrivere if(true){ do_something(); }, perché cogliere l'occasione per fare in modo che un altro programmatore introduca un grave bug lungo la strada (ricerca del codice totale ssl "goto fail" di Apple).
Craig,

9
Nessuna quantità di parentesi libererà il manutentore dall'usare il suo cervello. Sostengo l'idea di "nessuna parentesi se si adatta a una riga" perché, beh, per me un tale if è solo una versione dell'operatore ternario se in cui non è necessario fare nulla nella parte "after:" di ternario. E perché qualcuno dovrebbe introdurre parentesi ternarie se ?
Michal M,

Non sono affatto d'accordo sul fatto che alla fine sia soggettivo, né che influisca solo sullo stile e sulla leggibilità. Come qualcuno che ha perso tempo a cercare di eseguire il debug di problemi che si sono rivelati causati da delimitatori di blocchi mancanti (e senza notare la loro assenza), perché ho dovuto usare uno stile di codifica che li omette quando "non necessario" - e che ha letto di numerosi terribili bug molto probabilmente causati da tali stili di codifica - penso che questo sia un problema molto obiettivo e pratico. Certo, con uno stile che obbliga i delimitatori, possiamo ancora dimenticarli, ma sicuramente - almeno - la memoria muscolare ci rende molto meno propensi a farlo.
underscore_d

10

Sto usando il formattatore di codice dell'IDE che uso. Potrebbe essere diverso, ma può essere impostato in Preferenze / Opzioni.

Mi piace questa:

if (statement)
{
    // comment to denote in words the case
    do this;
    // keep this block simple, if more than 10-15 lines needed, I add a function for it
}
else
{
    do this;
}

5
Trattandosi di un problema di stile totalmente soggettivo, personalmente non mi piace la ridondanza delle linee solo parentesi graffe. Ma hey.
Matchu,

14
Sostengo questo stile. La maggior parte delle persone legge il codice da sinistra a destra e in qualche modo rende i nostri occhi ancorati al bordo sinistro dello schermo. Aiuta a separare visivamente ed estrarre il codice in blocchi logici di passaggi.
mloskot,

6
Ho sempre preferito questo stile. Molto più facile trovare la corrispondente parentesi di chiusura. Quindi ci vuole molto spazio? Usa un carattere più piccolo.
giorno

4
Trovo sempre più facile "scansionare" il codice quando le parentesi graffe si trovano su linee separate. Questo vale per tutto; classi, metodi, istruzioni if ​​e while, eccetera. Non mi è mai piaciuto avere quel primo tutore sulla stessa linea ...
Svish,

2
Lo spazio bianco è economico, specialmente quando si dispone di un IDE in grado di piegare il codice.
Moo,

10

La "regola" che seguo è questa:

Se l'istruzione "if" sta testando per fare qualcosa (funzioni di chiamata IE, configurare variabili ecc.), Usare le parentesi graffe.

if($test)
{
    doSomething();
}

Questo perché sento che è necessario chiarire quali funzioni vengono chiamate e dove sta andando il flusso del programma, a quali condizioni. Far capire al programmatore esattamente quali funzioni sono chiamate e quali variabili sono impostate in questa condizione è importante per aiutarli a capire esattamente cosa sta facendo il programma.

Se l'istruzione "if" sta eseguendo il test per smettere di fare qualcosa (controllo del flusso IE all'interno di un loop o di una funzione), utilizzare una riga singola.

if($test) continue;
if($test) break;
if($test) return;

In questo caso, ciò che è importante per il programmatore è scoprire rapidamente quali sono i casi eccezionali in cui non si desidera eseguire il codice, e questo è tutto coperto in $ test, non nel blocco di esecuzione.


8

Avere le parentesi graffe fin dal primo momento dovrebbe aiutarti a evitare di dover eseguire il debug di questo:

if (statement)
     do this;
else
     do this;
     do that;

1
Questa sembra essere la logica accettata, ma (per interpretare qui l'avvocato del diavolo) una singola regola aggiuntiva di evidenziazione della sintassi non risolverebbe anche questo, salvando una riga?
Ken,

2
Quindi avremo un IDE che corregge il rientro quando colpisci ;:)
Sam Harwell,

6

Usa parentesi graffe per tutte le dichiarazioni if ​​anche quelle semplici. Oppure, riscrivi un'istruzione if semplice per usare l'operatore ternario:

if (someFlag) {
 someVar= 'someVal1';
} else {
 someVar= 'someVal2';
}

Sembra molto più bello in questo modo:

someVar= someFlag ? 'someVal1' : 'someVal2';

Ma usa l'operatore ternario solo se sei assolutamente sicuro che non c'è nient'altro che deve andare nei blocchi if / else!



2

Dalla mia esperienza, l'unico (molto) leggero vantaggio del primo modulo è la leggibilità del codice, il secondo modulo aggiunge "rumore".

Ma con gli IDE moderni e l'autogenerazione del codice (o il completamento automatico) consiglio vivamente di utilizzare il secondo modulo, non passerai altro tempo a digitare parentesi graffe ed eviterai alcuni dei bug più frequenti.

Ci sono abbastanza bug che consumano energia, la gente non dovrebbe aprire le porte per grandi sprechi di tempo.

Una delle regole più importanti da ricordare quando si scrive il codice è la coerenza. Ogni riga di codice deve essere scritta allo stesso modo, indipendentemente da chi l'ha scritto. Essere rigorosi impedisce ai "bug" di accadere;)

Questo è lo stesso con la denominazione chiara ed esplicita di variabili, metodi, file o con il rientro corretto ...

Quando i miei studenti accettano questo fatto, smettono di combattere contro il loro codice sorgente e iniziano a vedere il codice come un'attività davvero interessante, stimolante e creativa. Sfidano le loro menti, non i loro nervi!


2

È una questione di preferenza. Personalmente uso entrambi gli stili, se sono ragionevolmente sicuro che non avrò bisogno di aggiungere più istruzioni, io uso il primo stile, ma se ciò è possibile, io uso il secondo. Dato che non puoi aggiungere più dichiarazioni al primo stile, ho sentito alcune persone sconsigliare di usarlo. Tuttavia, il secondo metodo comporta una riga di codice aggiuntiva e se tu (o il tuo progetto) utilizzate questo tipo di stile di codifica, il primo metodo è molto preferito per le semplici istruzioni if:

if(statement)
{
    do this;
}
else
{
    do this;
}

Tuttavia, penso che la migliore soluzione a questo problema sia in Python. Con la struttura a blocchi basata su spazi bianchi, non hai due diversi metodi per creare un'istruzione if: ne hai solo una:

if statement:
    do this
else:
    do this

Sebbene questo abbia il "problema" di non poter usare affatto le parentesi graffe, ottieni il vantaggio che non ci sono più linee rispetto al primo stile e ha il potere di aggiungere più istruzioni.


Personalmente penso che il modo in cui Python gestisce le istruzioni if-else sia molto brutto, ma, di nuovo, non sono un programmatore Python (ancora)
helpermethod

1

Ho sempre cercato di rendere il mio codice standard e di apparire il più vicino possibile allo stesso. Questo rende più facile per gli altri leggerlo quando hanno il compito di aggiornarlo. Se fai il tuo primo esempio e aggiungi una linea nel mezzo, fallirà.

Non funzionerà:

se (istruzione) farlo; e questo; altrimenti fai questo;


1

Personalmente uso il primo stile solo per lanciare un'eccezione o tornare prematuramente da un metodo. Come argomento Controllo all'inizio di una funzione, perché in questi casi raramente ho più di una cosa da fare e non c'è mai un altro.

Esempio:

if (argument == null)
    throw new ArgumentNullException("argument");

if (argument < 0)
    return false;

Altrimenti uso il secondo stile.


1

La mia preferenza personale sta usando una miscela di spazi bianchi e parentesi come questa:

if( statement ) {

    // let's do this

} else {

    // well that sucks

}

Penso che questo appaia pulito e rende il mio codice molto facile da leggere e, soprattutto, il debug.


0

Sono d'accordo con la maggior parte delle risposte nel fatto che è meglio essere espliciti nel codice e utilizzare le parentesi graffe. Personalmente adotterò una serie di standard di codifica e assicurerei che tutti i membri del team li conoscano e si conformino. Dove lavoro, usiamo gli standard di codifica pubblicati da IDesign.net per i progetti .NET.


0

Preferisco mettere una parentesi graffa. Ma a volte, l'operatore ternario aiuta.

Invece di :

int x = 0;
if (condition) {
    x = 30;
} else {
    x = 10;
}

Uno dovrebbe semplicemente fare: int x = condition ? 30 : 20;

Immagina anche un caso:

if (condition)
    x = 30;
else if (condition1)
    x = 10;
else if (condition2)
    x = 20;

Sarebbe molto meglio se inserissi la parentesi graffa.

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.