This post originated from an RSS feed registered with .NET Buzz
by Udi Dahan.
Original Post: Polymorphism and the switch statement
Feed Title: Udi Dahan - The Software Simplist
Feed URL: http://feeds.feedburner.com/UdiDahan-TheSoftwareSimplist
Feed Description: I am a software simplist. I make this beast of architecting, analysing, designing, developing, testing, managing, deploying software systems simple.
This blog is about how I do it.
In my previous post, I contrivedly complained about how C# makes it hard for me to switch based on type. In the comments I got, rather quickly I might mention, Keith suggested the "replace switch statement with polymorphism" refactoring. While that refactoring is quite often what is needed when the switch is found in implementations of procedural business logic, the appropriate refactoring in this case is different. First, some context. The code described was in an event handler for a specific command activation - the 'new' command. The command pattern is a common one in user interfaces so I won't expound on it here. OK, so the user can via the menu or toolbar request to create a new entity. The menu, or toolbar, activate the 'new' command while passing along the type of entity to create in the EventArgs of the Activated event of the command. The code shown in the previous post showed a single event handler that would decide based on the EntityType property of the event args what to do - open the customer form, order form, etc. What is needed is to perform the refactoring called (well, I call it): "replace switch statement in single event handler with multiple, specific type based event handlers". I should probably find a better name for that :) I'll skip some of the interim steps and go directly to the generic solution. The new code would look more like this: public class CommandHandler<T> where T : IEntity { public CommandHandler() { NewCommand.Activated += delegate(object sender, EntityEventArgs e) { if (e.EntityType == typeof(T)) { IView v = this.builder.Build<IEntityView<T>>(); v.Show(); } }; } } and then you'd just instantiate a command handler for each entity type like so: new CommandHandler<Customer>(); new CommandHandler<Order>(); and the forms would respectively implement IEntityView<Customer> and IEntityView<Order>. The builder that you use (I use Spring) would easily look up the type supporting that interface (you'd most probably only have one class like that in play) and instantiate it. So, although in this case Microsoft does not make it easy to get the poorly designed code working, surprisingly they supply no guidance around this incredibly common Rich/Smart scenario - even in the CAB/Smart Client Factory. The solution is object oriented, generic, and results in less code. A winner all around. What say you?...