Il modo migliore per formattare l'istruzione if con più condizioni


90

Se vuoi che del codice venga eseguito in base a due o più condizioni, qual è il modo migliore per formattare tale istruzione if?

primo esempio: -

if(ConditionOne && ConditionTwo && ConditionThree)
{
   Code to execute
}

Secondo esempio: -

if(ConditionOne)
{
   if(ConditionTwo )
   {
     if(ConditionThree)
     {
       Code to execute
     }
   }
}

che è più facile da capire e leggere tenendo presente che ogni condizione può essere un nome di funzione lungo o qualcosa del genere.


Peccato che nessuno in questa pagina menzioni la sottostringa "veloce" o "prestazioni". Questo è quello che sono venuto qui per imparare.
Presidente Dreamspace

Risposte:


133

Preferisco l'opzione A

bool a, b, c;

if( a && b && c )
{
   //This is neat & readable
}

Se hai variabili / condizioni di metodo particolarmente lunghe, puoi semplicemente interromperle

if( VeryLongConditionMethod(a) &&
    VeryLongConditionMethod(b) &&
    VeryLongConditionMethod(c))
{
   //This is still readable
}

Se sono ancora più complicati, prenderei in considerazione l'idea di eseguire i metodi condition separatamente al di fuori dell'istruzione if

bool aa = FirstVeryLongConditionMethod(a) && SecondVeryLongConditionMethod(a);
bool bb = FirstVeryLongConditionMethod(b) && SecondVeryLongConditionMethod(b);
bool cc = FirstVeryLongConditionMethod(c) && SecondVeryLongConditionMethod(c);

if( aa && bb && cc)
{
   //This is again neat & readable
   //although you probably need to sanity check your method names ;)
}

IMHO L'unico motivo per l'opzione "B" sarebbe se hai elsefunzioni separate da eseguire per ciascuna condizione.

per esempio

if( a )
{
    if( b )
    {
    }
    else
    {
        //Do Something Else B
    }
}
else
{
   //Do Something Else A
}

Mi piace. Anche se non sono un grande fan dell'idea del metodo, a meno che i metodi non esistano già e restituiscano un valore booleano.
Thomas Owens,

2
Non stai valutando tutto senza una ragione nel secondo esempio?
Odys

Vorrei utilizzare "&&" prima della condizione. È difficile avere condizioni con la stessa lunghezza di carattere dell'esempio.
AdrianN

29

Altre risposte spiegano perché la prima opzione è normalmente la migliore. Ma se hai più condizioni, considera la creazione di una funzione (o proprietà) separata facendo i controlli delle condizioni nell'opzione 1. Ciò rende il codice molto più facile da leggere, almeno quando usi buoni nomi di metodo.

if(MyChecksAreOk()) { Code to execute }

...

private bool MyChecksAreOk()
{ 
    return ConditionOne && ConditionTwo && ConditionThree;
}

Se le condizioni si basano solo su variabili di ambito locale, è possibile rendere statica la nuova funzione e passare tutto ciò di cui si ha bisogno. Se c'è un mix, passa la roba locale.


2
Ho trovato che questa è la condizione più efficace e più facile da aggiungere in seguito
pbojinov

+1 all'inizio ho alzato un sopracciglio ma questa è davvero la migliore risposta imho. avere quel booleano isOkToDoWhatevercome proprietà ha molto senso.
grinch

1
Ma questo sposta la stessa complessa condizione altrove dove deve anche essere leggibile, quindi siamo tornati al punto di partenza con questo. Non si tratta solo della ifleggibilità delle affermazioni, ma piuttosto della leggibilità delle condizioni.
Robert Koritnik

@RobertKoritnik Capisco cosa stai dicendo, ma non credo che siamo tornati al punto di partenza perché abbiamo ridotto la complessità che il lettore deve considerare in una volta sola. Può guardare le condizioni, OPPURE può guardare il codice usando le condizioni in cui le condizioni hanno un nome (si spera) carino. Almeno spesso lo trovo più facile da capire, ma a volte è bello avere tutti i dettagli in un unico posto. Come sempre, dipende.
Torbjørn

Ottimo punto utilizzando buoni nomi di metodo e refactoring della logica.
JB Lovell,

10

Il primo esempio è più "facile da leggere".

In realtà, secondo me dovresti usare il secondo solo ogni volta che devi aggiungere un po 'di "logica else", ma per un semplice condizionale, usa il primo sapore. Se sei preoccupato per la durata della condizione puoi sempre utilizzare la sintassi successiva:

if(ConditionOneThatIsTooLongAndProbablyWillUseAlmostOneLine
                 && ConditionTwoThatIsLongAsWell
                 && ConditionThreeThatAlsoIsLong) { 
     //Code to execute 
}

In bocca al lupo!


10
if (   ( single conditional expression A )
    && ( single conditional expression B )
    && ( single conditional expression C )
   )
{
   opAllABC();
}
else
{
   opNoneABC();
}

