Las enumeraciones, o ENUMS, son un tipo de dato especial que permite a los programadores definir un conjunto de constantes nombradas bajo un mismo tipo.
La principal ventaja de utilizar enums es que proporcionan legibilidad y estructura al código, ya que sustituye números o cadenas “mágicas” por nombres establecidos significativos y prefijados.
Los números y cadenas “mágicos” son literales que alguien añade al código, sin explicar al siguiente demasiado bien de donde vienen. Por ejemplo
var nota = suma * 1.271; // ¿de donde viene 1.271? a saber
El ejemplo más típico (y por otro lado aburrido) que se suele poner son los días de la semana.
enum DiaSemana {
Lunes, Martes, Miercoles, Jueves, Viernes
};
DiaSemana hoy = DiaSemana.Miercoles;
Esto ayuda a la mantenibilidad del código. Por ejemplo, si tenemos que añadir, o modificar alguna de las constantes, únicamente tenemos que cambiar la enum. En nuestro caso, si quieres añadir sabado
y domingo
, sólo hay que modificarlo en un único sitio.
Finalmente, evitan errores al restringir los valores que podemos usar a los definidos en el enum evitando, por ejemplo, que alguien escriba mal por error un valor. Por ejemplo, te proteges de que alguien escriba por error juevs
(se ha comido una ‘e’).
Además, en lenguajes tipados, nos realiza la comprobación de tipos, y nos impide mezclarlos por error. Por ejemplo, metiendo un valor de Mes
en una variable de tipo `DiaSemana
En algunos lenguajes las enumeraciones únicamente pueden estar asociadas con números enteros, mientras que otros lenguajes permiten otros valores como strings.
Ejemplos de Enums en distintos lenguajes
Vamos a ver cómo se realizaría una ENUM en distintos lenguajes.
Por ejemplo, supongamos que tenemos el estado de una tarea. Estos estados posibles son sin comenzar
, pendiente
, en progreso
y finalizado
.
En C# tenemos el concepto de ENUM de forma nativa a través de la palabra reservada enum
.
// Definición de una enumeración en C#
public enum Estado {
SinComenzar,
Pendiente,
EnProgreso,
Finalizado
};
// Asignación del estado inicial a la variable estadoActual
Estado estadoActual = Estado.SinComenzar;
En C++ también tiene el concepto de ENUM usando la palabra reservada enum
.
// Definición de una enumeración en C++
enum Estado {
SinComenzar,
Pendiente,
EnProgreso,
Finalizado
};
// Asignación del estado inicial a la variable estadoActual
Estado estadoActual = Estado::SinComenzar;
En JavaScript, podemos utilizar objetos inmutables para simular enumeraciones. En el siguiente fragmento de código, definimos un objeto inmutable llamado Estado utilizando Object.freeze()
// Definición de un objeto inmutable en JavaScript utilizando Object.freeze()
const Estado = Object.freeze({
SinComenzar: "sin_comenzar",
Pendiente: "pendiente",
EnProgreso: "en_progreso",
Finalizado: "finalizado"
});
// Asignación del estado inicial a la variable estadoActual
let estadoActual = Estado.SinComenzar;
En Python, a partir de la versión 3.4, podemos utilizar la clase Enum del módulo enum para definir enumeraciones.
# Definición de una enumeración en Python utilizando la clase Enum
from enum import Enum
class Estado(Enum):
SinComenzar = "sin_comenzar"
Pendiente = "pendiente"
EnProgreso = "en_progreso"
Finalizado = "finalizado"
# Asignación del estado inicial a la variable estadoActual
estadoActual = Estado.SinComenzar
Buenas prácticas Consejos
Las enumeraciones son herramienta muy útil que nos permiten representar un conjunto fijo de valores discretos de una manera clara y legible. En general, es una buena idea usarlos.
Sin embargo, en algunos casos, su uso nos puede llevar a una sobreingeniería, especialmente cuando se trata de su integración con otras partes del sistema.
Por ejemplo, consideremos una enumeración Estado
que representa los diferentes estados de un proceso. Si queremos guardar estos estados en una base de datos utilizando códigos como.
Estado | Valor |
---|---|
SinComenzar | “S” |
Pendiente | “P” |
EnProgreso | “E” |
Finalizado | “F” |
Para ello necesitaríamos realizar mapeos entre los valores de la enumeración y los códigos al leer y escribir en la base de datos.
// Función para mapear de cadena a enumeración
public static Estado MapearStringAEnum(string estadoString) {
switch (estadoString) {
case "S":
return Estado.SinComenzar;
case "P":
return Estado.Pendiente;
case "E":
return Estado.EnProgreso;
case "F":
return Estado.Finalizado;
default:
throw new ArgumentException("Estado no válido");
}
}
// Función para mapear de enumeración a cadena
public static string MapearEnumAString(Estado estadoEnum) {
switch (estadoEnum) {
case Estado.SinComenzar:
return "S";
case Estado.Pendiente:
return "P";
case Estado.EnProgreso:
return "E";
case Estado.Finalizado:
return "F";
default:
throw new ArgumentException("Estado no válido");
}
}
Este proceso puede complicar innecesariamente nuestro código y aumentar su complejidad. Una alternativa más sencilla en este caso sería utilizar constantes simples en lugar de una enumeración. Por ejemplo:
// Definición de constantes para los estados
public const string SIN_COMENZAR = "S";
public const string PENDIENTE = "P";
public const string EN_PROGRESO = "E";
public const string FINALIZADO = "F";
// Asignación del estado inicial a la variable estadoActual
string estadoActual = SIN_COMENZAR;
Es más simple, pero acabamos de perder la semántica y (sobre todo) la seguridad que nos proporciona por las enumeraciones. Por ejemplo, cualquier cadena podría asignarse a la variable estadoActual
, incluso si no representa un estado válido.
Para abordar esta cuestión, existen patrones alternativos, como las strongly typed enums
, que proporcionan la seguridad de tipos de datos más estrictos al tiempo que conservan la legibilidad y la claridad del código.
En definitiva, que usar Enums está bien, y en general es recomendable. Pero como siempre, con cabeza. Usarlas de forma indiscriminada puede complejizar el código, más que ayudarnos.