Aaron Feng posted recently on “The death of if-else, if, and else”. In the post Aaron rewrote some JavaScript conditional checks using a dispatch table type approach.
Following along with Aaron’s post using C#, we’d start with a list of Channel objects:
var channels = new List<Channel> { new Channel { Number = 2, Station = "NBC", ShowTitle = "Saturday Night Live", Genre = "comedy", Repeat = true }, new Channel { Number = 3, Station = "ESPN", ShowTitle = "College Football", Genre = "football", Repeat = false} // ... };
Then we have the logic for deciding which channels to record:
public void Surf(IEnumerable<Channel> channels) { foreach (var channel in channels) { if (channel.Genre == "football") { Record(channel); } else if (channel.Genre == "comedy" && !channel.Repeat) { Record(channel); } else if (channel.Genre == "crime" && channel.ShowTitle != "Cops!") { Record(channel); } } }
Rewriting the code using Aaron’s final approach would look like the following:
public void Surf2(IEnumerable<Channel> channels) { var dispatch = new Dictionary<string, Action<Channel>> { { "football", c => Record(c) }, { "comedy", c => {if(!c.Repeat) Record(c);}}, { "crime", c => {if(c.ShowTitle != "Cops!") Record(c);}} }; foreach (var channel in channels) { dispatch[channel.Genre](channel); } }
Personally, I feel Aaron’s dispatch table is not a big improvement over the previous “if else” version. The actions in the dispatch table are too busy. I think a cleaner approach is to just extract the rules into a data structure – essentially build a collections of predicates to evaluate. Given a channel, the data structure can tell me if the channel should be recorded.
public void Surf3(IEnumerable<Channel> channels) { var recordingRules = new Func<Channel, bool>[] { c => c.Genre == "football", c => c.Genre == "comedy" && !c.Repeat, c => c.Genre == "crime" && c.ShowTitle != "Cops!" }; foreach (var channel in channels) { if(recordingRules.Any(rule => rule(channel) == true)) { Record(channel); } } }
Not quite as flexible, but for this specific example its easier to read and maintain.
What do you think? Is that better or worse?