Polémica / discusión: ¿Debemos usar "null == $var" ó "$var == null"?

Algunos de mis lectores y colegas se quejan que gracias a los cursos el blog quedó un poco vacío de contenidos, así que voy a compartir una discusión interesante que se dió en el foro de uno de los grupos del curso "Introducción a Zend Framework" ;-)

Se presentó un ejemplo donde se usaba un if con "null === $var", en vez del tradicional "$var === null" (el orden invertido).

Aquí mi explicación:

Imagen de Enrique Place
Re: Pagina 13 Correccion
de Enrique Place - viernes, 27 de marzo de 2009, 19:57


Mmmm ... en lo personal no soy partidario de usar null === dato, prefiero el estándar dato === null, ya que es más claro y natural su lectura:

Leyendo de izquierda a derecha, "si el dato es exactamente igual a null" en oposición a "si null es exactamente igual al dato" guiño

Aunque conozco la seudo-ventaja de evitar un accidente de asignación, no creo que exista un IDE que no te marque el error.

Prefiero siempre pensar que debemos codificar para otros y cuanto más claro, simple y natural, más fácil será que nos sigan.

Es una opinión, podemos definir con un "si el estándar Zend lo dice, lo acatamos" guiño

Hablando con un colega sobre este tema (lo bueno de tener colegas desarrolladores / docentes es que podemos tener formas distintas de ver las cosas y podemos discutirlas de manera constructiva y hasta corregirnos entre nosotros), me comentaba que en todo el código fuente de ZF se usa la forma "null == $var", por lo que me decía que era un "estándar" de ZF.

En su momento no tenía tantas horas recorridas dentro del código de ZF, por lo tanto no estaba seguro si realmente se usaba en el 100% del código o sucedía en algunas partes del mismo, así que me puse a volver a revisar los documentos donde especifican el estándar de Zend (no sería la primera vez que me olvide de algún detalle del mismo, por eso siempre RTFM):

El borrador que supuestamente se va actualizando y discutiendo hasta pasar al documento formal
http://framework.zend.com/wiki/display/ZFDEV/PHP+Coding+Standard+(draft)

Documento formal

http://framework.zend.com/manual/en/coding-standard.html

En ambos casos no encontré ninguna sugerencia o referencia al respecto. Así que podríamos llegar a la siguiente conclusión:
  • Esta práctica o técnica no es parte (actualmente) del documento de estándar de codificación (no se sugiere en ningún momento).
  • Pero, aparentemente es un "estándar de facto" ("de hecho") o directamente "una práctica de facto" (más que un estándar de codificación) que los desarrolladores de ZF hacen uso (se puede ver en el código).
Por lo tanto, en mi opinión, si no hay evidencias que en ninguna parte del código de Zend exista el uso inverso, es decir "$var == null", podríamos llegar a la conclusión que es una práctica que deberíamos seguir (aunque yo no lo haya hecho hasta la fecha).

Los Estándares

Los estándares solo sirven si los seguimos todos, de lo contrario no son estándares y se pierde su efecto, y deberíamos dar el ejemplo, por lo que su adopción nos beneficia a todos los desarrolladores (ya que codificaríamos con las mismas reglas, facilitando el entendimiento y dejando un código más "uniforme").

Le comentaba a este colega que hace unos años cuando empecé a adoptar el primer estándar de codificación de Zend (cuando ZF ya se podía empezar a usar en su primer versión) me "dolió bastante" tener que adoptar las llaves iniciando a la izquierda (al estilo C++) y el uso de "_" para todo lo que es "elementos privados", de la misma forma me sucede con el nombre con separación "_" (ej: Zend_Db, Zend_View, etc), ya que estamos modificando los nombres de las clases por un problema de PHP de no tener resuelto el manejo de ubicaciones de directorios y namespaces.

Cabe acotar que muchas tecnologías, como Java o .Net, vienen siempre de la mano de una empresa que a su vez vende su IDE y este ayuda a resolver todos estos problemas (de cómo ubicar los archivos / directorios) y en sí no es tanto problema del lenguaje, aunque ayuda que este maneje conceptos como paquetes / namespaces, y que nosotros nunca tuvimos desde PHP esa relación con ningún IDE (donde muchos desarrolladores aún usan editores de código).

Pero, como acotaba antes, si no adoptamos todos el estándar y tratamos que los demás lo usen, el estándar carece de efecto y no sirve, a ningún desarrollador Java o .Net se le ocurre cambiar la forma de indentar el código por una propia. Por ejemplo, el IDE de .Net (Visual Studio .Net) no te permite cambiar la indentación, él te indenta automáticamente. La primera vez que lo usé dije "¡qué es esto!" pero luego me di cuenta que en realidad era una muy buena idea, no te dejaba lugar a "inventar" estándares y a preocuparte en lo funcional (de todas formas si creas atributos, métodos o variables de un solo carácter, hasta donde sé, te lo sigue permitiendo ;-))

En Resumen

Como docente y como "desarrollador que codifica pensando en los demás", esta práctica no es de mi agrado (por un tema de claridad), y tampoco aparece explícitamente en el documento de estándar de codificación (se podría hasta pensar que es una técnica para evitar un error y no una forma de codificación, aunque lleva a cambiar todo el "paisaje" de nuestro fuente), por el momento no puedo adoptarlo a menos que así explícitamente esté discutido y comunicado como un estándar formal, más allá de si es un "estándar/práctica/técnica de facto" del equipo de desarrollo de Zend Framework.

