Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using enums or a set of classes when I know I have a finite set of different options?

Let's say I have defined the following class:

public abstract class Event {
    public DateTime Time { get; protected set; }

    protected Event(DateTime time) {
        Time = time;
    }
}

What would you prefer between this:

public class AsleepEvent : Event {
    public AsleepEvent(DateTime time) : base(time) { }
}

public class AwakeEvent : Event {
    public AwakeEvent(DateTime time) : base(time) { }
}

and this:

public enum StateEventType {
    NowAwake,
    NowAsleep
}    

public class StateEvent : Event {
    protected StateEventType stateType;

    public StateEvent(DateTime time, StateEventType stateType) : base(time) {
        stateType = stateType;
    }
}

and why? I am generally more inclined to the first option, but I can't explain why. Is it totally the same or are any advantages in using one instead of the other? Maybe with the first method its easier to add more "states", altough in this case I am 100% sure I will only want two states: now awake, and now asleep (they signal the moments when one awakes and one falls asleep).

like image 252
devoured elysium Avatar asked Dec 09 '22 16:12

devoured elysium


2 Answers

I prefer the first. You can attach methods and behaviour to the classes, and move away from the switch/case pattern common with enums towards true polymorphism (and its benefits wrt. maintenance - adding new cases etc.).

like image 127
Brian Agnew Avatar answered Dec 12 '22 06:12

Brian Agnew


Real OOPers don't use if! Prefer polymorphism to conditionals.

Of course there could be situations where the enum is the way to go (say, if you have a very, very large amount of states or you know that for the domain, it's very likely that all observers will be interested in all transitions), but in the general case, the first option is less complicated. Using the second approach, every listener must repeat the same piece of code:

if (theStateImInterestedIn == event.stateType){ 
    /* actual code */ 
}

And every listener needs this, except for the listeners which react in the same way to all transitions! Code duplication! Aaaaargh! As we all know, repeated code causes bugs (hence the DRY principle), and so we can conclude that your gut feeling is correct - the first option (using two different classes) is the better, as every individual listener implementation will have less boiler plate.

Also; add an else there and you've got interesting times ahead when you add a new state: Some listeners were interested in both types of events, and so assumed that the else branch meant "the state I didn't check for in the if". They now break because the else clause covers >1 state.

like image 40
gustafc Avatar answered Dec 12 '22 05:12

gustafc