Conditional branches are like a piece of meat in the source code; as the software ages, the meat starts to rot. Before you know it, maggots (bugs) will start to feast on the meat.
One of the main reasons bugs tend to hide around conditional branches is because it increases the complexity of the software. The more conditional branching exists, the more difficult it is to fit all the logic into one’s head. This is obvious, and I can probably talk all day on how bugs can be introduced with conditional branching, but let’s not dwell on that. Instead let’s talk about how we can solve the problem in a simple way.

The dispatch table pattern is not new, but I feel like it is not widely adopted. It is not a traditional design pattern one will find in a typical design pattern book, but in my opinion this pattern will give you the most bang for the buck. With a dispatch table, branching statements can be eliminated completely, and the “shape” of the code can be seen. In the simplest form, a dispatch table is a hash table where all the keys represent all possible actions, and the value of each key contains a call back function that does the actual work.
This is best explained with a simple example. I am going to use JavaScript in the example, but the idea is language independent.
Let’s say, you are building a Tivo’ish program that surfs all the channels and figures out what it should record. Assuming an external data feed look like following:
var channels = { 1: { station: "NBC", showTitle: "Saturday Night Live", genre: "comedy", repeat: true }, 2: { station: "FOX", showTitle: "Cops", genre: "crime", repeat: true }, 3: { station: "ESPN", showTitle: "College Football", genre: "football", repeat: false }, 4: { station: "HBO", showTitle: "Curb Your Enthusiasm", genre: "comedy", repeat: false }, };
The key for the channels hash table is a channel number. In this case, there are only 4 channels, one through four. Let’s move on to the core logic:
function record(channel) { // do some work here... console.log("recording " + channel.showTitle); } function surf(channels) { var genre, repeat, showTitle; for(var number in channels) { genre = channels[number].genre; repeat = channels[number].repeat; showTitle = channels[number].showTitle; if (genre === "football") { record(channels[number]); } else if (genre === "comedy" && !repeat) { record(channels[number]); } else if (genre === "crime" && showTitle !== "Cops") { record(channels[number]); } } }
The code above is making decisions on the genre of the show with a couple of ugly else-if statements. As one can imagine, the else-if statement will continue to grow when additional functionality is required and eventually becomes unmanageable. Imagine what the unit test for this function looks like. Yuck!
Now let’s switch to the dispatch table version:
var actions = { "football": function (channel) { record(channel); }, "comedy" : function (channel) { if (!channel.repeat) { record(channel); } }, "crime" : function (channel) { if (channel.showTitle !== "Cops") { record(channel); } }, }; function surf_dispatch(channels, actions) { var genre; for(var number in channels) { genre = channels[number].genre; actions[genre](channels[number]); } }
An actions dispatch table has been added as a parameter, and all the conditional branch logic has been completely removed. Notice how simple the new surf function has become. Now this version is very easy to extend because the application logic has been decoupled from structural logic. To make things even better, the actions dispatch table is essentially a configuration point for the application. There is an anonymous function with one parameter associated with each key, that is the interface each dispatch item must implement. The application will start to behave differently when the table has been updated. New behavior can be injected without changing any core code. Now, that’s flexibility!
Skeptics may say, that problem has been solved in the Object Oriented world by polymorphism. There are known refactoring steps to deal with this: Extract Method, Move Method, Replace Type Code with Subclasses then finally Replace Conditional with Polymorphism. Wow, that is a lot of work, and think about the number of classes and lines of code you will end up with! I will take the dispatch table pattern any day.
Dispatch table is one of those hidden gem design patterns, that will allow the software to be extended in ways never imagined. The application behavior can be completely changed by supplying new anonymous functions to the dispatch table. If you are working in a dynamic language, the dispatch table can live in a separate “configuration” file, and be read during run-time.
I have only scratched the surface on what you can do with a dispatch table. Chapter 2 of Higher-Order Perl by Mark Jason Dominus has a much more comprehensive overview of dispatch tables. The book is currently available as a free download, so there is no reason not to check it out. Don’t be afraid if you are not familiar or a fan of Perl, the book is readable with very little Perl knowledge.
I would also like to give a special thanks to my friend, and colleague, Kyle Burton, for recommending the book. It forever changed how I think.
25 Responses
Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.
Interesting way to do it, but it may become quickly scrambled with a moderately high number of conditions. Moreover, it’s not always easy to determine which parameter is the best discrimination criteria to use.
I think I still prefer something that will let a (~smart~) compiler optimize the branch tree and be easy to read (because centralized). Something like pattern matching [1] or cond in CL [2]. If the pattern/condition list is simple-enough or at least easy to decompose, the generated/executed code will be very close to the one you present, and the best discrimination criteria is quite easy to find for a compiler once you have a comprehensive list of conditions to be applied.
[1] : http://en.wikipedia.org/wiki/Pattern_matching
[2] : http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/mac_cond.html
When your feed adds a genre not in your list you will get an error. That seems worse to me.
@mike a default action can be implemented with almost no effort. Maybe I can show that, so there will be no error if genre isn’t in the action table.
I’ve been experimenting with functional pattern matching in JavaScript (see: http://www.bramstein.com/projects/jfun/).
Using my experiments, you could rewrite your code as follows:
The last case in the pattern match is a catch-all to make the match exhaustive.
I’m not sure if implementing pattern matching on top of JavaScript is a good idea though. The syntax especially suffers. I’ve been thinking about moving the pattern matching into a preprocessor, but then it wouldn’t be JavaScript anymore
[edit of previous...]
My co-worker actually presented this pattern in a ziptalk on Friday - without knowing the name. I called it a kind of table method patter implementation, and it has also a lot in common with Strategy Pattern (it IS strategy pattern, without objects).
So dispatch pattern it is then. It shows up more and more in my own code (C# mostly), and makes the code much more maintainable.
I believe almost the same behavior can be obtained by using a switch with each case calling its own function. (A switch uses a sorts of jump table) This also solves the default actions issue. The only thing you need to type extra is the break statement. (Which is handy to leave out in some cases
Also anonymous functions scream code replication, so if you put normal functions references in your actions array It becomes even more similar to a switch. (I hate code replication
Just a small suggestion: imho you should include all the fields in the decision table ( showname & repeat ), using lambda’s for example. Then you can avoid the much hated if’s in your example delegates.
My vote is for using switch as well. Also double-spaces after periods? On the web?
I have been using this approach in php a lot and since javascript supports eval type of functionality you can also add dispatch information such that you can filter actions easier.
I am all pro this approach as a tabular format of action/reactions seems much more coherent and legible than nasty conditional tree. It is not that they magically disappear, but just that they don’t sit in the foreground
What about something like this…
switch{
case (genre === "comedy" && !repeat):
case (genre === "crime" && showTitle !== "Cops"):
case (genre === "football"):
record(channels[number]);
}
Checkout “No ifs, ands or buts”, a presentation of the experimental “Subtext” programming environment explicitly built to tackle the problem you’re talking about.
http://subtextual.org/subtext2.html
I agree that this is another good way to eliminate massive if-then-else in some cases, though I think the example would be better illustrated as:
Oh wait, never mind… I missed the point
The article is titled “The Death of If-else, if, and else”, and you use if, else if.
hmmmmm, and we are to take you advise seriously.
This is also named as “Table Driven Method” in famous Code Complete 2 book.
Continuing the Discussion