Perché è considerata una cattiva pratica omettere le parentesi graffe? [chiuso]


177

Perché tutti mi dicono che scrivere codice come questo è una cattiva pratica?

if (foo)
    Bar();

//or

for(int i = 0 i < count; i++)
    Bar(i);

Il mio più grande argomento per omettere le parentesi graffe è che a volte può essere il doppio delle linee con loro. Ad esempio, ecco un codice per dipingere un effetto bagliore per un'etichetta in C #.

using (Brush br = new SolidBrush(Color.FromArgb(15, GlowColor)))
{
    for (int x = 0; x <= GlowAmount; x++)
    {
        for (int y = 0; y <= GlowAmount; y++)
        {
            g.DrawString(Text, this.Font, br, new Point(IconOffset + x, y));
        }
     }
 }
 //versus
using (Brush br = new SolidBrush(Color.FromArgb(15, GlowColor)))
    for (int x = 0; x <= GlowAmount; x++)
        for (int y = 0; y <= GlowAmount; y++)
            g.DrawString(Text, this.Font, br, new Point(IconOffset + x, y));

Puoi anche ottenere l'ulteriore vantaggio di concatenarti usingsinsieme senza dover rientrare un milione di volte.

using (Graphics g = Graphics.FromImage(bmp))
{
    using (Brush brush = new SolidBrush(backgroundColor))
    {
        using (Pen pen = new Pen(Color.FromArgb(penColor)))
        {
            //do lots of work
        }
    }
 }
//versus
using (Graphics g = Graphics.FromImage(bmp))
using (Brush brush = new SolidBrush(backgroundColor))
using (Pen pen = new Pen(Color.FromArgb(penColor)))
{
    //do lots of work
}

L'argomento più comune per le parentesi graffe ruota attorno alla programmazione di manutenzione e ai problemi che ne deriverebbero inserendo il codice tra l'istruzione if originale e il risultato previsto:

if (foo)
    Bar();
    Biz();

Domande:

  1. È sbagliato voler usare la sintassi più compatta offerta dalla lingua? Le persone che progettano queste lingue sono intelligenti, non riesco a immaginare che metterebbero una funzione che è sempre male da usare.
  2. Dovremmo o non dovremmo scrivere codice in modo che il minimo comune denominatore possa capire e non avere problemi a lavorarci?
  3. C'è un altro argomento che mi manca?

6
Sono d'accordo con te. Omettili. Periodo.
Andrei Rînea,

67
A chi importa quante linee c'è qualcosa nel 2010. I monitor sono ampi, economici e ad alta risoluzione! Il mio monitor è 2048 X 1152 e ne ho DUE! La leggibilità è molto più importante del salvataggio di 2 linee verticali quando è possibile introdurre facilmente errori sottili che sono difficili da trovare.

51
I monitor sono ampi ed economici, ma non sono alti ed economici. Lo spazio verticale è più scarso dello spazio orizzontale.
Adam Says - Ripristina Monica l'

32
@AdamRuth Girali di lato :)
Zachary Yates

16
Quindi non ti sbagli come Apple con il bug SSL trovato nel febbraio 2014, LOL.
apprese il

Risposte:


183

In realtà, l'unica volta che mi ha davvero morso è stato quando stavo eseguendo il debug e ho commentato la barra ():

if(foo)
  // bar();
doSomethingElse();

A parte questo, tendo ad usare:

if(foo) bar();

Che si occupa del caso di cui sopra.

MODIFICA Grazie per aver chiarito la domanda, sono d'accordo, non dovremmo scrivere il codice al minimo comune denominatore.


31
Ovviamente è un problema, ma penso che il problema più grande per i manutentori sia che aggiungeranno una seconda riga e non si renderanno conto che non fa parte dell'affermazione condizionale, anche se DAVVERO sembra che dovrebbe essere.
danieltalsky,

23
Non mi piace lo stile di una fodera perché vado sempre a cercare il corpo del loop sottostante.
Nosredna,

18
Trovo che lo stile one-liner sia più irritante che utile perché (specialmente in deep nesting - ugh) l'affermazione può essere facilmente ignorata e può derivarne confusione. Uso quasi esclusivamente tali if a singola istruzione per la convalida dell'input (ovvero i rendimenti iniziali) o il controllo del loop (ad esempio ignorando i nomi di file irrilevanti nelle passeggiate del filesystem), tuttavia, dove le righe vuote aiutano a disattivarle dal codice principale.
Alan Plum,

1
Lo stile a una riga nasconde anche la barra () dalla copertura del test. Sembrerà coperto anche se foo è sempre falso.
Bohumil Janda,

1
Questo è un altro modo di dire: "se la fonte avesse incluso le parentesi graffe, non avrei perso tempo durante il debug". - l'aggiunta delle parentesi graffe è banalmente semplice ed evita di lasciare insidie ​​per la persona successiva. L'unico argomento contro è la "leggibilità", che è piuttosto tenue, dato che questo è un caso in cui succede qualcosa di implicito se li ometti.
Andrew Theken,

156

Velocità di lettura ...

