Per quanto riguarda la manutenzione, `else while` senza interventi ortodontici è considerato sicuro?


26

È else whilesenza intervenire bretelle considerati manutenzione "sicuro" saggio?

Scrivere if-elsecodice senza parentesi graffe come di seguito ...

if (blah)
    foo();
else
    bar();

... comporta un rischio perché la mancanza di parentesi graffe rende molto semplice modificare inavvertitamente il significato del codice.

Tuttavia, sotto è anche rischioso?

if (blah)
{
    ...
}
else while (!bloop())
{
    bar();
}

O else whilesenza le parentesi graffe senza intervento è considerato "sicuro"?


20
per me else whilesembra icky. Vorrei usare else { while (condition) { ... } }.
Joachim Sauer,

7
Penso che sia troppo soggettivo per una risposta corretta ... Io stesso non lo farei perché non mi aspetto un ciclo lì, e penso che non mi aspetto di rendere difficile la leggibilità.
johannes,

7
Vorrei estrarre il metodo per while-stuff
moscerino il

12
Onestamente, mi dà i brividi. ifviene valutato solo una volta, ma whileindica un loop, quindi il collegamento di entrambi mi dà la sensazione non if
comprovata

4
E se nella elseclausola vuoi fare while e fare qualcosa di più? Usa solo le parentesi graffe, per favore.
Carlos Campderrós,

Risposte:


57

Questo mi ricorda questo codice:

if ( ... ) try {
..
} catch (Exception e) {
..
} else {
...
}

Ogni volta che si combinano due tipi di blocchi, dimenticando le parentesi graffe e non aumentando il rientro, si sta creando un codice molto difficile da capire e mantenere.


18
Buon esempio. Che modo orribile di scriverlo.
Leone,

4
Caspita, questa risposta è ridicolmente convincente!
Mehrdad,

È possibile configurare facilmente IDE moderni per formattare automaticamente il codice al salvataggio, incluso l'inserimento di parentesi graffe e la correzione del rientro. Quindi questo è solo mezzo argomento. Un rientro corretto non costituirebbe un problema per la leggibilità, sia che ci siano parentesi graffe o meno.
Hans-Peter Störr,

55

Forse è perché ho imparato il mio mestiere (molto tempo fa) usando il metodo Jackson Entity Structure Diagram , ma sottoscrivo l'opinione secondo cui l'unico termine corretto senza limiti dopo un ifo un elseè un successivo if(ovvero consentire una else ifscala)

Qualsiasi altra cosa (nessun gioco di parole intenzionale) lascia il potenziale per incomprensioni e / o problemi di manutenzione. Questo è l'aspetto centrale dell'idea che i PO siano "non sicuri".

Sarei anche molto cauto nell'includere while()la stessa linea del else- se rinforzato o no. Non mi sembra giusto ... la mancanza di maschere di rientro extra che è la elseclausola. E la mancanza di chiarezza crea incomprensioni (vedi sopra).

Quindi nell'esempio consiglierei / raccomanderei fortemente (e insisto, nel mio team) su:

if ( blah )
{
    ...
}
else
{
    while ( !bloop() )
    {
        bar();
    }
}

Certo, mi aspetterei anche di vedere anche i commenti adatti.

-- Modificare --

Recentemente Apple ha sofferto di una vulnerabilità SSL, causata da una scarsa correzione della manutenzione, che ha aggiunto una seconda linea a una singola linea non rinforzata. Quindi mettiamo a letto l'idea che le linee singole non incrociate siano OK?


2
Concordo sul fatto che sia l'unico termine corretto per seguire un altro. Se ci fosse un else while, probabilmente non mi accorgerei nemmeno che c'era un ciclo in una rapida scrematura del codice, specialmente se la condizione che stavo cercando era soddisfatta dall'if.
Drake Clarris,

3
È divertente. Tutti dicono che è più facile leggere se tutto è tra parentesi graffe. Trovo che sia vero il contrario. Se è solo una frase, tenerla tra parentesi graffe rende più facile la lettura. Meno confusione. Può essere solo perché l'ho sempre fatto in quel modo.
Jeff Davis,

2
@JeffDavis è una buona cattura. "Più facile da leggere" è un tipico invito all'inutile guerra santa. Io per primo preferisco le parentesi graffe, ma non a causa dell'irrilevante spazzatura "easiertoread" (per me è esattamente il contrario) ma perché è più difficile interrompere un'ulteriore manutenzione del codice. Tra l'altro OP farro meglio nella loro domanda: è else whilesenza intervenire bretelle considerato "sicuro" ?
moscerino del

