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?