A parte ciò che è già stato menzionato. A questo punto, sono già stato condizionato per analizzare le dichiarazioni con parentesi graffe e spazi bianchi. Quindi ho letto:

if (condition)
{
    DoSomething();
}

DoSomethingElse();

Leggermente più veloce di quello che leggo:

if (condition) DoSomething();

DoSomethingElse();

L'ho letto un po 'più lentamente se sembra così:

if (condition) DoSomething();
DoSomethingElse();

L'ho letto significativamente più lentamente del precedente:

if (condition) 
    DoSomething();
DoSomethingElse();

perché non posso fare a meno di rileggerlo nel caso specifico e chiedermi se l'autore intendesse:

if (condition)
{
    DoSomething();
    DoSomethingElse();
}

Già trattato in generale, ma quando si tratterà di leggere quanto segue, lo esaminerò per un po 'per accertarmi di cosa intendesse l'autore. Potrei anche dare la caccia all'autore originale per confermare.

if (condition) 
    DoSomething();
    DoSomethingElse();

29
Il problema è risolto quando, nel tuo quarto campione, inserisci semplicemente una riga vuota dopo l'istruzione if per separarla da DoSomethingElse () Ecco cosa faccio e la leggibilità è praticamente la stessa del primo campione (se non migliore ;-P) Un'altra cosa è che mettere le linee in gruppi di 2 o 3 aiuta significativamente la leggibilità, basta scansionare il codice molto più velocemente.
Piotr Owsiak,

6
Forse è perché sono abituato a Python, ma mettere la prima parentesi graffa sulla stessa riga dell'istruzione if mi permette di leggere + capirlo ancora più velocemente.
Ponkadoodle,

16
Il problema con lo stile senza braccia ti fa sprecare la tua preziosa concentrazione pensando se il blocco ha parentesi graffe piuttosto che cose più importanti. Questo da solo è una ragione sufficiente per usare la convenzione più semplice possibile, che è sempre parentesi graffe.
Nate CK,

2
Le parentesi graffe sono esplicite per natura. Continuerò con quello, grazie.
TheOptimusPrimus

2
Nell'ultimo caso, dai la caccia all'autore originale e sculaccialo ...;)
Per Lundberg,

55

Se è qualcosa di piccolo, scrivilo così:

if(foo()) bar();

Se è abbastanza lungo da dividere in due righe, usa le parentesi graffe.


sì, è quello che faccio anche io. Ti costringe ad aggiungere parentesi graffe se aggiungi un'altra riga ed è abbastanza chiaro vedere che la barra () è in realtà parte dell'if, quindi succederanno cose brutte se la commenterai.
jalf

10
Non molto adatto al debugger, però. Come si imposta un punto di interruzione nella parte "barra"?
Nemanja Trifunovic,

9
@Nemanja: basta posizionare il cursore sulla barra (); e premi F9. Sia VS2005 che VS2008 gestiscono i punti di interruzione all'interno della linea, se sono "istruzioni" separate.
GalacticCowboy,

4
GalanticCowboy: ci sono più ambienti di quelli che conosci. :-)

20
Certo, ma dato che il contesto è C #, questo dovrebbe coprire una maggioranza significativa degli utenti ...
GalacticCowboy,

47

Pensavo anche che fosse meglio usare le parentesi graffe solo quando veramente necessario. Ma non più, il motivo principale, quando hai molto codice, lo rende più leggibile e puoi analizzare il codice più velocemente quando hai uno stile di rinforzo coerente.

Un altro buon motivo per usare sempre le parentesi graffe, oltre a qualcuno che aggiunge una seconda affermazione al if, è qualcosa del genere:

if(a)
   if(b)
     c();
else
   d();

Hai notato che la clausola else è in realtà quella di "if (b)"? Probabilmente l'hai fatto, ma ti fideresti di qualcuno che abbia familiarità con questo gotcha?

Quindi, se solo per coerenza e perché non sai mai quali cose inaspettate potrebbero accadere quando qualcun altro (sono sempre gli altri che sono stupidi) a cambiare il codice, metto sempre delle parentesi graffe, perché rende il codice sorgente più leggibile, più veloce da analizzare il tuo cervello. Solo per le più semplici dichiarazioni if, come un if in cui viene fatta una delega o è simile a switch, in cui sai che la clausola non verrà mai estesa, tralascerei le parentesi graffe.


12
Questo è uno dei due casi in cui uso le parentesi graffe. Altrimenti no.
Andrei Rînea,

3
Questo dovrebbe piuttosto essere scritto come se (a && b) ... in primo luogo si pensi.
alexander.biskop,

8
@ alexander.biskop: Sicuramente no, dato che questo dà al blocco else un significato diverso ( !a || !b) rispetto alle parentesi aggiunte ( !a) o senza ( a && !b).
Ben Voigt,

