if ('constante' == $ variable) vs si ($ variable == 'constante')

49

Dernièrement, j'ai beaucoup travaillé en PHP et plus particulièrement dans le cadre WordPress. Je remarque beaucoup de code sous la forme de:

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

Où je m'attendais à voir:

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

Est-ce une convention trouvée dans certaines langues / cadres? Y a-t-il une raison pour laquelle la première approche est préférable à la seconde (du point de vue du traitement, de l'analyse ou même du point de vue humain?)

Ou est-ce simplement une question de goût? J'ai toujours pensé qu'il était préférable, lors de l'exécution d'un test, que l'élément variable testé par rapport à une constante soit à gauche. Cela semble mieux correspondre à la façon dont nous poserions la question en langage naturel: "si le gâteau est au chocolat" plutôt que "si le chocolat est le gâteau".

Tom Auger
la source
1
Je n'écris jamais de code comme ça, mais être honnête "si le chocolat est la saveur du gâteau" est naturel. Le langage naturel est plus flexible.
Rick Sladkey
4
@Rick Cela peut sembler naturel en langage, mais vous ne pouvez pas nier que lorsque vous voyez un code comme celui-là, vous devez vous arrêter le premier (peut-être seulement une seconde) pour penser à ce que c'est d'essayer de faire.
Edgar Gonzalez
4
@ Edgar Gonzalez: D'accord, je suis fermement contre le code.
Rick Sladkey
3
Le chapitre 19 de Code Complete 2nd Edition (sous la section "Expressions booléennes: problèmes courants avec les expressions booléennes") recommande en fait cette pratique pour la raison exacte indiquée dans de nombreuses réponses ici: pour empêcher l'attribution dans des langages dérivés de C lorsque la comparaison était voulue .
CraigTP
4
Je les ai souvent vues qualifiées de "conditions Yoda"
Brian

Réponses:

84

La principale raison de faire cela (ce qu'on appelle "Yoda conditionnel") est pour éviter les accidents par lesquels vous utilisez accidentellement un opérateur d'affectation ( =) au lieu de l'opérateur de comparaison d'égalité ( ==).

C'est-à-dire si vous avez commis l'erreur de faire:

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

La déclaration sera évaluée à true(ou, dans le cas de certaines langues, comme PHP, une valeur de vérité) et vous aurez un bogue difficile à trouver.

Mais si vous avez fait:

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

Vous recevrez une erreur fatale, car vous ne pouvez pas affecter $fooà un entier.

Mais comme vous l'avez fait remarquer, inverser l'ordre rend généralement les choses moins lisibles. Ainsi, de nombreuses normes de codage (mais pas toutes, y compris WordPress ) suggèrent ou exigent $foo == 1malgré les avantages de la recherche de bogues 1 == $foo.

En règle générale, mon conseil est de respecter la norme de codage établie, le cas échéant: pour WordPress, cela signifie que vous devez utiliser le conditionnel de Yoda.

Lorsqu'il n'y en a pas et qu'il est impossible d'en établir un par consensus avec vos pairs, c'est le choix du revendeur.

Attila
la source
2
Je me souviens lors de la conception d’une langue (il ya très longtemps) que nous avons spécifiquement fait de :=l’opérateur d’affectation (avec ==pour test d’égalité) afin d’éviter ce genre de problème.
Donal Fellows
7
J'ai écrit beaucoup, beaucoup de lignes de code, et je n'ai jamais tapé accidentellement à la =place de ==. La différence est tellement accentuée partout que je ne les ai jamais confondus. D'autre part, j'ai lu beaucoup de codes qui sont source de confusion ou qui sont difficiles à comprendre. En tant que tel, je mettrais les priorités sur la lisibilité :). Peu importe, bonne réponse.
Crazy2be
5
Encore une autre bonne raison d’utiliser -Wall -Werrorou l’équivalent de votre compilateur / interprète. Il existe très peu de situations dans lesquelles une affectation dans une condition est correcte, encore moins lisible. Beaucoup de langues ne le permettent même pas.
Karl Bielefeldt
7
Pédant: Tout if($foo = 1)Equivaut à truedans certaines langues, en PHP , il évalue à 1 au lieu; if($foo = 20)évalue à 20; if($foo = 0)évalue à 0, ce qui contrairement aux autres est faux. Cela peut ajouter toute une couche de complexité au bogue.
Charles
2
En fait, les normes de codage WordPress NE font appel à Yoda Conditionals: codex.wordpress.org/WordPress_Coding_Standards#Yoda_Conditions
Tom Auger le
13

C'est un mécanisme de codage défensif destiné à prévenir une utilisation accidentelle de l'opérateur d'assignation.

Considérons une mauvaise utilisation / erreur de l'opérateur d'affectation à la place de l'opérateur d'égalité

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

La condition ci-dessus deviendrait toujours vraie, mais ce n'est probablement pas ce que le programmeur d'origine avait en tête. Considérez, à sa place, cette

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

Ici, PHP (et la plupart des autres langues) refuserait de s’exécuter, car il est impossible d’attribuer quoi que ce soit à la valeur fixe de 1. En codant toutes les instructions conditionnelles de cette manière, vous vous assurez automatiquement de l'absence d'utilisation accidentelle d'un opérateur d'affectation dans une condition.

Alan Storm
la source
9

J'aime utiliser cette convention en Java pour supprimer la possibilité d'une exception de pointeur nul. Donc, quelque chose comme ça ne vous causera aucun problème ni besoin de code supplémentaire:

String foo = null;

if ("bar".equals(foo))
{
    //Do something
}
Ben Newman
la source
3
J'aime ça, mais je déteste le langage général.
Thomas Eding
3
Si une valeur null n’est pas valide à ce point dans le code, vous devriez l’avoir déjà vérifiée de toute façon ou conçu votre code de telle sorte qu’une valeur nulle serait impossible.
Ed S.
6
cela semble être un moyen facile de masquer les problèmes. Les poussières ne sont pas nettoyées en les haussant à l'intérieur du tapis.
Lie Ryan
0

En pratique, de nombreux compilateurs vous avertiront si vous écrivez "if (x = 1)" au lieu de "if (x == 1)", car il s'agit très probablement d'une erreur.

Avec Clang, vous pouvez éviter l'avertissement en disant efficacement au compilateur "Je le pense vraiment, et je sais ce que je fais", et cela se fait en écrivant "if ((x = 1))". Notez les parenthèses supplémentaires. Cela fonctionne aussi dans d'autres situations. si (faux) déclaration; peut vous avertir que la déclaration n'est jamais exécutée; if ((false)) statement; ne donne pas cet avertissement.

gnasher729
la source
J'aime beaucoup cela! J'évite ce qui suit, langage complètement légitime en PHP car je reçois toujours des avertissements dans mon IDE:if ($array = getSomething()){ // ..so something with $array }
Tom Auger