Best Practices: Fight Code Ambiguity with Enumerations

I've written before about the idea that code needs to have a reason to exist. Right alongside that idea is another I frequently find myself having to be reminded of: code must have a clear, explicit meaning.

Let me clarify what I mean by that (irony alert!). I think that a reason to exist and meaning are two distinct ideas. In my mind, having meaning gives the code purpose and importance (much like it does for humans). Funny thing is, many coders don't put enough effort into revealing the meaning of their code to their fellow developers. The absence of meaning leads to one of the most dangerous enemies a programmer will ever have to face: a monster known to as Ambiguity.

How do you slay this beast? There are many avenues to take, and one of them is to wield a weapon known to us programmers as Enumerations.

Ambiguity: the Programmer's Terror

Consider the following line of code:

var value = DownloadFile("FileName.pdf", true);

After reading this line, we immediately have a problem: we don't know what true actually means! We know (or can reasonably assume) what the DownloadFile() method is supposed to do, and the first parameter looks like a filename, but what in the world does that second parameter represent? We have no idea, and now we have to dig down further to find out. Digging into this particular method won't take much time, but if we're having to do it on tens or hundreds of different methods in a given day it gets exhausting rather quickly.

Let us also consider this scenario:

var success = UploadFile("FileName.pdf", content, 1, 5, 12);

That's even worse than the previous one! What do 1, 5, 12, mean? Size, number of pages, type of file? We can't determine that from just reading this snippet. Worse, anybody who comes along and needs to make changes to this code is less likely to actually follow through, since they'll probably have to know what the values mean in order to feel comfortable making changes and they won't have easy access to that knowledge. Not only does this snippet have awful readability, it indirectly hampers developers' ability to make the code better.

The monster Ambiguity has reared it's ugly head in these two examples, spitting fire and promising doom. So what do we do about it? We pick up the mighty sword known as Enumerations and use it to cut the head off of the beast.

The Best Defense is a Good Enum

Enumerations (aka Enums) are a construct in .NET used to provide a value with a name. By naming our Enums properly and clearly, we can give meaning to otherwise meaningless values.

An example Enumeration might look like this:

public Enum HistoryType
{
Standard,
Detailed,
Exempt
}

Note that Enumerations in .NET, by default, start at value 0 and increment. So for HistoryType, Standard has value 0, Detailed has value 1, and Exempt has value 2. If we wanted to set specific values, we can do so like this:

public Enum HistoryType
{
Standard = 1,
Detailed = 4,
Exempt = 9
}

If we wanted to update the code snippets we saw earlier to use Enumerations, we might do so like this:

I'm a huge fan of Enumerations, and I think these examples nicely illustrate why. Since we've refactored the two bad examples from earlier into using Enums, we can now tell exactly what they do without needing to dive any further. We've saved ourselves precious time by just taking a bit more time to clearly explain what these values mean.

There's two situations in which using Enumerations is almost always the best option: