Artículo - Esteban Calabria

Anuncio
Lic. Esteban César Calabria
Mayo del 2008
Constancia para el éxito (Uso de constantes)
Lic. Esteban César Calabria
Mayo del 2008
Introducción
Las constantes son una herramienta soportada por numerosos lenguajes de
programación para definir un valor, por ejemplo numérico o string, que no será
alterado en ningún momento, y darle un nombre significativo. Por ejemplo
const
CONST_ACELERACION_GRAVEDAD = 9.8;
De ahí en más siempre que desee realizar un cálculo que involucre la aceleración
de la gravedad podemos usar el nombre de la constante en lugar del valor
numérico.
Var
Velocidad:real;
SegundosTranscurridos:real
(…)
Velocidad := CONST_ACELERACION_GRAVEDAD * SegundosTranscurridos;
(…)
En esta ocasión aprovecharé la oportunidad para hablar sobre el uso de las
constantes y por qué se suele recomendar tanto su uso. Daremos al final algunos
ejemplos de como utilizarlas en distintos lenguajes.
Este trabajo se divide en dos. La primera parte aboga el uso de la constantes
explicando en que nos benefician. Si el lector se siente cómodo y está
familiarizado con su uso puede ir directamente a la segunda parte donde se dan
ejemplos de cómo aplicarlas en distintos lenguajes.
Parte 1. – Sobre el uso de las constantes
1.1.Facilitar la lectura del código
La mayoría de las personas no poseemos la habilidad natural que poseen las
computadoras para trabajar con números. Para comunicarnos utilizamos palabras y
no una interminable secuencia de bits. Es por ello que un programa cuanto más
cercano está al lenguaje de la computadora menos inteligible es para una persona.
Cuando en el cuerpo de algún método aparece un valor numérico distinto a 0, 1, -1
o un string literal diremos que estamos en presencia de un valor hardcodeado.
1
Lic. Esteban César Calabria
Mayo del 2008
Velocidad := 9.8 * SegundosTranscurridos;
(Ej. Valor Hardcodeado)
Los valores hardcodeados generalmente representan algo, la aceleración de la
gravedad, el porcentaje de iva, etc. No obstante para entender su significado hay
que tener el nivel de familiarización con el código que tiene el programador que
acaba de escribirlo. Si otra persona, o el mismo programador, un tiempo después
se cruzan con el valor hardcodeado requiere de un esfuerzo de interpretación para
saber a que se refería ese valor originalmente.
Si reemplazáramos ese valor hardcodeado por una constante y a la misma se le
diera un nombre lo suficientemente significativo, ese esfuerzo de interpretación se
eliminaría facilitando enormemente la legibilidad del código fuente.
1.2.Facilita modificar el código.
Hay valores que dependiendo del problema que estamos resolviendo tienen
especial importancia. En una aplicación financiera por ejemplo lo es el porcentaje
del IVA mientras que en un programa que realiza cálculos físicos tal vez lo sea la
aceleración de la gravedad.
Esos valores son claves para el problema que estamos resolviendo. Si quisieramos
alterar alguno de esos valores, por ejemplo si por una disposición de la AFIP se
altera el porcentaje del IVA, tendríamos que recorrer todo el código fuente de
nuestra aplicación, buscar donde aparece y reemplazarlo.
Con el uso de las constantes esa tarea se nos simplifica ya que nos provee un
punto (o varios) conocido y centralizado de nuestro programa donde se agrupan
los valores de importancia. Si en algún momento tenemos que modificar alguno de
esos valores iremos directamente ahí sin necesidad de recorrer todo el código
fuente.
Es importante, al igual que las variables, que las constantes posean nombres
significativos ya que de nada sirve reemplazar - y hasta puede empeorar las cosas un valor hardcodeado por una constante cuyo nombre no represente nada al que
lee el código.
1.3.Evita errores lógicos
El caso anterior no sólo nos facilita modificar el código fuente. Volvamos al caso
donde la AFIP saca una resolución por la cual se modifica el porcentaje del IVA y
por lo tanto tenemos que modificar nuestra aplicación financiera. Habrá que
corregir en el código el valor viejo del porcenaje del IVA en todos los lugares que
aparezca.
2
Lic. Esteban César Calabria
Mayo del 2008
Ahora si por algún motivo dejamos un lugar sin actualizar el nuevo porcenaje del
IVA, nuestra aplicación compilará correctamente pero contendrá errores lógicos.
Tal vez dicho error sea detectado mucho tiempo después mientras el cliente use la
aplicación y se dé cuenta de que los números no le cierran. Esta clase de errores
son los más graves con los que podemos encontrarnos.
Uno de los objetivos que se persigue a la hora de programar, sobre todo por la
razón antes mencionada, es evitar el código duplicado. Podemos decir que tener en
dos lados distintos el mismo valor hardcodeado representando la misma cosa, es
estar ante la presencia de código duplicado, aunque no se trate de dos fragmentos
de código sino simplemente de un valor que debería ser constante.
1.4.Provee una forma de parametrización
Una de las características con las que se suele halagar a una aplicación es subrayar
su flexibilidad en cuanto a las distintas opciones de parametrización que posee.
Esto significa la posibilidad de alterar su comportamiento modificando algún
parámetro. Qué es y qué no es un parametro podemos decir que queda en manos
del que lo hace, pero como ejemplo podemos citar la posibilidad que nos ofrecen
algunos programas de modificar el color de fondo de la aplicación y que la misma
siga funcionando.
Esto me parece importante porque poniendo los parámetros del sistema como
constantes podemos alterar su comportamiento (parametrizarlo) modificandolas y
volviendo a recompilar.
No obstante en la práctica nos encontramos que la parametrización del sistema se
hace dentro del mismo o bien mediante algún archivo de configuración. Esto nos
dice algo importante. El uso de constantes como buena práctica va más allá de los
beneficios mencionados. Nos habla de separar la lógica de un algoritmo que
resuelve un problema de los valores concretos con los que opera. Este principio
nos puede ayudar a pensar algoritmos más reutilizables que resuelvan con cierto
nivel de abstracción un problema concreto y pueda aplicarse en escenarios
diferentes al que se utilizó originalmente.
El día de hoy utilizamos constantes, mañana esos valores pueden salir de una base
de datos relacional.
1.5. Desventajas
Las constantes presentan el inconveniente de requerir el esfuerzo adicional al
programador de declararla cada vez que se encuentre con un valor hardcodeado,
algo que en el calor de la resolución del problema suele pasar un segundo plano.
En ese caso se puede, después de escribir el código, volverlo a leer para asegurarse
que no haya algún valor hardcodeado que convenga reemplazarlo por una
3
Lic. Esteban César Calabria
Mayo del 2008
constante. De igual forma sigue requeriendo un esfuerzo más de parte del autor del
código.
Mas aún los entornos de desarrollo actuales no suelen poseer un mecanismo para
advertir sobre (y pedirles modificar) la presencia de valores hardcodeados.
El programador deberá estar atento, al declarar una constante, que ésta ya no
exista con un nombre distinto. Ayudaría si al compilar la aplicación el entorno de
desarrollo advirtiera sobre la presencia de distintas constantes con el mismo valor
para corroborar que conceptualmente no se tratan de la misma cosa.
1.6. Mejorar código existente
El uso de constantes es además uno de los refactorings (métodos concretos para
mejorar código fuente existente) más básicos que podemos aplicar y se le suele
conocer como “Replace magic number with numeric constant”.
Parte 2. – Constantes en la práctica
2.1.Constantes de tipos básicos
Veamos un ejemplo de como declarar constantes simples en algunos lenguajes
2.1.1.Ejemplo en Pascal
program EjemploConstantes;
uses
Crt;
const
CONST_ACELERACION_GRAVEDAD = 9.8;
CONST_DOCENA = 12;
CONST_MES_ENERO = 'Enero';
//Constante punto flotante
//Constante entera
//Constante String
(…)
2.1.2.Ejemplo en C#
class Constantes
{
public const double gravedad = 9.8;
public const int docena = 12;
public const string mes_enero = "Enero";
4
Lic. Esteban César Calabria
Mayo del 2008
(…)
}
(…)
2.2.Arreglos constantes
Arreglos(a.k.a Vectores) constantes
También es posible declarar vectores constantes como en este ejemplo. Para
demostrarlo usaremos un vector constante para convertir números en letras.
2.2.1.Ejemplo en Pascal
program NumerosALetras;
uses
Crt;
const
CONST_MIN_NUMERO = 1;
CONST_MAX_NUMERO = 10;
CONST_NUMEROS_A_LETRAS : array [CONST_MIN_NUMERO..CONST_MAX_NUMERO] of string
=('uno','dos','tres','cuatro','cinco', 'seis','siete','ocho','nueve','diez');
var
Numero:integer;
begin
Writeln('Ingrese un numero entre ',CONST_MIN_NUMERO,' y ',CONST_MAX_NUMERO);
Readln(Numero);
if (Numero>=CONST_MIN_NUMERO) and (Numero<=CONST_MAX_NUMERO) then
Begin
Writeln('En letras es: ',CONST_NUMEROS_A_LETRAS[Numero])
end
else
Begin
Writeln('Fuera de Rango');
end;
Readkey;
end.
2.2.2.Ejemplo en C#
class NumerosALetras
{
public const int MIN_NUMERO = 1;
public const int MAX_NUMERO = 10;
static readonly string[] NUMEROS
= new string[MAX_NUMERO-MIN_NUMERO+1]
{"uno","dos","tres","cuatr","cinco" ,
"seis","siete","ocho","nueve","diez" };
static void Main(string[] args)
{
Console.WriteLine("Ingrese un numero entre {0} y {1} ",
MIN_NUMERO, MAX_NUMERO);
int Numero;
int.TryParse(Console.ReadLine(),out Numero);
5
Lic. Esteban César Calabria
Mayo del 2008
if ((Numero >= MIN_NUMERO) && (Numero <= MAX_NUMERO))
{
Console.WriteLine("En letras es {0}", NUMEROS[Numero-MIN_NUMERO]);
}
else
{
Console.WriteLine("Fuera de Rango");
}
Console.ReadLine();
}
}
2.3 .Registros Constantes
Registros (a.k.a structs, estructuras) constantes
De igual forma que los arreglos los registros, estructuras o structs como se prefiera
llamarle también pueden ser constantes
2.3.1.Ejemplo en Pascal
type
TPosicion = record
x:integer;
y:integer;
end;
const
ALTO = 200;
ANCHO = 200;
CONST_CENTRO : TPosicion = (x:0 ; y:0);
CONST_BORDE_SUPERIOR_DERECHO : TPosicion = (x:ANCHO ; y:ALTO);
CONST_BORDE_INFERIOR_IZQUIERDO : TPosicion = (x:-ANCHO ; y:-ALTO);
2.3.2.Ejemplo en c#
struct Posicion
{
public int x;
public int y;
public Posicion(int x,int y)
{
this.x = x;
this.y = y;
}
}
class Constantes
{
const int alto = 200;
const int ancho = 200;
public static readonly Posicion Centro = new Posicion (0,0);
public static readonly Posicion BordeSuperiorDerecho
= new Posicion(ancho, alto);
public static readonly Posicion BordeInferiorIzquierdo
= new Posicion(-ancho, -alto);
}
6
Lic. Esteban César Calabria
Mayo del 2008
2.4 Arreglos de Registros constantes
Arreglos (a.k.a. vectores) de Registros (a.k.a.structs,
estructuras) constantes
Por último podemos tener un arreglo de registros que sea constante.
2.4.1 Ejemplo en Pascal
type
TPlaneta = record
Nombre:String;
KmDiametro:integer;
end;
const
POS_MAS_CERCANO_AL_SOL = 1;
POS_MAS_LEJANO_AL_SOL = 9;
CONST_PLANETAS_SISTEMA_SOLAR :
array [POS_MAS_CERCANO_AL_SOL..POS_MAS_LEJANO_AL_SOL] of TPlaneta
= ((Nombre:'Mercurio'; Diametro:4880),
(Nombre:'Venus'; Diametro: 12103),
(Nombre:'Tierra'; Diametro:12756),
(Nombre:'Marte'; Diametro:6794),
(Nombre:'Jupiter'; Diametro:142984),
(Nombre:'Saturno'; Diametro:120536),
(Nombre:'Urano'; Diametro: 51118),
(Nombre:'Neptuno'; Diametro:49532),
(Nombre:'Pluton'; Diametro: 2274));
var
Numero:integer;
begin
Writeln('Ingrese un numero de planeta');
Readln(Numero);
if (Numero>=POS_MAS_CERCANO_AL_SOL) and (Numero<=POS_MAS_LEJANO_AL_SOL) then
Begin
Writeln('En planeta ',
CONST_PLANETAS_SISTEMA_SOLAR[Numero].Nombre,
' tiene ',
CONST_PLANETAS_SISTEMA_SOLAR[Numero].KmDiametro,
' km de diametro.' );
end
else
Begin
Writeln('Te fuiste del sistema solar');
end;
Readkey
End;
2.4.2. Ejemplo en C#
struct Planeta
{
public string Nombre;
public int KmDiametro;
public Planeta(String Nombre, int KmDiametro)
{
this.Nombre = Nombre;
this.KmDiametro = KmDiametro;
}
7
Lic. Esteban César Calabria
Mayo del 2008
}
class PlanetasSistemaSolar
{
public const int MAS_CERCANO_AL_SOL = 1;
public const int MAS_LEJANO_AL_SOL = 9;
static readonly Planeta[] PlanetasSistemaSolar
= new Planeta[MAS_LEJANO_AL_SOL - MAS_CERCANO_AL_SOL + 1]
{ new Planeta("Mercurio",4880),
new Planeta("Venus",12103),
new Planeta("Tierra",12756),
new Planeta("Marte",6794),
new Planeta("Jupiter",142984),
new Planeta("Saturno",120536),
new Planeta("Urano",51118),
new Planeta("Neptuno",49532),
new Planeta("Pluton",2274) };
static void Main(string[] args)
{
Console.WriteLine("Ingrese un numero de planeta");
int Numero;
int.TryParse(Console.ReadLine(), out Numero);
if ((Numero >= MAS_CERCANO_AL_SOL) && (Numero <= MAS_LEJANO_AL_SOL))
{
int PosVector = Numero - MAS_CERCANO_AL_SOL;
Console.WriteLine("El planeta {0} tiene {1} Km. de Diametro",
PlanetasSistemaSolar[PosVector].Nombre,
PlanetasSistemaSolar[PosVector].KmDiametro);
}
else
{
Console.WriteLine("Te fuiste del sistema solar");
}
Console.ReadLine();
}
}
8
Descargar