DevPinoy.org
A Filipino Developers Community
   
Enums are EVIL!

Early in my C# coding life I actually liked enums. They're neater than C enums (which are glorified int constants) and they're type-safe. But lately I've grown to hate them. To me, they are a leading cause of verbosity in C# code and those who use them tend to produce procedural code. I'll show why I feel this is so, and I'll discuss an approach you can use to weed them out.

I remember a project I worked on earlier this year in a previous employer. Some parts of the code made use of Model-View-Presenter and some don't. I guess such a thing is kinda expected when development teams change throughout the different phases of the project. But there's this particular thing in the WinForms code that stood out like a sore toe. The UI had a grid control and an array of buttons in the lower portion of the form. In this case, each button had a particular enum assigned to its Tag property. All the buttons had just one event handler, and eventually the call to the event handler gets to a massive switch-case block which calls the appropriate view/form method for the button. Massive pain!

Enums are simply labels (or, in the example I cited above, tags). You can assign them anywhere to allow you to distinguish between different cases that are represented by the enum. For example, if you want to distinguish between days, you can use a DayOfWeek enum, which comes built into .NET anyway. If you want to distinguish between different data types you can have some enum like MyDataType.String, MyDataType.Integer, MyDataType.Decimal, and so on. But then...HOW do you actually plan to distinguish between them later in your code? More often than not, it will involve a massive if or switch block. I mean, pull out any .NET code you can find that uses enums...it's very likely that it will have that conditional block to distinguish between the different values for that enum. It is equally likely that duplication or similar code (cut-n-paste code?) can be found across the various case handlers in that particular if or switch block.

The object-oriented way of dealing with an enum is to...throw it out! Wink I am not kidding. Instead, replace them with polymorphic behavior. The example I cited above with all form buttons having a common event handler but differing enum values assigned to each button's Tag property can be refactored into using the Command pattern. The WinForms default event handling mechanism is in fact very similar already to the Command pattern so the simpler solution might be to simply switch back to the WinForms way of doing things (having a delegate to handle each Button's Click event). On the other hand, my example above about handling different data types can be dealt with using something like the Strategy pattern.  So you can have separate classes for handling string, integer and decimal operations having the same interface or superclass. So instead of doing something like:

HideAllFields();
switch (dataType) {
    case MyDataType.String:
        StringTextField.Text = someValue;
        StringTextField.Visible = true;
        break;
    case MyDataType.Integer:
        IntTextField.Text = someValue.ToString();
        IntTextField.Visible = true;
        break;
    case MyDataType.Decimal:
        DecTextField.Text = someValue.ToString();
        DecTextField.Visible = true;
        break;
}

You can do something like:

HideAllFields();
myData.EnableControlAndSetValue(someValue);

and have different classes representing string, integer and decimal deriving from the same class or interface with a virtual method named EnableControlAndSetValue. In this case the class for handling strings can look like:

public class MyStringType : MyBaseType {
    public MyStringType(TextBox textFieldControl) : base(textFieldControl) {
    }
    public override void EnableControlAndSetValue(object someValue) {
        myPrivateTextBox.Text = someValue.ToString();
        myPrivateTextBox.Visible = true;
    }

You might be thinking: "Hey, that means more code to type!" In a way, yes, that's true for this example. But imagine if you have twenty possible data types, and suddenly the requirement is changed and you have to support thirty possible data types. With the enum approach, you'll have to change the enum to add ten new enum entries, and you'll have to extend your switch statement to support thirty cases. In contrast, with the Strategy pattern approach here will only require you to create ten new short classes to correspond to those new data types, each differing only in their overridden EnableControlAndSetValue method. If all your classes do the same routine (setting the textbox Text property and making it Visible) then you can even move the EnableControlAndSetValue method to the base class (e.g. MyBaseType) and you won't have to override it at all in each class.

You might think that this example is contrived and puts enums in the worst light possible and that there are pros and cons to the enum approach vs. the polymorphic approach. Yes, there definitely are trade-offs, but in my case I prefer smaller, more focused classes than an unwieldy series of if/switch statements. So these days I have shunned enums. I only work with them when I am forced to do so (i.e. legacy code I need to maintain at work -- and I certainly feel the itch to get it refactored!).

UPDATE: The master showed me these links: Replace Conditional Logic with Strategy and Replace Conditional Dispatcher with Command. Thanks master!


Posted 09-12-2007 11:00 AM by cruizer

Comments

rdagumampan wrote re: Enums are EVIL!
on 09-11-2007 8:14 PM

Before I am fond of using Enums also but this time I am trying to refactor and converthem into public static classes with public static readonly properties.

cruizer wrote re: Enums are EVIL!
on 09-11-2007 8:47 PM

any particular reason why, rodel?

LaTtEX wrote re: Enums are EVIL!
on 09-11-2007 9:49 PM

Enums are fine if the definition of the enumeration is very rigid, and the containing type (e.g., an int) is appropriate for that rigid enumeration.

Otherwise nakakabuwisit siya dahil nga rigid siya.

jokiz wrote re: Enums are EVIL!
on 09-11-2007 11:35 PM

i still love enums especially flaggable ones!

cruizer wrote re: Enums are EVIL!
on 09-12-2007 12:54 AM

ok, so i retract. maybe enums are not entirely evil ;P they have their unique uses

but now it would really take a lot of convincing for me to go with enums

jakelite wrote re: Enums are EVIL!
on 09-12-2007 9:33 AM

@dehran_ph

actually sir enums are just syntactic sugar which basically does the same thing under the covers.

this enum

public enum Sex

{