1
@Ben Voigt: True! Per caso ;-) Mezzo anno e due voti più tardi, qualcuno si rende conto che l'affermazione che ho fatto è sbagliata ... Immagino di non aver prestato sufficiente attenzione ai dettagli, principalmente perché l'intenzione dietro il mio commento era diversa da quella di sottolineare una trasformazione tecnicamente corretta di tale clausola if. Ciò che intendevo dire era che le istruzioni if ​​inline nidificate generalmente diminuiscono la leggibilità (e in particolare la tracciabilità del flusso di controllo), e quindi dovrebbero piuttosto essere combinate in un'unica istruzione (o eludere del tutto). Saluti
alexander.biskop

3
@ alexander.biskop: allo stesso tempo, il debug è più semplice con if nidificati ciascuno con condizioni più semplici, poiché puoi passare da un passaggio all'altro.
Ben Voigt,


35

Le linee sono economiche. La potenza del processore è economica. Il tempo degli sviluppatori è molto costoso.

Come regola generale, a meno che non stia sviluppando un'applicazione assolutamente essenziale in termini di risorse / velocità, commetterei sempre errori sul lato della scrittura del codice che è

(a) Facile per qualsiasi altro sviluppatore di seguire ciò che sto facendo

(b) Commenta parti specifiche del codice che potrebbero averne bisogno

(c) Facile da eseguire il debug se qualcosa va storto

(d) Facile da modificare se deve essere in futuro (ad es. aggiunta / rimozione di codice)

La velocità o l'eleganza accademica del codice è secondaria rispetto a questi fattori dal punto di vista aziendale. Questo non vuol dire che ho deciso di scrivere un codice grosso o brutto, ma questo è il MIO ordine di priorità.

Omettendo le parentesi graffe nella maggior parte dei casi, ciò rende per me (b), (c) e (d) più difficili (nota comunque impossibile). Direi che usare le parentesi graffe o meno non ha effetto su (a).


9
La tua ultima affermazione su (a) è un'opinione secondo cui un gran numero di sviluppatori, inclusi altri poster qui, discuteranno.
Kelly S. francese,

34

Preferisco la chiarezza che offre la parentesi graffa. Sai esattamente cosa si intende e non devi indovinare se qualcuno ha solo preso in giro e li ha lasciati fuori (e ha introdotto un bug). L'unica volta che li ometto è quando inserisco if e action sulla stessa riga. Nemmeno io lo faccio spesso. In realtà preferisco lo spazio bianco introdotto mettendo la parentesi graffa sulla propria linea, anche se da anni di programmazione in stile C di K&R, terminare la linea con una parentesi graffa è una pratica che devo lavorare per superare se l'IDE non lo impone per me.

if (condition) action();  // ok by me

if (condition) // normal/standard for me
{
   action();
}

23

Penso che sia una questione di linee guida per il progetto a cui stai lavorando e gusti personali.

Di solito li ometto quando non sono necessari, tranne alcuni casi come i seguenti:

if (something)
    just one statement; // i find this ugly
else
{
    // many
    // lines
    // of code
}

preferisco

if (something)
{
    just one statement; // looks better:)
}
else
{
    // many
    // lines
    // of code
}

15

Uno dei casi in cui questo può morderti è tornato ai vecchi tempi delle macro C / C ++. So che questa è una domanda C #, ma spesso gli standard di codifica vengono riportati senza i motivi per cui lo standard è stato creato in primo luogo.

Se non stai molto attento quando crei le tue macro, puoi finire col causare problemi con le istruzioni if ​​che non usano {}.

#define BADLY_MADE_MACRO(x) function1(x); function2(x);

if (myCondition) BADLY_MADE_MACRO(myValue)

Ora, non fraintendetemi, non sto dicendo che dovreste sempre fare {} solo per evitare questo problema in C / C ++, ma a causa di ciò ho dovuto affrontare alcuni bug molto strani.


2
se solo tutto il codice si fosse dichiarato tale ... sigh
Nathan Strong l'

15

Uso per pensare allo stesso modo.

