Design Patterns – Do Enums Create Brittle Interfaces?

abstract classcdesign-patternsenuminterfaces

Consider the example below. Any change to the ColorChoice enum affects all IWindowColor subclasses.

Do enums tend to cause brittle interfaces? Is there something better than an enum to allow for more polymorphic flexibility?

enum class ColorChoice
{
    Blue = 0,
    Red = 1
};

class IWindowColor
{
public:
    ColorChoice getColor() const=0;
    void setColor( const ColorChoice value )=0;
};

Edit: sorry for using color as my example, that's not what the question is about. Here is a different example that avoids the red herring and provides more info about what I mean by flexibility.

enum class CharacterType
{
    orc = 0,
    elf = 1
};

class ISomethingThatNeedsToKnowWhatTypeOfCharacter
{
public:
    CharacterType getCharacterType() const;
    void setCharacterType( const CharacterType value );
};

Further, imagine that handles to the appropriate ISomethingThatNeedsToKnowWhatTypeOfCharacter subclass are handed out by a factory design pattern. Now I have an API that cannot be extended in the future for a different application where the allowable character types are { human, dwarf }.

Edit: Just to be more concrete about what I'm working on. I am designing a strong binding of this (MusicXML) specification and I am using enum classes to represent those types in the specification which are declared with xs:enumeration. I am trying to think about what happens when the next version (4.0) comes out. Could my class library work in a 3.0 mode and in a 4.0 mode? If the next version is 100% backward compatible, then maybe. But if enumeration values were removed from the specification then I'm dead in the water.

Best Answer

When used properly, enums are far more readable and robust than the "magic numbers" they replace. I don't normally see them making code more brittle. For instance:

  • setColor() doesn't have to waste time checking if value is a valid color value or not. The compiler has already done that.
  • You can write setColor(Color::Red) instead of setColor(0). I believe the enum class feature in modern C++ even lets you force people to always write the former instead of the latter.
  • Usually not important, but most enums can be implemented with any size integral type, so the compiler can choose whatever size is most convenient without forcing you to think about such things.

However, using an enum for color is questionable because in many (most?) situations there's no reason to limit the user to such a small set of colors; you might as well let them pass in any arbitrary RGB values. On the projects I work with, a small list of colors like this would only ever come up as part of a set of "themes" or "styles" that's supposed to act as a thin abstraction over concrete colors.

I'm not sure what your "polymorphic flexibility" question is getting at. Enums don't have any executable code, so there's nothing to make polymorphic. Perhaps you're looking for the command pattern?

Edit: Post-edit, I'm still not clear on what kind of extendability you're looking for, but I still think the command pattern is the closest thing you'll get to a "polymorphic enum".

Related Topic