Formattazione di più espressioni condizionali in un'istruzione if-else in questo modo:

  1. consente una migliore leggibilità:
    a. tutte le operazioni logiche binarie {&&, ||} nell'espressione mostrata per prima
    b. entrambi gli operandi condizionali di ciascuna operazione binaria sono ovvi perché si allineano verticalmente
    c. le operazioni di espressioni logiche annidate sono rese ovvie usando l'indentazione, proprio come le istruzioni di annidamento all'interno della clausola
  2. richiede parentesi esplicite (non fare affidamento sulle regole di precedenza degli operatori)
    a. questo evita un comune errore di analisi statica
  3. consente un debug più semplice
    a. disabilitare singoli test condizionali singoli con un semplice //
    b. impostare un punto di interruzione appena prima o dopo ogni singolo test
    ceg ...
// disable any single conditional test with just a pre-pended '//'
// set a break point before any individual test
// syntax '(1 &&' and '(0 ||' usually never creates any real code
if (   1
    && ( single conditional expression A )
    && ( single conditional expression B )
    && (   0
        || ( single conditional expression C )
        || ( single conditional expression D )
       )
   )
{
   ... ;
}

else
{
   ... ;
}

Questo è il mio metodo. L'unico problema che ho è che devo ancora trovare un abbellitore di codice che offra questo come opzione
Speed8ump

9

La domanda è stata posta e finora è stata data una risposta come se la decisione dovesse essere presa esclusivamente su basi "sintattiche".

Direi che la risposta corretta di come si dispone un numero di condizioni all'interno di un se, dovrebbe dipendere anche dalla "semantica". Quindi le condizioni dovrebbero essere suddivise e raggruppate in base a ciò che le cose vanno insieme "concettualmente".

Se due test sono davvero due facce della stessa medaglia es. if (x> 0) && (x <= 100) allora mettili insieme sulla stessa riga. Se un'altra condizione è concettualmente molto più distante ad es. user.hasPermission (Admin ()) quindi inseriscilo sulla sua riga

Per esempio.

if user.hasPermission(Admin()) {
   if (x >= 0) && (x < 100) {
      // do something
   }
}


3

Il primo è più semplice, perché, se lo leggi da sinistra a destra ottieni: "Se qualcosa E qualcos'altro E qualcos'altro ALLORA", che è una frase di facile comprensione. Il secondo esempio dice "Se qualcosa ALLORA se qualcosa altro ALLORA se qualcos'altro ALLORA", che è goffo.

Inoltre, considera se volessi usare alcuni OR nella tua clausola - come lo faresti nel secondo stile?


0

In Perl puoi fare questo:

{
  ( VeryLongCondition_1 ) or last;
  ( VeryLongCondition_2 ) or last;
  ( VeryLongCondition_3 ) or last;
  ( VeryLongCondition_4 ) or last;
  ( VeryLongCondition_5 ) or last;
  ( VeryLongCondition_6 ) or last;

  # Guarded code goes here
}

Se una qualsiasi delle condizioni fallisce, continuerà semplicemente dopo il blocco. Se stai definendo delle variabili che vuoi mantenere dopo il blocco, dovrai definirle prima del blocco.


1
Sembra Perlish - nel "fa COSA?" senso;) Ma è effettivamente leggibile, una volta che ci si abitua.
Piskvor ha lasciato l'edificio il

-2

Sto affrontando questo dilemma da molto tempo e ancora non riesco a trovare una soluzione adeguata. Secondo me, l'unico buon modo è provare prima a sbarazzarsi delle condizioni prima in modo da non confrontarne improvvisamente 5.

Se non c'è alternativa, come altri hanno suggerito, suddividila in separazioni e abbrevia i nomi o raggruppali e, ad esempio, se tutto deve essere vero, usa qualcosa come "se nessun falso nell'array di x allora esegui".

Se tutto fallisce, @Eoin Campbell ha dato delle buone idee.


Questo non aggiunge nulla di nuovo alle risposte già esistenti.
jerney

-4

Quando la condizione è davvero complessa, utilizzo il seguente stile (esempio di vita reale in PHP):

if( $format_bool &&
    (
        ( isset( $column_info['native_type'] )
            && stripos( $column_info['native_type'], 'bool' ) !== false
        )
        || ( isset( $column_info['driver:decl_type'] )
            && stripos( $column_info['driver:decl_type'], 'bool' ) !== false
        )
        || ( isset( $column_info['pdo_type'] )
            && $column_info['pdo_type'] == PDO::PARAM_BOOL
        )
    )
)

Credo che sia più bello e leggibile che annidare più livelli di if(). E in alcuni casi come questo non puoi semplicemente rompere la condizione complessa in pezzi perché altrimenti dovresti ripetere le stesse affermazioni in if() {...}blocco molte volte.

Credo anche che aggiungere un po 'di "aria" al codice sia sempre una buona idea. Migliora notevolmente la leggibilità.

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.