Minimizar el aturdimiento en el código fuente

Formas de minimizar los errores utilizando el nombre de las variables


Minimizar el aturdimiento en el código fuente

En el diseño de interfaces de usuario existe un concepto denominado 'minimizar el aturdimiento '. Imaginemos por un momento un editor de texto en el que el icono del botón Grabar no represente un disco si no un hombre prehistórico cincelando una piedra. La primera vez que el usuario escriba su documento y desee grabarlo irá a buscar el botón de grabar, lo más lógico sería que buscase un disco como en otras aplicaciones y seguramente tarde un tiempo en encontrar el botón adecuado.

Cuando se diseña un interface de usuario se busca que sea similar a otras aplicaciones: los botones de grabar contienen la imagen de un disco, los de nuevo documento una hoja en blanco, los de formato en negrita una B mayúscula (o una N si están en inglés) … Se intenta constantemente que cuando el usuario se enfrente por primera vez a la aplicación encuentre un entorno familiar, que no se 'aturda ', en tres palabras: 'minimizar el aturdimiento '.

¿Qué tiene que ver esto con la normalización de código ? En nuestro trabajo el noventa por ciento del tiempo lo pasamos viendo diverso tipo de código, de diferentes aplicaciones o de diferentes módulos de la misma aplicación. Lo normal es que al cabo del tiempo veamos tanto código propio como de nuestros compañeros de equipo, cada archivo con un estilo diferente (incluso aunque provenga del mismo programador), distintas tabulaciones, diferentes formas de nombrar las variables, todo esto implica que nos lleve un tiempo más o menos largo poder leer el código y saber lo que está haciendo y un tiempo aún más largo ser capaces de modificarlo. En resumen: estamos tan 'aturdidos ' como el usuario al que hemos cambiado los gráficos de los botones.

Parte del trabajo, quizá el más importante, de la normalización del código es precisamente minimizar las diferencias de trabajo y proporcionar un entorno sensato para que el periodo de adaptación sea mínimo y facilite tanto la programación de nuevo código como el mantenimiento del antiguo. En pocas palabras, nuestro esfuerzo se dirige a minimizar el aturdimiento producido al leer código.

Nombres de variables: unicidad y significado

Imaginemos que tenemos una serie de funciones en un programa en C # que graban los datos de un pedido, antes de ello, calcula el saldo a partir de las líneas:



public void Save(clsPedido op)
{ ComputeLines(op);
	op.Save();
}

public void ComputeOrder(clsPedido o)
{ o.Saldo = ComputeLines(o);
}

public int ComputeLines(clsPedido ope)
{ colLineas op = ope.LoadLines();

	return ope.SumLines();
}


En el código anterior, las tres funciones utilizan una clase que mantiene el pedido ( clsPedido ), sin embargo, las tres funciones llaman a sus variables de forma diferente, en la primera se llama op , en la segunda o y en la tercera ope . Además, la tercera función utiliza de nuevo la variable op pero no para nombrar una variable de tipo clsPedido si no para identificar una variable de tipo colLineas .

El programa es corto, no existe demasiado espacio para la confusión, pero ya hemos utilizado tres nombres de variables diferentes, cada vez que entremos a modificar una función tendremos que buscar cómo se llama la variable que identifica nuestro pedido antes de poder siquiera empezar a pensar en modificarla.

La solución en este caso es muy sencilla, si vamos a utilizar una variable para identificar un objeto lo lógico es utilizar siempre el mismo nombre de variable:



public void Save(clsPedido op)
{   ComputeLines(op);

		op.Save();
}

public void ComputeOrder(clsPedido op)
{ op.Saldo = ComputeLines(op);
}

public int ComputeLines(clsPedido op)
{ colLineas ol = op.LoadLines();

	return ol.SumLines();
}


En esta ocasión sabremos que la variable que representa nuestro pedido se llama op mientras que la variable que representa las líneas se llama ol . Con algo tan simple hemos conseguido dos cosas fundamentales: en primer lugar que cada vez que entramos a una función sabemos cómo se llaman nuestras variables, en segundo lugar, si entramos en otra parte del programa y encontramos una variable denominada op podemos llegar a suponer que se trata de un objeto relacionado con un pedido. Esto además nos lleva a un efecto lateral que facilita un poco más el trabajo: evitamos pensar cómo tenemos que llamar un nuevo objeto de tipo clsPedido cuando creemos una nueva función, la elección es simple: se llamará op .

Por supuesto tenemos un pequeño problema, op es fácil de escribir y ligeramente sencillo de recordar pero tiene un significado cuando menos difuso, se podría referir también a la clase clsProveedor , por ejemplo. Debemos intentar que nuestros nombres tengan significado, que nos digan algo. ¿Y si en lugar de utilizar op como nombre de variable para la clase clsPedido utilizáramos algo más significativo como por ejemplo objPedido ? Con este cambio conseguimos que el código sea más legible y más fácil de recordar.

Además podemos establecer una norma: inicialmente todos los nombres de objetos comenzarán por el prefijo obj y les seguirá el nombre de la clase a la que se representa. Así para la clase clsPedido tendremos variables que se llamarán objPedido , para la clase clsProveedor variables con el nombre objProveedor , para la clase clsCliente variables con el nombre objCliente .

Pero ¿qué ocurre cuando en una función utilizamos más de una variable de una clase ? No podemos definir dos veces un nombre de variable idéntico dentro de la misma función pero sí podemos añadir un sufijo a esa variable para que nos amplíe el significado. Así por ejemplo si tenemos una función en la que se copien los datos de un pedido en otro podemos utilizar los nombres de variables objPedidoOrigen y objPedidoDestino :



public void Copy(clsPedido objPedidoOrigen, clsPedido objPedidoDestino)
{ objPedidoDestino.Precio = objPedidoOrigen.Precio;
	objPedidoDestino.Unidades = objPedidoOrigen.Unidades;
}


De esta forma además de identificar nuestra variable y saber que objPedidoOrigen es de tipo clsPedido puesto que sigue nuestra normativa de nombres, también sabemos que es la fuente de los datos mientras que objPedidoDestino representa el pedido sobre el que se van a copiar los datos.

Nombres de función

Otra fuente de confusión debidos a la falta de normalización de código son los nombres de función o métodos.

En este caso tenemos el mismo problema que anteriormente, que nuestros nombres de función pueden ser cualquiera, sin embargo, en nuestras clases y formularios habrá una serie de funciones que son más o menos comunes. Por ejemplo, habrá métodos para cargar datos, para grabar, borrar,...

La idea es utilizar siempre el mismo nombre de función para cada método o al menos para los estándares. Así nuestra función para grabar se llamará Save , la función de impresión se llamará Print , la función para borrar se llamará Delete .

Así, por ejemplo, si entramos en un formulario que tiene un error en sus rutinas de impresión sabemos desde el primer momento que el lugar donde comenzar a buscar es el método Print .

Nota: Normalmente utilizo el inglés para los nombres de métodos y clases. En realidad no es porque mi nivel de inglés sea alto, al contrario, es porque mi nivel de inglés es bajo y el único nombre que se me ocurre en inglés para un método de grabación es Save , sin embargo en español se me ocurren Grabar y Guardar .

Páginas relacionadas