Fino a un giorno (perché c'è sempre quel "giorno" che ti cambia la vita per sempre?) Passiamo dalle 24 alle 36 ore di fila senza dormire eseguendo il debug del codice di produzione solo per scoprire che qualcuno non ha messo parentesi graffe combinate con una ricerca / sostituzione .

Era qualcosa del genere.

 if( debugEnabled ) 
      println( "About to save 1 day of work to some very important place.");
 saveDayData();

Ciò che è venuto dopo è stato

 if( debugEnabled ) 
 //     println( "About to save 1 day of work to some very important place.");
 saveDayData();

Si scopre che il sistema generava 500 mb di log al giorno e ci è stato chiesto di fermarlo. Il flag di debug non era abbastanza, quindi una ricerca e sostituire println era in ordine.

Ancora quando l'app andava in produzione il flag di debug era spento e l'importante "saveDayData" non veniva mai chiamato.

MODIFICARE

Ora l'unico posto in cui non uso le parentesi graffe è nel costrutto if / try.

if( object != null ) try { 
     object.close();
} catch( .....

Dopo aver visto uno sviluppatore superstar farlo.


3
Non capisco. Hai una variabile che controlla il debug (debugEnabled) e usi ancora i commenti per disabilitare il debugging ??? Perché non hai impostato debugEnabled su false?
Igor Popov,

Questo non è esattamente lo scenario, ma hai un buon punto. Le cose stupide (come non impostare il debug su false) creano bug sottili e stupidi che sono più difficili da trovare rispetto a bug "ovvi". Non usare le parentesi graffe non è stato di grande aiuto in questo caso.
OscarRyz,

1
@igor Che ne dite perché volevano solo rimuovere una linea di registrazione e non tutte le linee di registrazione?
Gman,

14

Per essere schietto lo vedo come:

I buoni programmatori programmano difensivamente, i cattivi programmatori no.

Dal momento che ci sono molti esempi sopra e le mie esperienze simili con i bug relativi all'oblio delle parentesi graffe, ho imparato il modo più duro per mettere SEMPRE I BRETELLI.

Qualsiasi altra cosa è scegliere lo stile personale rispetto alla sicurezza e questa è chiaramente una cattiva programmazione.

Joel menziona anche questo nel far sembrare sbagliato il codice sbagliato

Una volta che vieni morso da un bug a causa di parentesi graffe mancanti, scopri che le parentesi graffe mancanti sembrano sbagliate perché sai che è un luogo potenziale in cui si può verificare un altro bug.


Se le parentesi graffe aperte vengono posizionate sulle linee da sole, in qualsiasi punto due o più linee rientrate senza una coppia di parentesi appariranno errate, così come qualsiasi coppia di parentesi senza pari. Tale utilizzo costerà una riga vuota nei casi in cui ifun'istruzione controlla un blocco, ma evita la necessità di un blocco nei casi in cui ifun'istruzione controlla una singola azione anziché un blocco.
supercat

14

Sono abbastanza felice di:

foreach (Foo f in foos)
  foreach (Bar b in bars)
    if (f.Equals(b))
      return true;

return false;

Personalmente, non vedo perché

foreach (Foo f in foos)
{
  foreach (Bar b in bars)
  {
    if (f.Equals(b))
    {
      return true;
    }
  }
}

return false;

è più leggibile.

Sì, le linee sono gratuite, ma perché dovrei scorrere pagine e pagine di codice quando potrebbe essere la metà delle dimensioni?

Se c'è una differenza nella leggibilità o nella manutenibilità, allora, sicuramente, metti le parentesi graffe ... ma in questo caso non vedo alcun motivo per.

Inoltre, inserirò sempre parentesi graffe per gli annidati se è dove ho annidato gli altri

if (condition1)
  if (condition2)
    doSomething();
  else (condition2)
    doSomethingElse();

vs

if (condition1)
  if (condition2)
    doSomething();
else (condition2)
  doSomethingElse();

è terribilmente confuso, quindi lo scrivo sempre come:

if (condition1)
{
  if (condition2)
    doSomething();
  else (condition2)
    doSomethingElse();
}

Quando possibile, utilizzo operatori ternari, ma non li annido mai .


ho appena visto che questo sta succedendo nel mio codice :) ho pensato che avrei dato un'occhiata in giro, ed ecco ... è già là fuori :)
Noctis,

10

Sono d'accordo che "se sei abbastanza intelligente da convincere qualcuno a pagarti per scrivere il codice, dovresti essere abbastanza intelligente da non fare affidamento esclusivamente sul rientro per vedere il flusso del codice".

Tuttavia ... possono essere commessi errori e questo è un problema per il debug ... specialmente se stai entrando nel codice di qualcun altro.


10

La mia filosofia è se rende il codice più leggibile, perché non farlo?

Ovviamente devi tracciare la linea da qualche parte, come trovare quel mezzo felice tra nomi di variabili concisi e eccessivamente descrittivi. Ma le parentesi evitano davvero errori e migliorano la leggibilità del codice.

Puoi sostenere che le persone abbastanza intelligenti da essere programmatori saranno abbastanza intelligenti da evitare bug che derivano da dichiarazioni senza parentesi. Ma puoi onestamente dire che non sei mai stato ingannato da qualcosa di così semplice come un errore di ortografia? Minuti come questo possono essere travolgenti quando si guardano grandi progetti.


7
Naturalmente questo è molto soggettivo. Lasciarli fuori qualche volta migliora la leggibilità.
Brian Knoblauch,

È vero, se mai lascio fuori le parentesi, tengo una riga, come altri hanno già detto. Sono stato morso troppe volte ma affermazioni senza parentesi a più righe. Anche se sai di cercarlo, può ancora occasionalmente prenderti.
James McMahon,

10

Ci sono sempre delle eccezioni, ma vorrei discutere contro l'omissione delle parentesi graffe solo quando si trova in una delle forme:

if(x == y)
   for(/* loop */)
   {
      //200 lines
   }

//rampion's example:
for(/* loop */)
{
   for(/* loop */)
      for(/* loop */)
      {
         //several lines
      }
}

Altrimenti, non ho alcun problema.


4
Cattivi esempi. In entrambi i casi, aggiungerei 200 linee per loop nel suo metodo, o preferibilmente diversi metodi.
Adam Jaskiewicz,

2
Vero, ma succede. Inoltre, ogni volta che un blocco è più lungo dello schermo del lettore è alto, avrai questo problema. E non puoi controllare l'altezza dello schermo del tuo lettore di codice. Potrebbero vedere solo un paio di righe su ciascun lato.
rampion

2
Succede Ciò non significa che dovrebbe accadere.
Adam Jaskiewicz,

3
@AdamJaskiewicz Right. Succede Dobbiamo pensare a ciò che accade, piuttosto che a ciò che dovrebbe accadere. Se potessimo limitarci a ciò che dovrebbe accadere, non dovremmo preoccuparci dei bug.
Beska,

10

Di tanto in tanto uso il codice più in basso (più istruzioni using), ma a parte quello ho sempre messo le parentesi graffe. Trovo solo che rende il codice più chiaro. È palesemente ovvio, oltre alla semplice indentazione, che un'istruzione fa parte di un blocco (e quindi probabilmente fa parte di un if etc).

Ho visto il

if (...)
    foo();
    bar();

bug mi morde (o meglio "io e i colleghi" - in realtà non ho introdotto il bug) una volta . Questo nonostante il fatto che i nostri standard di codifica all'epoca raccomandassero l'uso di parentesi graffe ovunque. Mi ci è voluto un tempo sorprendentemente lungo da individuare, perché vedi quello che vuoi vedere. (Era circa 10 anni fa. Forse lo troverei più velocemente ora.)

Naturalmente se usi "parentesi graffa alla fine della riga" riduce le linee extra sostenute, ma personalmente non mi piace lo stile. (Lo uso al lavoro e l'ho trovato meno sgradevole di quanto mi aspettassi, ma è ancora un po 'spiacevole.)


Sostengo sempre il caso che la coerenza sia più importante dello stile reale, perché dovremmo fare un'eccezione solo nel caso di utilizzi?
Bob,

@Bob: buon punto, e lo faccio solo occasionalmente. Non vorrei fingere di avere delle ragioni reali qui :) In realtà, c'è una ragione ragionevole: annidare gli utilizzi (e solo gli usi) in questo modo è abbastanza ovvio, e si finisce ancora con un blocco. Non riesco a vedere immediatamente il pericolo.
Jon Skeet,