@JeffDavis - So che questo thread ha due anni, ma Apple ha recentemente scoperto perché non usare le parentesi graffe non è una buona idea andrewbanks.com/…
Andrew

@Andrew A proposito, il linguaggio Swift di Apple ora proibisce esplicitamente il controllo del flusso su una riga. Quel bug potrebbe essere uno dei motivi per farlo.
Sulthan,

6

Mi è sempre stato insegnato a tenere tutto tra parentesi graffe, rientrato e commentato. Credo che sia molto più facile leggere e individuare errori. Personalmente ritengo che la modularità sia la chiave, quindi scrivo sempre il codice in questo modo:

    if(blah)
    {
     ....
    }
    else
    {
       while(!bloop()
       {
        bar;
       }
    }

6

Vorrei estrarre il metodo e farlo

if ( blah )
{
    ...
}
else
{
   newMethod();
}

Vedi l'approccio "Estrai metodo" spiegato nel sito del Catalogo Refactoring :

Hai un frammento di codice che può essere raggruppato insieme.

Trasforma il frammento in un metodo il cui nome spiega lo scopo del metodo.

void printOwing() {
    printBanner();

    //print details
    System.out.println ("name:    " + _name);
    System.out.println ("amount    " + getOutstanding());
}

                                                                                                         http://www.refactoring.com/catalog/arrow.gif

void printOwing() {
    printBanner();
    printDetails(getOutstanding());
}

void printDetails (double outstanding) {
    System.out.println ("name:    " + _name);
    System.out.println ("amount    " + outstanding);
}

Dipende ... se, ad esempio, il ciclo while utilizzava i dati a livello di funzione, ora devi aggiungere più dati al modulo (o alla classe, se usi C ++). E se solo un piccolo frammento di codice, ti piacciono i metodi banali. Ma a volte, a seconda delle circostanze, sono d'accordo.
Andrew,

1
I compilatori +1 Smart C ++ possono incorporare una funzione. In ambiente .Net le piccole funzioni sono migliori grazie a JIT.
Giobbe

4

Lo considererei una cattiva abitudine di programmazione. A volte funziona perfettamente e non avrai problemi a compilare ed eseguire il codice. Altre volte può causare gravi bug e finirai per passare ore a risolvere quel bug.

Si consiglia sempre di modulare il codice. Se devi inserire un ciclo while nella parte altrimenti inseriscilo in un blocco in modo che gli altri, quando lavori sul tuo codice, possano facilmente comprendere la logica.

if ( blah )
{
    ...
}
else
{
    while ( !bloop() )
    {
        bar();
    }
}

È buona norma inserire il codice in blocchi. Rende anche più semplice e facile la comprensione e il debug.


4

Potrebbe andare bene se rimane così, anche se personalmente non mi piace e la mia preferenza è quella di usare le parentesi graffe anche per i blocchi di codice if / else più semplici. È solo più ordinato per me.

Tuttavia, dove questo diventa disordinato è quando hai annidato se / else ne esegue alcuni con parentesi graffe, altre senza. Un ciclo While in mezzo a tutti quegli spaghetti! Ho lavorato così tanto con il codice ed è un incubo il debug e la comprensione. Questo segue dal primo punto che va bene quando rimane semplice e tu ne sei contento, ma poi arrivano altri programmatori che aggiungono cose, probabilmente un if nel ciclo while. Se in primo luogo è scritto pulito, allora ci sono meno possibilità che ciò accada.

Il punto è chiarire le cose in modo che altri programmatori possano vedere a colpo d'occhio ciò che è giusto e ciò che è sbagliato. Scrivi il codice in modo tale che il modello appaia corretto e non si barchi.

Il rovescio della medaglia di questo è che forse potrei vedere alcune persone affermare che in alcuni casi questo legge bene. Se ho la risorsa di cui ho bisogno, eseguo questa elaborazione altrimenti sto aspettando qualcosa. Anche allora per me non c'è ancora alcuna differenza nel nidificare il ciclo while all'interno del blocco else.


3

Bene, nonostante tutti discutano sull'uso delle parentesi graffe e sembrano amarle, in realtà preferisco il contrario. Uso le parentesi graffe solo quando devo perché lo trovo più leggibile e conciso senza.

if (...)
   foo();
else while(...)
   bar();

... Trovo davvero questo " else while(...)" leggibile in modo notevole! Sembra persino un inglese semplice! Ma immagino che la gente lo troverà strano perché è inusuale a dir poco.

Alla fine, tendiamo tutti a renderlo a prova di idiota con le parentesi graffe però ... perché, beh, lo sai.


3
sarà particolarmente leggibile dopo che alcuni innocenti manutentori si sono trasformati else while(...) bar();in qualcosa di simile else while(...) foobar(); bar();:)
moscerino del