   Male,

   Female

}

compiles to this IL

.class public auto ansi sealed Sex

   extends [mscorlib]System.Enum

{

   .field public static literal valuetype Sex Female = int32(1)

   .field public static literal valuetype Sex Male = int32(0)

   .field public specialname rtspecialname int32 value__

}

or perhaps i misunderstood your post =D

Brave Anonymous wrote re: Enums are EVIL!
on 09-12-2007 7:42 PM

He he.  The switch code fragment is actually easier to understand, especially with 30 cases.  The intent is clear and takes just a 2-second glance to understand.

cruizer wrote re: Enums are EVIL!
on 09-12-2007 8:00 PM

true. but in most real-world apps the typical switch code fragment is not just a fragment but a humongous piece of code.

barakoboy wrote re: Enums are EVIL!
on 09-13-2007 12:00 AM

i normally use enums for methods that have a limited number of possible correct values.

for example:

public void warpMeToTheMonthOf(Month month) {

   // enter time space warp code here

}

Comgen wrote re: Enums are EVIL!
on 09-13-2007 1:22 AM

Evil in the sense that if misused will lead to "HELL" but if used properly will be heaven.. Maybe we can enumerate some of the scenarios where in Enums are used properly, improperly.

jop wrote re: Enums are EVIL!
on 09-13-2007 2:59 AM

During the time when Java doesn't have an enum type someone invented this typesafe enum technique: www.bearcave.com/.../type_safe_enum.html

It uses public static instances of the "Enum Class" instead of using public static ints. I find this more flexible because it is now a full blown class that you can extend.

I still find this much better than C# enums. Here is a Month enum implemented using that pattern: jop.pastebin.com/f24346ce0

Java now has an enum class. Conceptually, it is the same as the original technique but with a much better (IMO) syntax.

I still use enums instinctively, but I have very little tolerance for them. Once I feel the need to use them in conditionals, I refactor the enum into an EnumClass and then put the logic into the class itself.

jakelite wrote re: Enums are EVIL!
on 09-13-2007 8:24 PM

c# enums are actually syntactic sugar over typesafe enumerations. this code

public enum Sex

{

   Male,

   Female

}

compiler to this

.class public auto ansi sealed Sex

   extends [mscorlib]System.Enum

{

   .field public static literal valuetype SSD.Data.Sex Female = int32(1)

   .field public static literal valuetype SSD.Data.Sex Male = int32(0)

   .field public specialname rtspecialname int32 value__

}

cruizer wrote Cyclomatic complexity and its effect on my code
on 09-20-2007 2:58 AM

Have you heard of the term cyclomatic complexity ? I had my first encounter with it in the current project

jonas wrote re: Enums are EVIL!
on 09-28-2007 11:05 AM

I totally agree with enums are evil.... I just find them used as an alias for an int.

I prefer using simple objects to represent an item....

Also I hate switch statements... too much bloat...

Passenger wrote re: Enums are EVIL!
on 09-30-2007 7:07 PM

If you were writing this let say five years ago when you dont have the convenience of .net you might  give it a much moderate title.. Back when you have to manage your classes, resources were limited. But time changes hardwares catch up, softwares catchup... Anyway i still go for the simplest solution whatsoever its just a matter of choice and lifestyle i guess. You wouldnt want to find "MASO" for cracking nuts. I still find enum very handy. teka ano bang ingle sa MASO? HA HA di ko alam eh.

cruizer wrote re: Enums are EVIL!
on 09-30-2007 8:51 PM

yun maso eh sledgehammer yata. you're right about having the simplest available solution...even the pattern I described above would be overkill and YAGNI at times.

cruizer wrote And so I ate my words
on 10-09-2007 2:59 AM

Yeah, I said enums are evil . Now I'm taking them back. I was forced to swallow my pride and use

Chris B. Behrens wrote re: Enums are EVIL!
on 10-19-2007 8:07 AM

One thing I've never understood about this refactor...doesn't replacing it with the command just move the dispatcher from one place to another?

The example you choose allows you unify all of the paths with ToString; well, you could have done that inline with a cast to an object, too. What about an example where the branches cannot be unified?

cruizer wrote Design patterns are NOT from hell
on 05-01-2008 6:56 PM

I saw this somewhere in my daily reading list (I religiously browse my Google Reader at the start of

Rob Conery wrote You’re Not Your Data Access
on 06-11-2009 8:51 PM

Seems I touched off a bit of a “swirl” with a comment I made on my last blog post: I think, in general

Colour Coding wrote Enums are Evil: The State Pattern
on 07-25-2009 5:27 AM

Enums are Evil: The State Pattern

Copyright DevPinoy 2005-2008