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

49

Últimamente, he estado trabajando mucho en PHP y específicamente en el marco de WordPress. Noto mucho código en forma de:

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

Donde hubiera esperado ver:

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

¿Es esta una convención que se encuentra en ciertos lenguajes / marcos? ¿Hay alguna razón por la cual el enfoque anterior es preferible al segundo (desde una perspectiva de procesamiento, una perspectiva de análisis o incluso una perspectiva humana)?

¿O es simplemente una cuestión de gustos? Siempre he pensado mejor al realizar una prueba, que el elemento variable que se está probando contra alguna constante está a la izquierda. Parece encajar mejor con la forma en que haríamos la pregunta en lenguaje natural: "si el pastel es chocolate" en lugar de "si el chocolate es el pastel".

Tom Auger
fuente
1
Nunca escribo un código así, pero para ser justos "si el chocolate es el sabor del pastel" suena natural. El lenguaje natural es más flexible.
Rick Sladkey
44
@Rick Puede sonar natural en el lenguaje, pero no puede negar que cuando ve un código así, debe detenerse primero (tal vez solo por un segundo) para pensar qué es lo que está tratando de hacer.
Edgar González
44
@Edgar González: De acuerdo, estoy firmemente en contra en el código.
Rick Sladkey
3
El Capítulo 19 de Code Complete 2nd Edition (en la sección "Expresiones booleanas: problemas comunes con las expresiones booleanas") en realidad recomienda esta práctica por la razón exacta que se indica en muchas de las respuestas aquí: para evitar la asignación en lenguajes derivados de C cuando se hizo la comparación .
CraigTP
44
A menudo los he visto referidos como "Condiciones de Yoda"
Brian

Respuestas:

84

La razón principal para hacer esto (lo que se llama "Yoda condicional") es para evitar accidentes mediante los cuales accidentalmente usa un operador de asignación ( =) en lugar del operador de comparación igual ( ==).

Es decir, si cometió el error de hacer:

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

La declaración evaluará true(o, en el caso de algunos lenguajes, como PHP, un valor verdadero) y tendrá un error difícil de encontrar.

Pero si lo hiciste:

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

Recibirá un error fatal porque no puede asignar $fooa un número entero.

Pero como usted señaló, invertir el orden generalmente hace que las cosas sean menos legibles. Por lo tanto, muchos estándares de codificación (pero no todos, incluido WordPress ) sugieren o requieren a $foo == 1pesar de los beneficios de la búsqueda de errores 1 == $foo.

En general, mi consejo es seguir cualquier estándar de codificación establecido que exista, si hay uno: para WordPress, eso significa usar los condicionales de Yoda.

Cuando no lo hay, y es imposible establecer uno a través del consenso con sus pares, es decisión del distribuidor.

Atila
fuente
2
Recuerdo cuando diseñé un lenguaje (hace mucho tiempo) que específicamente hicimos :=ser el operador de asignación (con ==prueba de igualdad) para evitar este tipo de problemas.
Donal Fellows
77
He escrito muchas, muchas líneas de código, y nunca he escrito accidentalmente en =lugar de ==. La diferencia está tan acentuada en todas partes que nunca los confundí. Por otro lado, he leído muchos códigos que son confusos o difíciles de entender. Como tal, pondría las prioridades en la legibilidad :). De todos modos, buena respuesta.
crazy2be
55
Otra buena razón para usar -Wall -Werroro el equivalente de su compilador / intérprete. Hay muy pocas situaciones en las que una asignación dentro de una condición sea correcta, y mucho menos más legible. Muchos idiomas ni siquiera lo permiten.
Karl Bielefeldt
77
Pedantic: mientras se if($foo = 1)evalúa trueen algunos idiomas, en PHP se evalúa a 1 en su lugar; if($foo = 20)evalúa a 20; if($foo = 0)evalúa a 0, que a diferencia de los demás es falso. Esto puede agregar una 'capa de complejidad completa al error.
Charles
2
En realidad, los estándares de codificación de WordPress sí requieren condicionales de Yoda: codex.wordpress.org/WordPress_Coding_Standards#Yoda_Conditions
Tom Auger
13

Es un mecanismo de codificación defensivo destinado a evitar un uso accidental del operador de asignación.

Considere un mal uso / error del operador de asignación en lugar del operador de igualdad

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

El condicional anterior siempre devolvería verdadero, pero eso probablemente no sea lo que el programador original tenía en mente. Considere, en su lugar, esto

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

Aquí, PHP (y la mayoría de los otros lenguajes) se negarían a ejecutarse, ya que es imposible asignar algo al valor fijo de 1. Al codificar todas las declaraciones condicionales de esta manera, se asegura automáticamente de que no se use accidentalmente un operador de asignación en un condicional.

Alan Storm
fuente
9

Me gusta usar esa convención en Java para eliminar la posibilidad de una excepción de puntero nulo. Entonces, algo como esto no le causará ningún problema ni necesitará ningún código adicional:

String foo = null;

if ("bar".equals(foo))
{
    //Do something
}
Ben Newman
fuente
3
Me gusta esto, pero odio el idioma general.
Thomas Eding,
3
Si un valor nulo no es válido para ese punto en el código, ya debería haberlo verificado de todos modos o haber diseñado su código de tal manera que un valor nulo sería imposible.
Ed S.
66
Esto parece una manera fácil de enmascarar problemas. Los polvos no se limpian encogiéndolos de hombros dentro de la alfombra.
Lie Ryan
0

En la práctica, muchos compiladores le darán una advertencia si escribe "if (x = 1)" en lugar de "if (x == 1)" porque es muy probable que sea un error.

Con Clang, puede evitar la advertencia diciéndole efectivamente al compilador "Lo digo en serio y sé lo que estoy haciendo", y esto se hace escribiendo "if ((x = 1))". Tenga en cuenta los paréntesis adicionales. Eso también funciona en otras situaciones. declaración if (falsa); puede advertirle que la declaración nunca se ejecuta; declaración if ((falso)); No da esa advertencia.

gnasher729
fuente
¡Me gusta mucho eso! Evito lo siguiente, un lenguaje completamente legítimo en PHP porque siempre recibo advertencias en mi IDE:if ($array = getSomething()){ // ..so something with $array }
Tom Auger