sábado, 8 de octubre de 2016

Detecte el Error... o que la Fuerza te Acompañe


El siguiente cómic presenta una situación de Robots Asesinos como resultado de un error en la programación. ¿Cuál es el error?


Dependiendo del lenguaje de programación, este error puede ser evitado por la sintaxis del lenguaje y/o el compilador pero, considerando que C y C++, siguen estando dentro del Top 10 de los lenguajes de programación más usados en el mundo en las categorías Mobile, Enterprise y Embedded (ver artículo en IEEE Spectrum y la versión interactiva), este es un error clásico en estos lenguajes.

El error se produce porque en este tipo de lenguajes el operador = se usa para realizar asignaciones y no comparaciones, para lo cual existe el operador == y, aún cuando pueda parecer poco intuitivo, es una de las gracias también. La posibilidad de realizar una asignación y comparación al mismo tiempo, permite que la programación en lenguajes como éste sea muy compacta.

¿Entonces cómo evitar este tipo de errores?

La solución es usando lo que se llama Yoda Conditions, en honor al personaje Yoda de la Guerra de las Galaxias. La mayoría de los idiomas del mundo se hablan usando la sintaxis SVO (Sujeto-Verbo-Objeto). Por ejemplo: "El agarró el sable", "Yo programo en C". En el caso de Yoda, él habla usando la sintaxis OVS (Objeto-Sujeto-Verbo). Abajo, algunas de sus frases más famosas para ejemplificar:

  • "Un misterio infinito la Fuerza es. Mucho por aprender aún queda"
  • "Caminos a la victoria hay, distintos que aplastar a un enemigo".
  • "Mucho que aprender todavía tienes"
  • "Es una falta más y más común entre los Jedi. Demasiado seguros de ellos son. Incluso los más viejos, con más experiencia"

Dicho lo anterior, las Yoda Conditions consisten en escribir las comparaciones de manera inversa. Por ejemplo:

if ( a == 4 ) 
{ ... }

Usando las Yoda Conditions, el código anterior se debe escribir como sigue:

if ( 4 == a ) 
{ ... }

A primera vista, la lectura es poco natural y no es tan evidente la ventaja de hacer algo así, pero, tiene la gracia que en permite que el compilador detecte asignaciones erróneas y, además, en ciertas situaciones permite evitar errores infantiles con punteros u objetos nulos. Por ejemplo, consideremos que se requiere identificar si un Persona vive en una determinada Ciudad para realizar una acción. La manera natural de escribir esto es como sigue:

if ( Persona.ciudad().equals("santiago") ) 
{ ... }

El código anterior está sujeto a varias condiciones de error, por ejemplo, que el objeto Persona sea nulo y/o que la ciudad sea un String nulo también, provocando un NullPointerException. Si cambiamos la comparación a la sintaxis Yoda, el código quedaría como sigue:

if( "santiago".equals( Persona.ciudad() ) ) 
{ ... }

Dejemos de lado los problemas relacionados a los espacios, mayúsculas, minúsculas, etc. Sólo por completar el ejercicio de evitar las excepciones por punteros nulos, la comparación debiera quedar como sigue:

if( Persona != null && "santiago".equals( Persona.ciudad() ) ) 
{ ... }

Al aplicar esta técnica, se pueden evitar muchos errores y optimizar el código, evitando la incorporación de toneladas de cláusulas if-then para validar todo.

Ahora bien, esta última sintaxis sólo logrará el resultado deseado en lenguajes que realizan la validación de operaciones lógicas usando la semántica de Corto Circuito o Short-Circuit en inglés, en la cual, el segundo argumento sólo se evalúa considerando el valor del primer argumento y el operador utilizado (AND, OR).

Pero esto, como en la otra película, "es otra historia".

No hay comentarios.: