Esta entrada contiene algunos consejos que no por conocidos dejan de ser útiles a la hora de programar. Con ellos se puede evitar algunos errores de programación.
1) Comentar. Los lenguajes de alto nivel como C o Java son "amables" con el programador, pero no tanto. Un código muy compacto y optimizado puede ser muy bueno para la máquina, pero no para el humano. Esos códigos son difíciles de mantener y comprender. Es un error pensar que no se cambiarán o que recordaremos siempre qué hace un segmento de programa. Y aún cuando esto último sea cierto, es probable que el autor del programa no sea el único que lo leerá. Me ha pasado más de una vez que después de dejar un programa por un tiempo, cuando trato de mejorarlo lo encuentro a tal punto incomprensible que prefiero hacerlo de nuevo, aún cuando ésto me puede tomar un día completo. Ésto puede evitarse con un buen uso de los comentarios. He visto algunos programadores que piensan que es inútil y redundante. En mi experiencia es necesario. Una forma que uso para programar es escribir primero el seudocódigo en un editor y a partir de ahí escribirlo en el lenguaje de programación. Así el seudocódigo se transforma en comentarios.
2) Pensar en el usuario final. Un consejo muy bueno cuando se hace un programa es poner un comentario al principio explicando brevemente qué hace el código. Por cortesía con el usuario, es necesario no sólo comentarlo, sino imprimirlo al principio de la ejecución. Quien corre el programa puede no tener acceso al código fuente y no puede estar adivinando qué hace el programa o qué requiere como entrada. Si se requiere una entrada, es necesario que el usuario pueda saber en cualquier momento las carácterísitcas de ésta. Sin embargo, hay que tener en cuenta que muchas veces, el usuario de un programa no es una persona, sino otro programa. En buena medida ésto esta de acuerdo con la filosofía Unix. Algunos programas pueden ser comandos requeridos por otros comandos. Hay que poder hacer una diferencia entre cuándo un programa ha de ser usado por una persona o cuando por otro programa.
3) Cuidado con los condicionales. En C y C++, la instrucción
if (condicion)
Instrucciones
puede resultar en un error lógico no fatal si se combina un error de sintaxis con una mala práctica de programación. En esos lenguajes, una asignación como x = 2 es una expresión con un valor, el del lado izquierdo después de la asignación. Esto hace que pueda aparecer como parte de una expresión más larga y es aprovechado por programadores experimentados para escribir código más compacto. Por otro lado, un error muy común es escribir el operador de asignación '=' en lugar del de relación '=='. Cuando estas dos cosas ocurren en un programa, como en la instrucción
if ( x = 2)
printf("\nx = %d", x)
se realiza primero la asignación x = 2, se verifica la condición y se ejecuta la instrucción printf, imprimiéndose no el valor que x tenía, sino 2. El usuario puede pensar que se ha cumplido la condición, cuando en realidad se ha cambiado el valor de la variable. ¿Por qué se realiza el cuerpo de if?, es decir ¿Por qué es cierta la condición? la respuesta es que la condición de if se evalúa como un número booleano, que toma sólo los valores 0 y 1. La computadora toma como 1 cualquier cosa que no sea 0, y, como se dijo arriba, la expresión x = 2 tiene en realidad el valor de 2, lo cual es diferente de 0 y se evalúa como 1 o "verdadero". Si el segmento varía un poco, como se muestra abajo:
if ( x = 0)
printf("\nx = %d", x)
entonces el cuerpo de if no se ejecuta, porque el valor de la asignación x = 0 es 0 ó "falso".
Abajo se muestra un programa con estos errores.
#include <stdio.h>
int main()
{ /* Abre main*/
/* Inicialmente x = 1*/
int x = 1;
/* Buena practica de programacion*/
if( 1 == x )
printf("\nx = %d\n", x);
/*Una mala practica de programacion,
combinada con un error, genera una asignacion
sin advertencia y la condicion es verdadera*/
if( x = 2 )
printf("\nx = %d\n", x);
/* De nuevo se genera una asignacion,
se asigna 0 a x, y la condicion es falsa */
if ( x = 0 )
printf("\nx = %d\n", x);
/* El valor final de x*/
printf("\nx = %d\n", x);
return 0;
} /* Cierra main */
el programa se compila sin problemas y se genera el ejecutable. (En Java sí hay un aviso). Aquí la salida:
x = 1
x = 2
x = 0
¿Qué hay que hacer para evitar estos problemas? Crearse la buena práctica de programación de escribir siempre los condicionales como ( 2 == x ) en lugar de ( x == 2 ). Las dos formas son correctas, pero en caso de olvidar un '=', la segunda puede provocar un error sutil difícil de detectar si está inserto en programa grande. Recuerde que las asignaciones no se hacen de la forma 2 = x; sino como x = 2;
Aquí el mismo programa con ésta convención:
#include <stdio.h>
int main()
{ /* Abre main*/
/* Inicialmente x = 1*/
int x = 1;
/* Buena practica de programacion*/
if( 1 == x )
printf("\nx = %d\n", x);
/*Con una buena practica de programacion,
un error genera una advertencia del compilador*/
if( 2 = x )
printf("\nx = %d\n", x);
/* De nuevo se genera una advertencia
del compilador*/
if ( 0 = x )
printf("\nx = %d\n", x);
/* El valor final de x*/
printf("\nx = %d\n", x);
return 0;
} /* Cierra main*/
Aquí está un mensaje del compilador indicando un error.
Archivo.c: En la función ‘main’:
Archivo.c:15:7: error: se requiere un l-valor como operando izquierdo de la asignación
Archivo.c:20:8: error: se requiere un l-valor como operando izquierdo de la asignación
4) El orden de las condiciones afecta la rapidez con la que se ejecuta el programa. Cuando se escribe un segmento del tipo
if (condicion)
Instrucción1
else
Instrucción2
se debe poner como condición aquello que tenga más probabilidades de ser evaluado como "verdadero", de lo contrario el programa evaluará if y else cada vez que se ejecute, cuando podría evaluar solamente if, así se gana un poco de tiempo.
De igual manera, cuando se evalúa una instrucción de la forma
( (condición1) && (condición2) )
condición1 debe de ser la más probablemente falsa de las dos, ya que basta con que la primera sea falsa para que toda la expresión lo sea, y por lo tanto no es necesario verificar la condición2, así el programa se ejecuta más rápido.
Cuando se evalúa una instrucción
( (condición1) || (condición2) )
condición1 debe ser la más probablemente verdadera, porque basta con que la primera lo sea para que toda la expresión sea verdadera y no es necesario evaluar condicion2.
Seguir cada una de éstas recomendaciones tal vez provoque una diferencia marginal en la ejecución de un programa, pero en conjunto en un ciclo largo pueden hacer que el programa se ejecute más rápido.