Si alguno de vosotros encuentra más argumentos o documentación que hable que debemos seguirlo (como estándar), me avisa, y a los 5 minutos estoy cambiando mi forma de codificar ("la cabeza es redonda para que las ideas puedan cambiar de sentido").

Pero... (segundos antes de publicar este post)

Cuando este post ya estaba casi terminando y reconociendo mi falta de no cumplir algo que era "estándar de facto" y hacer público que aún así no iba a seguir esta práctica (ya que no aparecía en los documentos de estándares), empecé a hacer una investigación en el código de Zend y me llevé una gran sorpresa ;-)

Como soy un poco necio, pero mayormente curioso y metódico, me puse a sacar números reales del uso de una y otra práctica en el código de Zend a través de la siguiente búsqueda (buscar la cadena de forma recursiva dentro del directorio de ZF):

grep -i "null ==" * -R

Ingresé a uno de los servidores en GNU/Linux y tomé el directorio de Zend actualizado a la fecha y realicé las siguientes comprobaciones:

Aquí busqué todas las líneas de código en todos los fuentes de Zend y me encontré con el uso extendido de "null ==" algo.


Pero hice la búsqueda opuesta (pensando que no iba a encontrar nada) y veo que aparecen muchas líneas con "== null" (¿eh?)



Entonces, el pulso me temblaba e hice la siguiente prueba, para cada una de las sentencias antes ejecutadas, conté las lineas de ocurrencia ("wc -l") y llegué a la siguiente conclusión:

  • "null ==" aparece en 546 líneas
  • "== null" aparece en 2444 líneas!
Conclusión Final

Listo, no dije nada, tengo razón, no usen "null ==" por que yo lo digo y se acabó la discusión hasta nuevo aviso ;-)

PD: Esto en sí no es un tema de si mi colega se equivoca o yo, me pareció importante discutir todo el asunto de estándares y técnicas, y particularmente, esta tan controvertida forma de "evitar errores" (que parece está de moda) que en mi opinión lo único que hacen es ofuscar el código.

Además, para quebrar una lanza por mis colegas / amigos, muchas veces me han corregido errores más de los que yo pude encontrarles, sin olvidar que me considero eterno alumno de todo y aún dudo y me equivoco ;-)

9 comentarios:

Fran dijo...

Para mi no tiene sentido usar null == para comparar y evitar asi una asignacion de variable xq para comparar contra null hay q usar === (sino te puede pasar q '' == null) y ahi no podes cometer el error de asignar una variable.

Josepzin dijo...

Por una cuestión de lógica debería ser $var==NULL, porque uno no comparan NULL con "algo", compara "algo" con NULL.

ZydRick dijo...

Me parece que todo lo planteas de forma más compleja de lo que realmente es. Veamos.
No hace falta ser un experto en idiomas para saber que en algunos idiomas se definen las propiedades del objeto que se menciona después:
puerta roja
roja puerta

No tiene para todos el mismo orden de lectura una línea (Árabes por ejemplo)... Creo que de lo que trata no es de un estándar nada más sino de un hábito. Las comparaciones Zend no dice en su estándar como deben hacerse así que cada uno las hace como cree más conveniente.

Hace tiempo a mi me dijeron que la formula:
null === $var

Hacía que los desarrolladores se equivocaran menos, no se yo por mi parte uso $variable comparación valor porque me parece más cómoda su lectura.

Un Saludo y PAZ!

Unknown dijo...

y la función is_null() no la usan, yo la uso bastante, es mejor usar $var === null que is_null($var)?, se que la llamada a una función implica sobrecarga, pero alguna ventaja tiene que tener, no?

AdonisDeCuarta dijo...

Yo en principio siempre usé is_null($var). Pero, si hiciera la comparación formal, no veo dónde está la polémica. Veamos... ¿qué diferencia hay entre hacer $var === false o $var === null? Sin embargo, ¿a quién se le ocurriría la loca idea de hacer un false === $var? Nadie lo haría, es una estupidez.
Por lo tanto, es igual de estupidez hacerlo con el null.

ZydRick dijo...

Yo lo cierto es que suelo usar if((bool) $var)

Es más eficiente y simple.

Rubén Moraleda dijo...

Para los amantes de la micro-optimización ahí os van unas pruebas:

10 Millones de repeticiones (siendo $var=null, media de 3 ejecuciones):
!(bool)$var 3.6 seg
!is_null($var) 7.2 seg
$var=="" 3.6 seg
$var==null 3.6 seg
$var===null 3.3 seg

.........................

ZydRick, el problema de tu propuesta "(bool)$var" es que también evaluará false como null, y aunque puede resultar lógico, tambén puede darte problemas en algunos casos.

Yo al igual que la mayoría, me decanto siempre por "$var === null", me parece suficientemente claro, aunque tampoco tengo inconveniente en pasarme a "null === $var" en el futuro si se toma como estándar.

Saludos.

Diego dijo...

Acabo de leer que PHP 5.3.0 RC1 tiene soporte para namespaces.
Creo que salió hace unos días.

ZydRick dijo...

Rubén, por supuesto eso lo se. Hay casos en los que no vale, lo uso pero sabiendo usarlo claro.

Entradas populares