Language: EN

programacion-tipos-enums

Enum Types

Enumerations, or ENUMS, are a special type of data that allows programmers to define a set of named constants under the same type.

These constants represent discrete values that can be used instead of “magic words”. In some languages, enumerations can only be associated with integers, while other languages allow other values such as strings.

The main advantage of using enums is that they provide readability and structure to the code, as it replaces “magic” numbers or strings with meaningful and predefined names.

The most typical (and on the other hand boring) example that is usually given is the days of the week.

enum DayOfWeek {
    Monday, Tuesday, Wednesday, Thursday, Friday
};

DayOfWeek today = DayOfWeek.Wednesday;

This helps maintain the code. For example, if we have to add or modify any of the constants, we only have to change the enum. In our case, if you want to add Saturday and Sunday, you only have to modify it in one place.

Finally, they prevent errors by restricting the values we can use to those defined in the enum, avoiding, for example, that someone misspells a value by mistake. For example, you protect yourself from someone mistakenly writing thurs (they forgot an ‘e’).

In addition, in typed languages, it performs type checking, and prevents us from mixing them up by mistake. For example, entering a Month value into a DayOfWeek type variable.

Examples of Enums in different languages

Let’s see how an ENUM would be created in different languages.

For example, let’s say we have the status of a task. These possible states are “not started”, “pending”, “in progress” and “completed”.

In C# we have the concept of ENUM natively through the reserved word enum.

// Definition of an enumeration in C#
public enum Status {
    NotStarted,
    Pending,
    InProgress,
    Completed
};

// Assignment of the initial status to the currentStatus variable
Status currentStatus = Status.NotStarted;

In C++ it also has the concept of ENUM using the reserved word enum.

// Definition of an enumeration in C++
enum Status {
    NotStarted,
    Pending,
    InProgress,
    Completed
};

// Assignment of the initial status to the currentStatus variable
Status currentStatus = Status::NotStarted;

In JavaScript, we can use immutable objects to simulate enumerations. In the following code fragment, we define an immutable object called Status using Object.freeze().

// Definition of an immutable object in JavaScript using Object.freeze()
const Status = Object.freeze({
    NotStarted: "not_started",
    Pending: "pending",
    InProgress: "in_progress",
    Completed: "completed"
});

// Assignment of the initial status to the currentStatus variable
let currentStatus = Status.NotStarted;

In Python, from version 3.4 onwards, we can use the Enum class of the enum module to define enumerations.

# Definition of an enumeration in Python using the Enum class
from enum import Enum

class Status(Enum):
    NotStarted = "not_started"
    Pending = "pending"
    InProgress = "in_progress"
    Completed = "completed"

# Assignment of the initial status to the currentStatus variable
currentStatus = Status.NotStarted

Tips for using Enums Tips

Enumerations are a very useful tool, and they allow us to represent a fixed set of discrete values in a clear and readable way. In general, it is a good idea to use them.

However, in some cases, their use can lead to over-engineering, especially when it comes to integrating them with other parts of the system.

For example, consider an Status enumeration that represents the different states of a process. If we want to store these states in a database using codes such as.

StatusValue
NotStarted“N”
Pending“P”
InProgress“I”
Completed“C”

We would need to map between the enumeration values and the codes when reading and writing to the database.

// Function to map from string to enumeration
public static Status MapStringToEnum(string statusString) {
    switch (statusString) {
        case "N":
            return Status.NotStarted;
        case "P":
            return Status.Pending;
        case "I":
            return Status.InProgress;
        case "C":
            return Status.Completed;
        default:
            throw new ArgumentException("Invalid status");
    }
}

// Function to map from enumeration to string
public static string MapEnumToString(Status statusEnum) {
    switch (statusEnum) {
        case Status.NotStarted:
            return "N";
        case Status.Pending:
            return "P";
        case Status.InProgress:
            return "I";
        case Status.Completed:
            return "C";
        default:
            throw new ArgumentException("Invalid status");
    }
}

This process can unnecessarily complicate our code and increase its complexity. A simpler alternative in this case would be to use simple constants instead of an enumeration. For example:

// Definition of constants for the states
public const string NOT_STARTED = "N";
public const string PENDING = "P";
public const string IN_PROGRESS = "I";
public const string COMPLETED = "C";

// Assignment of the initial status to the currentStatus variable
string currentStatus = NOT_STARTED;

It’s simpler, but we have just lost the semantics and (above all) the security that enumerations provide. For example, any string could be assigned to the currentStatus variable, even if it does not represent a valid state.

To address this issue, there are alternative patterns, such as strongly typed enums, which provide the security of stricter data types while maintaining the readability and clarity of the code.

In short, using Enums is fine, and in general it is recommended. But as always, use your head. Using them indiscriminately can complicate the code, more than help us.