|14 April 2005|
|14 April 2005|
Nothing like a nice contentious blog headline to grab some readers is there! But seriously, it is wrong. Fundamentally wrong, and I've only just spotted it. Recently I've been doing some work of my own on the Macintosh with Objective-C and the Mac's Cocoa frameworks. I'm not going to evangelise all things Macintosh here (yet), but comparing how one framework does things with another (.NET) made me realize a fundamental flaw in the way .NET does things, particularly with Rich Windows Applications.
Martin Fowler's book "Refactoring: Improving the design of existing code" explains what refactoring is, and perhaps more importantly where to do it. Chapter 3, an essay co-written by Kent Beck, identifies code-smells, source code based symptoms of a larger problem which should ultimately lead to refactoring. If memory serves me rightly one of those "smells" talks about a case where a class is more interested in other objects than it is in itself.
Take a look at the Windows Forms Designer in .NET (which of course inherits the way it works from Visual Basic, the grandaddy of rapid user interface design tools). To build the UI of a Windows application you add a form to your object. You don't actually add a form of course; what happens is that you add a new class to the project which subclasses the .NET Form object. So far so good. Next, you drag and drop controls from the toolbox onto the form to build up the user interface. This results in instance variables getting added to the subclassed form, and code being generated to instantiate those controls at runtime and set up whatever properties you set with the property explorer. The final stage of course is to code up the events, a process which results in more code being added to the form.
Conceptually what you end up with is a subclasssed form that contains other objects, responds to messages from those objects and invariably fires messages down to yet more objects, or back to the original controls. This is a clear case when you think about it of a class not pulling it's weight and being more interested in manipulating other objects than it is in dealing with itself. If you following the refactoring book to the letter the correct way to have implemented this would be to have a mechanism where an event on a control fires a message to a controller containing all pertinent data to update a data model (the classic model view controller pattern). The form should only ever contain code that deals with the form itself, and thus is a cohesive class.
There's another problem as well. Imagine a classic form to represent a detailed view of a businesses' customer. You'd have a slew of labels on the form, as well as controls the user interacts with. The Visual Studio forms designer creates instance variables for each and every control on the form, which of course means at runtime that, other when the form initializes, you have a bunch of instance variables that are never ever used. Again, this is a classic code smell and an ideal candidate for refactoring.
So, Visual Studio is wrong yes? Well, it depends on your point of view; one mans manure is another's fertilizer and all that. Looking at in the light I did yesterday, yes it's fundamentally wrong, and to be quite frank the only Microsoft development tool that approached getting it right was Visual C++ (pre .NET). There you have an external resource file containing the forms definition with events triggering code on a separate controller. Unless you need to add specific functionality to a window to make the window behave differently to a standard one (and few people ever really need to do that), there is no need to go and create a weak object in memory populated with a stack of other relatively unused objects.
This in turn begs a question. Microsoft, over the years, have made a ton of money at simplifying development, but now there is a growing movement obsessed with code elegance, architecture and design principles. Will we ever see a day where Microsoft focussses on a tool that drives developers to implement applications using best practices? A clear model view controller implementation driven by a UI generator based on binary resource files that are "interpreted" instead of "instantiated" at runtime would appear to be the best and most elegant route to take, but that's Visual C++ which is effectively legacy, isnt it?