if ('costante' == $ variabile) vs. if ($ variabile == 'costante')


49

Ultimamente, ho lavorato molto in PHP e nello specifico all'interno del framework WordPress. Sto notando molto codice sotto forma di:

if ( 1 == $options['postlink'] )

Dove mi sarei aspettato di vedere:

if ( $options['postlink'] == 1 )

Si tratta di una convenzione trovata in alcune lingue / strutture? C'è qualche ragione per cui il primo approccio è preferibile al secondo (dal punto di vista dell'elaborazione, o dal punto di vista dell'analisi o anche dal punto di vista umano?)

O è semplicemente una questione di gusti? Ho sempre pensato meglio quando eseguivo un test, che l'elemento variabile da testare con una costante è sulla sinistra. Sembra mappare meglio il modo in cui porremmo la domanda in linguaggio naturale: "se la torta è cioccolato" piuttosto che "se il cioccolato è la torta".


1
Non scrivo mai un codice del genere, ma per essere onesti "se il cioccolato è il sapore della torta" sembra naturale. Il linguaggio naturale è più flessibile.
Rick Sladkey,

4
@Rick Potrebbe sembrare naturale nel linguaggio, ma non puoi negare che quando vedi un codice del genere, devi prima fermarti (forse solo per un secondo) a pensare cosa sta cercando di fare.
Edgar Gonzalez,

4
@Edgar Gonzalez: D'accordo, sono fermamente contrario al codice.
Rick Sladkey,

3
Il capitolo 19 di Code Complete 2nd Edition (sotto la sezione "Espressioni booleane: problemi comuni con espressioni booleane") in realtà raccomanda questa pratica per il motivo esatto indicato in molte delle risposte qui: per impedire l'assegnazione in linguaggi derivati ​​da C quando si intendeva il confronto .
CraigTP

4
Ho spesso visto queste chiamate "Condizioni Yoda"
Brian

Risposte:


84

Il motivo principale per farlo (il cosiddetto "Yoda condizionale") è prevenire incidenti in cui si utilizza accidentalmente un operatore di assegnazione ( =) anziché un operatore di confronto uguale ( ==).

Cioè, se hai fatto l'errore di fare:

$foo = 5;
if ($foo = 1) {
  // Stuff
}

L'affermazione valuterà true(o, nel caso di alcune lingue - come PHP - un valore veritiero) e avrai un bug difficile da trovare.

Ma se lo facessi:

$foo = 5;
if (1 = $foo) {
  // Stuff
}

Riceverai un errore irreversibile perché non puoi assegnarlo $fooa un numero intero.

Ma come hai sottolineato, invertire l'ordine generalmente rende le cose meno leggibili. Quindi, molti standard di codifica (ma non tutti, incluso WordPress ) suggeriscono o richiedono $foo == 1nonostante i vantaggi della ricerca di bug 1 == $foo.

In generale, il mio consiglio è di seguire qualunque standard di codifica stabilito, se ce n'è uno: per WordPress, ciò significa usare i condizionali Yoda.

Quando non c'è, ed è impossibile stabilirne uno attraverso il consenso con i vostri colleghi, è la scelta del rivenditore.


2
Ricordo quando progettammo una lingua (molto tempo fa) che specificamente facemmo :=essere l'operatore di assegnazione (con ==per il test di uguaglianza) al fine di evitare questo tipo di problemi.
Donal Fellows

7
Ho scritto molte, molte righe di codice e non ho mai digitato per errore al =posto di ==. La differenza è così accentuata ovunque che non li ho mai confusi. D'altra parte, ho letto molti pezzi di codice che sono confusi o altrimenti difficili da capire. Come tale, vorrei mettere le priorità sulla leggibilità :). Indipendentemente da ciò, buona risposta.
crazy2be

5
Ancora un altro buon motivo per usare -Wall -Werroro l'equivalente del compilatore / interprete. Esistono pochissime situazioni in cui un'assegnazione all'interno di una condizione è corretta, figuriamoci più leggibile. Molte lingue non lo consentono nemmeno.
Karl Bielefeldt,

7
Pedante: mentre if($foo = 1)valuta truein alcune lingue, in PHP invece valuta 1; if($foo = 20)valuta 20; if($foo = 0)restituisce 0, che a differenza degli altri è falso. Questo può aggiungere un intero 'altro livello di complessità al bug.
Charles,

2
In realtà, gli standard di codifica di WordPress richiedono Yoda Conditionals: codex.wordpress.org/WordPress_Coding_Standards#Yoda_Conditions
Tom Auger,

13

È un meccanismo di codifica difensiva pensato per prevenire un uso accidentale dell'operatore di assegnazione.

Considerare un uso improprio / errore dell'operatore di assegnazione al posto dell'operatore di uguaglianza

if ( $options['postlink'] = 1  )

Il suddetto condizionale tornerà sempre vero, ma probabilmente non è quello che il programmatore originale aveva in mente. Considera, al suo posto, questo

if( 1 = $options['postlink'])

Qui, PHP (e la maggior parte delle altre lingue) si rifiuta di funzionare, poiché è impossibile assegnare qualcosa al valore fisso di 1. Codificando tutte le istruzioni condizionali in questo modo, si garantisce automaticamente nessun utilizzo accidentale di un operatore di assegnazione in una condizione.


9

Mi piace usare quella convenzione in Java per rimuovere la possibilità di un'eccezione puntatore null. Quindi qualcosa del genere non ti causerà problemi o non avrà bisogno di alcun codice aggiuntivo:

String foo = null;

if ("bar".equals(foo))
{
    //Do something
}

3
Mi piace, ma odio il linguaggio generale.
Thomas Eding,

3
Se un valore null non è valido da quel punto nel codice, dovresti averlo già verificato o progettato il tuo codice in modo tale che un valore null sia impossibile.
Ed S.

6
questo sembra un modo semplice per mascherare i problemi. Le polveri non vengono pulite scrollandole all'interno del tappeto.
Lie Ryan,

0

In pratica, molti compilatori ti daranno un avviso se scrivi "if (x = 1)" invece di "if (x == 1)" perché è molto probabilmente un errore.

Con Clang, puoi evitare l'avvertimento dicendo efficacemente al compilatore "Intendo, e so cosa sto facendo", e questo viene fatto scrivendo "if ((x = 1))". Nota le parentesi extra. Funziona anche in altre situazioni. if (false) statement; potrebbe avvisarti che l'istruzione non è mai stata eseguita; if ((false)) statement; non dà questo avvertimento.


Mi piace molto! Evito il seguente linguaggio completamente legittimo in PHP perché ricevo sempre avvisi nel mio IDE:if ($array = getSomething()){ // ..so something with $array }
Tom Auger
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.