One of the cardinal sins against code readability is scattering hard-coded numbers and strings all over a codebase. For instance, a consumer-facing application may have options in a drop-down menu mapped to hard-coded strings in the back end — but that approach tends to cause problems.
For one thing, it’s easy to make spelling mistakes that not only look bad, but also introduce logic errors. If an option is spelled differently in different parts of the code, it can lead to customers not getting the product they selected. And if changes ever need to be made to the drop-down menu, such as spelling changes, adding or deleting options, it can be easy to miss a stray reference in some part of the codebase.
That’s where enums come in. Enums are special data types developers use when they map certain types of data to be represented in their applications. Enums are especially useful for data representing a category of things in the real world, like the months of the year. The months never change, and there are always 12, which makes them good candidates for representing as enums in code.
If an application stores months as strings instead of enums, problems can occur if an accidental misspelling in the backend prevents users from properly selecting a month that’s spelled correctly on the frontend. Enums get around this problem by representing all the choices in code as integers that increment from zero. Each choice has a name, such as the name of the month, eliminating spelling mistakes because comparisons are made between numbers instead of strings, and any misspelled enum name wouldn’t compile.
Since enums are ubiquitous in programming, developers often default to using enums whenever they need to represent data in code that looks like a short list. But are they always the best choice?
Enums Require a Lot of Mapping
Joe Wilson, owner of software development company Volare Systems, has used enums for a long time, but a few years ago he began to wonder whether they made sense for his type of development. Wilson is a full-stack developer, and the applications he works on have front-end, back-end and database components. He noticed that interfacing back-end C# code to front-end or database code while using enums was always a lot of work.
“I had always seen people struggling to get enums to work in their code,” Wilson said.
In back-end languages like C#, enums are represented as integers, and when their values are sent in a data load, they arrive at the receiving side as integers. In order to restore the original meaning of the enum, developers have to map the integer back to an enum. As a result, a lot of mapping happens when making calls between front-end, back-end and database components.
“I had always seen people struggling to get enums to work in their code.”
“Once you cross in or out of C#, that’s when you’re really paying for the use of enums,” Wilson said.
In addition to the work of mapping enums, it can be confusing for external developers who interface with the application, and also for internal developers and administrators when they view entries in the database that just appear as integers.
“When there’s another app, or somebody else that has to do reporting on your database, and they’re looking at the numbers, they’ve got to have the little cheat sheet for: ‘What does that actually do? What does that mean again?’” Wilson said.
Enums Save Database Space and Speed
Wilson wrote about these concerns in his tech blog a few years back, and he found that back-end developers, in particular, tended to push back against the idea of getting rid of enums. They were more likely to have seen advantages such as database indexing speed and the ability to use bitwise logic.
“People who work primarily in one aspect of it, like back-end developers, have a lot of complex code, and if it wasn’t for the enums they’d lose their minds,” Wilson said. “There’s a couple advantages to it, database size and performance — if you index integers you’ll be better off than if you index strings.”
Because enums are stored in databases as integers rather than as strings, developers also pointed out that they take up less space.
“People said, ‘You’ve obviously never had a gigantic database.... If you did, then you’d be worried about storage,” Wilson said.
While that is true, he’s skeptical the difference between storing enums as strings rather than as integers in the database would make or break a company’s server space. But it depends on the application — Wilson said some applications have more constraints and may need to run performance tests where little differences in speed add up.
Alternatives to Enums
Wilson has found that static classes work well as an alternative to using enums for the kind of code he writes. Strings stored in static classes are also part of fixed sets, so they share the readability benefits of enums in code, and it’s similarly easy to make changes to them. But they are passed as strings to the front-end and the database, which means mapping may not be necessary.
“It looks nice and clean, it’s easy to read for people that come after you and have to do maintenance on the software, and it gets stored in the database as a string and gets sent down to API calls as a string,” Wilson said.
In the code, strings in static classes even look similar to enums. Developers can get the string by referring to the class and using dot notation to call the relevant string.
“You have very readable code, it looks kind of enum-y, and your coding experience is about the same,” Wilson said.
He suspects that a lot of the time when developers choose to use enums, it’s not because the data type makes the most sense for the use case, but because enums are common and is what most people were taught. It’s the conventional wisdom, but he said in many cases it makes sense to question it.
“This is the thing that everybody has to assess, what is going on with their application and what the constraints are,” Wilson said. “It’s always tradeoffs in software development.”