3
bene, direi che è un manutentore innocente piuttosto stupido e pericoloso . Conosco il principio di attenuarlo per evitare stupidi errori ... ma andare così lontano è comunque abbastanza triste. Ma sapevo che avrei avuto tali commenti e voti negativi. Nessun problema.
Dagnelies,

2
"Codice sempre come se la persona che manterrà il tuo codice sia uno psicopatico violento che sa dove vivi." ( Alan Braggins )
moscerino del

1
Bene, tutto si riduce a quello che presumi sia il livello più stupido di qualcuno che lavora al tuo codice. Sostengo che se il tuo "manutentore" si confonde con queste quattro righe di codice ... allora hai un grosso problema a portata di mano. E se è uno psicopatico violento, ne hai due. ;)
dagnelies il

1
if - beh, il link a cui rimando sopra ha ampliato la versione di questa citazione: Programmatore 1: "C'è una bella citazione qui -" Codifica sempre come se la persona che manterrà il tuo codice è una psicopatica violenta che sa dove vivi "" . Programmatore 2: (Guarda il manutentore) 'Cosa intendi con "come se"? "
moscerino del

2

Metto sempre le parentesi graffe, solo perché potresti aggiungere un'altra riga quando sei di fretta, rientrare, dimenticare le parentesi graffe e grattarti la testa cosa sta succedendo. Tengo la staffa di apertura sulla stessa linea, ma non importa. In entrambi i casi è meglio averli.

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

Il posizionamento delle parentesi graffe probabilmente innesca più argomenti di qualsiasi altra cosa al di là (o forse anche alla religione)!
Andrew,

Concordato. Modificherò la mia risposta per enfatizzare la loro esistenza, non la posizione.
Tsvetomir Dimitrov,

2

Cosa c'è di così sbagliato nelle parentesi graffe che così tante persone stanno cercando di evitare di scriverle?

Quale problema else whilerisolve esattamente ?

Le parentesi graffe sono economiche e buone e rendono evidente e chiara l'intenzione del codice al contrario di intelligente e arguta.

Citando la filosofia Unix:

Regola di chiarezza: la chiarezza è meglio dell'intelligenza.

Poiché la manutenzione è così importante e così costosa, scrivi i programmi come se la comunicazione più importante che fanno non fosse al computer che li esegue ma agli esseri umani che leggeranno e manterranno il codice sorgente in futuro (incluso te stesso).


1

Non c'è niente di sbagliato in

if (blah)
    foo();
else
    bar();

proprio come non c'è niente di sbagliato in

if (blah) foo(); else bar();

nelle giuste circostanze (le tue circostanze possono variare, ma quello stile particolare è meglio usato quando hai un sacco di codice ripetitivo - quindi la vista di ogni riga è più importante del rientro stilistico)

Ma se scegli un modo, seguilo: la coerenza è il re. Quindi il tuo secondo esempio è pessimo, poiché l'espressione if aveva parentesi per la sua istruzione, l'istruzione while dovrebbe trovarsi tra parentesi per la clausola else, non al di fuori di essa.


inoltre, ho visto questo codice prima:

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

ed è stato scritto dallo standard di codifica nazista stesso (che ha insistito sulle parentesi per tutto).


1

Gli IDE moderni possono essere facilmente configurati per riformattare (inclusa la rimozione o l'aggiunta di parentesi graffe non necessarie) e / o reindirizzare il codice al salvataggio di un file. Quindi il tuo esempio sembrerebbe automaticamente per esempio

if (blah) {
  blub();
} else
  while (!bloop()) {
    bar();
  }

Il rientro rende sempre facilmente visibile l'annidamento, anche senza parentesi graffe non necessarie. Quindi, se riesci ad applicare tali impostazioni IDE, non vedo alcun rischio.

Personalmente, trovo il codice che omette le parentesi graffe e le interruzioni di riga molto più leggibile poiché evita il disordine:

if (blah) blub();
else while (!bloop()) bar();

Ma, naturalmente, molti sviluppatori sono molto felici di discutere di queste cose per sempre e un giorno.

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.