Il che non significa che non ci siano pericoli, ovviamente.
Jon Skeet,

1
La migliore soluzione a questo errore: usa Python. (
Sto scherzando

10

Sono impressionato e umiliato dal fatto che i miei colleghi in questo campo della programmazione per computer (tu molto) non siano scoraggiati dalla prospettiva di potenziali bug quando salti le parentesi su blocchi a linea singola.

Suppongo significhi che non sono intelligente. Ho commesso errori in questo caso più volte. Ho fatto il debug degli errori degli altri attorno a questo. Per questo motivo ho visto software distribuito con bug (RDP su una macchina con VS2002 e il carattere della finestra dell'orologio diventerà instabile).

Se guardo tutti gli errori che ho commesso che avrebbero potuto essere evitati con un cambiamento nello stile di codifica, l'elenco è molto lungo. Se non avessi cambiato il mio approccio in ognuno di questi casi, probabilmente non lo avrei mai fatto come programmatore. Ancora una volta, suppongo di non essere intelligente. Per compensare, sono stato un fedele utente di parentesi graffe su blocchi a linea singola per lungo tempo.

Detto questo, alcune cose sono cambiate nel mondo che rendono la regola "tu userai le parentesi graffe su blocchi a linea singola" oggi meno rilevante rispetto a quando Mosè ce la fece scendere:

  • Alcune lingue popolari risolvono il problema facendo leggere il rientro al computer, proprio come fa il programmatore (ad esempio Python).

  • Il mio editor si formatta automaticamente per me, quindi le possibilità che io venga indotto in errore dal rientro sono molto ridotte.

  • TDD significa che se introduco un bug perché vengo confuso da un blocco a linea singola, ho molte più probabilità di scoprire il bug rapidamente.

  • Il refactoring e l'espressività del linguaggio significano che i miei blocchi sono molto più brevi e i blocchi a riga singola si verificano molto più spesso rispetto al solito. Ipoteticamente, con un'applicazione spietata di ExtractMethod, avrei potuto avere solo blocchi a linea singola in tutto il mio programma. (Mi chiedo come sarebbe?)

In effetti, c'è un netto vantaggio che può derivare dal refactoring senza pietà e dall'omissione di parentesi graffe su blocchi a linea singola: quando vedi le parentesi graffe, un piccolo allarme può esplodere nella tua testa che dice "qui la complessità! Attenzione!". Immagina se questa fosse la norma:

if (condition) Foo();   // normal, everyday code

if (condition) 
{
    // something non-trivial hapening; pay attention!
    Foo();
    Bar();
}

Mi sto aprendo all'idea di cambiare la mia convenzione di codifica in qualcosa del tipo "i blocchi a riga singola potrebbero non avere mai parentesi graffe" o "se riesci a mettere il blocco sulla stessa riga della condizione e tutto si adatta a 80 caratteri, omettere le parentesi graffe ". Vedremo.


Come ex programmatore Java, sono pienamente d'accordo che la formattazione automatizzata sia la vera risposta al problema. Non è nemmeno necessario che il tuo editor aggiunga parentesi graffe automaticamente: il rientro automatico da solo può aiutare a evitare molto le ambiguità. Ovviamente ora che sono passato a Python, in primo luogo mi sono abituato a formattare correttamente il mio codice.
Alan Plum,

Mi sento lo stesso per le parentesi graffe. Riguarda la complessità. Idealmente avremmo solo un blocco di linee. Questo è ciò che chiamo leggibilità, non bretelle non necessarie.
Igor Popov,

9

Delle tre convenzioni:

if(addCurleyBraces()) bugFreeSofware.hooray();

e:

if(addCurleyBraces())
    bugFreeSofware.hooray();

e (che rappresentano qualsiasi stile di rientro usando una parentesi graffa di apertura e chiusura):

if(addCurleyBraces()) {
    bugFreeSofware.hooray();
}

Preferisco l'ultimo come:

  • Trovo più facile leggere se tutte le dichiarazioni if ​​sono scritte in modo uniforme.
  • Potrebbe rendere il software un po 'più robusto e privo di bug. Tuttavia, tutti gli IDE moderni e gli editor di testo avanzati dispongono di funzioni di rientro automatico che penso che tutti dovrebbero usare fintanto che non interferiscono con la formattazione dei commenti o vanno contro gli standard del team (in molti casi è possibile creare uno schema di formattazione personalizzato e condividilo con il team). Il mio punto qui è che se il rientro viene eseguito correttamente il rischio di introduzione di bug si riduce un po '.
  • Preferisco che l'espressione e le dichiarazioni booleane vengano eseguite su linee diverse. Mi piace essere in grado di contrassegnare una riga per scopi di debug. Anche se sto usando un IDE in cui posso contrassegnare un'istruzione e passare ad essa, è un'operazione interattiva e potrei dimenticare dove ho iniziato a eseguire il debug o almeno ci vorrà un po 'più di tempo per scorrere il codice diversi volte (poiché devo contrassegnare manualmente la posizione ogni volta durante il debug).

8

I tuoi argomenti principali contro l'uso delle parentesi graffe sono che usano linee aggiuntive e che richiedono un rientro aggiuntivo.

Le linee sono (quasi) libere, ridurre al minimo il numero di righe nel codice non dovrebbe essere un obiettivo.

E il rientro è indipendente dall'uso della parentesi graffa. Nel tuo esempio di "utilizzo" a cascata, continuo a pensare che dovresti rientrarli anche quando ometti le parentesi graffe.


8

Sono un convinto sostenitore della scrittura di codice ordinato e conciso, ma utilizzerei sempre parentesi graffe. Trovo che siano un modo conveniente per vedere rapidamente l'ambito in cui esiste una particolare riga di codice. Non c'è ambiguità, è solo esplicitamente esposto di fronte a te.

Alcuni potrebbero dire che è un caso di preferenza, ma trovo che il flusso logico di un programma sia molto più facile da seguire se è internamente coerente, e non credo che sia coerente scrivere un'istruzione IF come questa;

if(x < y)
    x = y;
else
    y = x;

E un altro come questo;

if(x < y)
{
    x = y;
    x++;
}
else
{
    y = x;
    y++;
}

Preferisco scegliere solo uno stile generale e attenersi ad esso :)


7

Uno dei problemi principali è quando si hanno regioni di battute e non uno liners, insieme con la separazione dal statment controllo ( for, if, cos'hai) e l'estremità del statment.

Per esempio:

for (...)
{
  for (...)
    for (...) 
    {
      // a couple pages of code
    }
  // which for block is ending here?  A good text editor will tell you, 
  // but it's not obvious when you're reading the code
}

4
Perché hai un paio di pagine di codice nel tuo ciclo for comunque?
Adam Jaskiewicz,

b / c Sono una zolla insensibile e sono ossessionata dall'eliminazione del "costo" delle chiamate di funzione. :)
rampion

4
La coppia di pagine di codice dovrebbe avere una funzione separata, di solito.
Jonathan Leffler,

1
mi scusi, intendevo dire che interpretavo il ruolo di una tale zolla. Tuttavia, ritengo che lo stesso problema possa verificarsi per le regioni più brevi, se visualizzato attraverso una finestra piccola. E questo è al di fuori del controllo del programmatore.
rampion

7

Ero un grande sostenitore di "parentesi graffe sono un must!", Ma da quando ho adottato i test unitari, trovo che i miei test unitari proteggano le dichiarazioni senza bretelle da scenari come:

if (foo)
    snafu();
    bar();

Con buoni test unitari, posso tranquillamente omettere parentesi graffe per affermazioni semplici per migliorare la leggibilità (sì, che può essere soggettiva).

In alternativa, per qualcosa di simile a quanto sopra, probabilmente vorrei in linea che assomigli a:

if (foo) snafu();

In questo modo, lo sviluppatore che deve aggiungere bar () alla condizione, sarebbe più adatto a riconoscere la mancanza di parentesi graffe e ad aggiungerle.


2
Hai detto "Non ne ho bisogno", quindi hai dato una ragione per usarlo: leggibilità!
tvanfosson,

4
Non farei affidamento su un Unit Test per trovarlo. LINT forse, Unit test no!
Kristen,

2
@Kristen - L'idea del test unitario è affermare il comportamento del metodo. Se il comportamento cambia (come descritto sopra) il test unitario fallirà. Non vedo il problema in questo.
Liggy,

Ma perché fare affidamento su Unit Test per raccogliere l'evidentemente evidente che dovrebbe essere risolto prima di andare a UT?
Andrew

7

Usa un giudizio personale.

if (foo)
  bar();

va bene da solo. A meno che tu non sia davvero preoccupato per i deficienti che inseriscono qualcosa di simile in seguito:

if (foo)
  bar();
  baz();

Se non sei preoccupato per i deficienti, stai bene (non lo sono - se non riescono a ottenere correttamente la sintassi del codice di base, questo è l'ultimo dei loro problemi)>

In cambio, è molto più leggibile.

Il resto del tempo:

if (foo) {
  bar();
  baz();
}

Quale è stato il mio preferito da quando ricordo. Inoltre:

if (foo) {
  bar();
  baz();
} else {
  qux();
}

Per me va bene.

Lo spazio verticale di per sé non è terribilmente rilevante, la leggibilità lo è. Il tutore di apertura su una linea da solo interrompe la conversazione per un elemento sintattico, fino a quando l'occhio si sposta sulla riga successiva. Non quello che mi piace.


L'unica volta che preferisco il primo stile è quando devo tornare immediatamente o lanciare un errore nel caso in cui qualcosa non vada. Come if (parameter == null) return null;.
nawfal,

7

Ok, questa è una vecchia domanda a cui è stata data una risposta alla morte. Ho qualcosa da aggiungere.

Per prima cosa devo solo dire USARE I BRETELLI. Possono solo aiutare la leggibilità e la leggibilità (per te stesso e gli altri!) Dovrebbe essere molto in cima al tuo elenco di priorità a meno che tu non stia scrivendo assembly. Codice illeggibile sempre, porta sempre a bug. Se scopri che le parentesi graffe occupano troppo spazio nel tuo codice, probabilmente i tuoi metodi sono troppo lunghi. La maggior parte o tutti i metodi dovrebbero adattarsi all'altezza dello schermo se lo stai facendo bene e Trova (F3) è tuo amico.

Ora per la mia aggiunta: c'è un problema con questo:

if (foo) bar();

Prova a impostare un punto di interruzione che verrà colpito solo se la barra () verrà eseguita. Puoi farlo in C # posizionando il cursore sulla seconda metà del codice, ma questo non è ovvio ed è un po 'doloroso. In C ++ non puoi assolutamente farlo. Per questo motivo, uno dei nostri sviluppatori più esperti che lavorano sul codice C ++ insiste per spezzare le istruzioni "if" in due righe. E sono d'accordo con lui.

Quindi fai questo:

if (foo)
{
    bar(); //It is easy to put a breakpoint here, and that is useful.
}

2
Fare clic con il tasto destro sulla barra e selezionare Inserisci punto di interruzione ... Per nulla difficile. Conosci i tuoi strumenti.
Bob,

Fare clic con il tasto destro sulla barra dell'indicatore non fa nulla; vuoi dire fare clic destro sul testo? Ad ogni modo, se si desidera colpire il punto di interruzione solo quando l'istruzione "if" è vera e "bar ()" si trova sulla propria riga, è possibile posizionare il cursore in qualsiasi punto di tale linea e premere F9 oppure fare clic con il tasto sinistro del mouse margine indicatore. Se, tuttavia, tutto il codice si trova su una singola riga, è necessario posizionare il cursore su "barra ()" o fare clic con il pulsante destro del mouse esattamente lì prima di premere F9 e fare clic sul margine dell'indicatore non funzionerà (posiziona il punto di interruzione su " Se'). Non è "difficile", ma richiede meno concentrazione quando il codice è su due righe.
pietra,

Oh, ah ah, fai clic destro su "bar ()." Intendevi il testo. Gotcha. Certo, o basta premere F9 ...
stone

>> devi posizionare il cursore su "bar ()" o fare clic con il tasto destro esattamente lì prima di premere F9, (intendevo posizionare il cursore esattamente lì prima di premere F9 o fare clic con il tasto destro)
pietra

7

per evitare che il codice con parentesi graffe occupi molto spazio, utilizzo la tecnica consigliata nel libro Codice completo :

if (...) {
    foo();
    bar();
}
else {
    ...
}

Non capisco perché è stato downmodded risparmia una riga per ogni coppia di parentesi che lo uso sempre
Eric

2
Questo è più popolarmente noto come stile K&R. Basato sul libro The C Programming Language di Kernighan e Ritchie: en.wikipedia.org/wiki/The_C_Programming_Language_(book) . E non dovrebbe farti modificare.
jmucchiello,

Grazie! Ho pensato che fosse solo un gusto personale. Trovavo fastidiosa questa sintassi, ma l'ho adottata dopo aver letto Code Complete e ora mi diverto molto.
Nathan Prather,

stavo leggendo tutte le risposte sopra questa pensando "perché nessuno ha ancora suggerito questo ???" Rende la parentesi di chiusura allineata con il blocco che sta chiudendo, ovvero "if" o "while", ecc., Non un "{" insignificante. +1.
Nickf

Se le parentesi graffe aperte vengono sempre posizionate sulle linee da sole, allora una ifche è seguita da una singola riga rientrata può essere visivamente riconosciuta come controllo di una singola istruzione senza necessità di parentesi graffe. Lo stile parentesi aperta di per sé salva così gli spazi bianchi nella situazione in cui ifun'istruzione controlla qualcosa che è semanticamente una singola azione (distinta da una sequenza di passaggi che contiene solo un singolo passaggio). Ad esempio, if (someCondition)/ `throw new SomeException (...)`.
supercat

6

Supponiamo che tu abbia del codice:

if (foo)
    bar();

e poi arriva qualcun altro e aggiunge:

if (foo)
    snafu();
    bar();

Secondo il modo in cui è scritto, bar (); viene ora eseguito incondizionatamente. Includendo le parentesi graffe, si impedisce questo tipo di errore accidentale. Il codice dovrebbe essere scritto in modo tale da rendere tali errori difficili o impossibili da compiere. Se stavo facendo una revisione del codice e vedessi le parentesi graffe mancanti, specialmente distribuite su più righe, creerei un difetto. Nei casi in cui è giustificato, tenerlo su una riga in modo che la possibilità di commettere un errore del genere sia nuovamente ridotta al minimo.


Questo punto era già stato posto nell'interrogazione.
Mike Scott,

Non proprio, in realtà. Sì, ha menzionato il potenziale per questo tipo di bug, ma stavo parlando di rendere il tuo codice a prova di bug e rimuovere il potenziale di errore come parte delle migliori pratiche.
Elie,

Esiste davvero un codice a prova di bug?
Bob,

No, ma puoi renderlo più difficile. Leggi "Best Kept Secrets of Peer Code Review" di Jason Cohen (vedi link a lato di alcune pagine qui) per avere un'idea migliore del perché lo fai.
Elie,

Chi è questo Mike Scott e perché è la polizia di risposta? Mi fa sempre arrabbiare il fatto che le persone debbano dichiarare ciò che è ovvio. Quindi perché Mike non ha continuato a commentare la descrizione aggiunta che gli utenti pubblicano su questo problema. Tutte le risposte non si riferiscono alla domanda?
Bruceatk,

6

Ridurre le linee non è davvero un buon argomento per far cadere le parentesi graffe. Se il tuo metodo è troppo grande, probabilmente dovrebbe essere rifattorizzato in pezzi più piccoli o ristrutturato. Fare ciò aumenterà senza dubbio la leggibilità più che semplicemente eliminare le parentesi graffe.


5

Li ometto sempre quando appropriato, come nel tuo primo esempio. Il codice pulito e conciso che posso vedere e comprendere dando un'occhiata è più facile da mantenere, eseguire il debug e capire del codice che devo scorrere e leggere riga per riga. Penso che la maggior parte dei programmatori sarà d'accordo con questo.

È facile che sfugga di mano se inizi a fare l'annidamento multiplo, le clausole if / else e così via, ma penso che la maggior parte dei programmatori dovrebbe essere in grado di dire dove tracciare la linea.

Lo vedo un po 'come l'argomento a favore if ( foo == 0 )vs if ( 0 == foo ). Quest'ultimo può prevenire bug per i nuovi programmatori (e forse anche occasionalmente per i veterani), mentre il primo è più facile da leggere e capire rapidamente quando si mantiene il codice.


4

Il più delle volte è radicato come standard di codifica, sia per un'azienda che per un progetto FOSS.

Alla fine, qualcun altro dovrà eseguire il grok del codice ed è un grande dispendio di tempo per ogni sviluppatore dover capire lo stile specifico della sezione di codice su cui stanno lavorando.

Inoltre, immagina che qualcuno stia passando tra Python e una lingua Cish più di una volta al giorno ... In Python il rientro fa parte del blocco simbolico della lingua e sarebbe abbastanza facile commettere un errore come quello che citi.


+1 per un commento su Python. Sono sempre stupito di quanto possa essere "stupido" quando cambio continuamente da una lingua all'altra.
Kena,

3

Err dalla parte di più sicuro - solo un altro bug che potenzialmente non dovrai correggere.

Personalmente mi sento più sicuro se tutti i miei blocchi sono avvolti in una spirale. Anche per le battute singole, si tratta di semplici notazioni che prevengono facilmente gli errori. Rende il codice più leggibile, nel senso che vedi chiaramente cosa c'è nel blocco per non confondere il corpo del blocco con le seguenti istruzioni al di fuori del blocco.

Se ho un liner, in genere lo formatto come segue:

if( some_condition ) { do_some_operation; }

Se la linea è troppo ingombrante, utilizzare quanto segue:

if( some_condition )
{
    do_some_operation;
}
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.