Good Design Minimizes The Impact Of Changes

Blue Skies from Stock.xchng We’ve all been there.  Your project stakeholder stands in your doorway with a coffee mug in hand and asks for one more teeny tiny change.

Yeeeaaah. It’d be great if you could just change the display to include the user’s middle name.  That’s pretty easy, right?

No problem!  Let’s see.  I’ll just need to modify the database schema to add the column, update several stored procedures to reflect the schema change, add a new property to the User class, update the data access code to reflect the new property, and finally update the various user controls that render or take in input for this information.

That’s quite a number of changes to the codebase for one measly little change.

The goal of good software design is to minimize the impact of changes in the code.  Many of you might be having the same reaction to this that you would if I just told you the sky is blue.  Well no duh!  Even so, I think this bears repeating again and again, because this principle is violated in subtle ways, which I will discuss in a follow-on post.

This is one reason that duplicate code is considered such an odoriferous code smell.  When a snippet of code is repeated, a change to the code affects every location in which that snippet is located.

Many Design Patterns focus on minimizing the impact of changes by attempting to look at what varies in a system and encapsulate it

For example, suppose you develop a class that monitors the power level of your Universal Power Supply (UPS) device.  When a power level change occurs, several UI widgets need to be updated.

A naïve implementation might have the UPS class keep a reference to each widget that needs to be updated and directly makes a call to various methods or properties of each widget to update the widget’s state.

The downside of this approach becomes apparent when you need to add a new widget or change a widget.  You now need to update the UPS class because of changes to the UI.  The UPS class is not insulated to changes in the UI

The Observer pattern addresses this issue by changing the direction of the dependency so that the UPS class (the observed) does not have direct knowledge of the UI widgets (the observers).  The widgets all implement a comment observer interface and the UPS class only needs to know about that one interface.  Add a new widget and the code for the class does not need to be updated.  Now the UPS class is insulated from changes to the UI.

Another example of code that is not resilient to change is a class with several methods that contain a similar switch statement.  Going back to the example of the UPS class, suppose the class has several operations it must do every few seconds.  But how it implements each operation is dependent on the current power state.

A naïve implementation might have a switch statement in each method that contains a case for each possible power state.  The problem with this approach is that when we need to add a new power state or edit how an existing state behaves, we have to update multiple existing methods.  The State pattern addresses this problem by encapsulating the behavior of a state in a class.  Thus each power state would be encapsulated in a class and the UPS class would simply delegate calls to its member state instance.

So where is the downside in all this? Seems like these patterns provide a win-win situation for us.  Well in these contrived examples it sure does, but not in every situation.  When used improperly, a pattern in one scenario can actually increase the impact of change in another.  Stay tuned.

What others have said

Requesting Gravatar... Damien Guard Nov 13, 2006 4:07 PM
# re: Good Design Minimizes The Impact Of Changes
I think Subtext is a particularly good example of this problem.

If you added an extra field for a blog post to the database and you didn't need anything but view support you would need to modify countless stored procedures and a whole bunch of cs files.

Just follow the flow of logic to see how many layers it goes through.

[)amien
Requesting Gravatar... Haacked Nov 13, 2006 4:13 PM
# re: Good Design Minimizes The Impact Of Changes
You've figured out my inspiration for this post. ;) It's something we're working on. One thing we recently did was remove one layer of abstraction (ObjectProvider -> DataProvider) by removing the DataProvider.
Requesting Gravatar... Damien Guard Nov 13, 2006 4:31 PM
# re: Good Design Minimizes The Impact Of Changes
Another good idea would be to remove the SP's and replace them with parameterised queries which are almost as fast.

An alternative option would be to let something like Subsonic deal with all the data access :)

[)amien
Requesting Gravatar... Haacked Nov 13, 2006 4:42 PM
# re: Good Design Minimizes The Impact Of Changes
Right now I'm looking at NHibernate and Subsonic as options. I'm kinda leaning towards Subsonic because I think it'll be faster to implement. Especially with Rob Conery helping out.

As for parameterized queries, they can be just as fast if not faster than Stored Procedures. Just not the first time you run them.
Requesting Gravatar... Haacked Nov 13, 2006 4:43 PM
# re: Good Design Minimizes The Impact Of Changes
In any case, i'll talk more about that in my follow-up post. You're ruining the punchline. ;)
Requesting Gravatar... Rob Conery Nov 13, 2006 5:13 PM
# re: Good Design Minimizes The Impact Of Changes
The next add-on I'm throwing into SubSonic will be a "SubTextGenerator" that will output a blog for you. It will come complete with pre-generated posts and comments, as well as the obligatory Google Ads and Gravatars.

Requesting Gravatar... Damien Guard Nov 14, 2006 2:15 AM
# re: Good Design Minimizes The Impact Of Changes
Oops, I'll be quiet now ;-)

[)amien
Requesting Gravatar... Daniel Nov 14, 2006 5:52 AM
# re: Good Design Minimizes The Impact Of Changes
I'm ready for the solution to the first example! For all the ORMs and DataSet, this is still my biggest time-consumer: new field in db -> change DataSet (entity code, orm, etc) -> change UI. One "solution" would be untyped datasets, so your code would be new field in db -> change UI. But then you're introducing all sorts of code smells. (Though I guess this is more or less the approach of a SqlDataSource & GridView/FormView, which for cases not requiring much business logic, is pretty powerful...)
Requesting Gravatar... Scott Schecter Nov 14, 2006 6:08 AM
# re: Good Design Minimizes The Impact Of Changes
Phil, check out EntitySpaces when you compare persistence layers.
Requesting Gravatar... Scott Schecter - Entropy Expounded Nov 14, 2006 6:23 AM
# Why should I be using EntitySpaces
Requesting Gravatar... Jeremy Coenen Nov 15, 2006 11:05 AM
# re: Good Design Minimizes The Impact Of Changes
Go with SubSonic if only because it is a part of the "Sub" suite of applications/tools that just plain rock.

SubSonic
Subversion
SubText

Coincidence? I think not.
Requesting Gravatar... Andy Maule Nov 16, 2006 2:26 AM
# re: Good Design Minimizes The Impact Of Changes
Interesting Phil.

I've written a response on my blog http://web4.cs.ucl.ac.uk/staff/a.maule/wordpress/?p=49
Requesting Gravatar... you've been HAACKED Nov 16, 2006 9:33 AM
# Tradeoffs When Minimizing The Impact Of Changes
Tradeoffs When Minimizing The Impact Of Changes
Requesting Gravatar... DotNetKicks.com Nov 22, 2006 10:47 PM
# Good Design Minimizes The Impact Of Changes
You've been kicked (a good thing) - Trackback from DotNetKicks.com
Requesting Gravatar... Evan Nov 24, 2006 2:46 PM
# re: Good Design Minimizes The Impact Of Changes
I've been looking at the same type of problems lately. I hate having to modify 6 different files, update the SPs, and then change all the UI for tiny little changes like the MiddleName field you described.

The best solution I've found includes using some type of O/R mapper for the DAL and entity classes. If you can get support for partial classes in the code generator, it's a win/win for adding custom logic to business entities while letting the O/R mapper handle the first and subsequent generation of the DAL/entities (so code generation doesn't overwrite your custom code).

.netTiers is by far the best solution I've seen, and it's open source (but requires the use of CodeSmith). It uses the Enterprise Library under the covers and provides for a very nice level of abstraction (the DAL can even run against multiple db platforms)

http://www.nettiers.com/

I'm looking forward to your followup post on this.

Evan (a fellow SubText blogger)
Requesting Gravatar... Rob Conery Nov 24, 2006 4:14 PM
# re: Good Design Minimizes The Impact Of Changes
What do you find compelling about .netTiers? While I firmly believe the quality of the code is excellent, the AMOUNT of it is utterly insane.

I hate to say SubSonic is an OR Mapper, but it sort of is and it uses Partials. And you can alter your code templates. And it produces about 1% of the code. And you never have to touch it. Change a field in your DB (or add a view/SP) and compile - done.

Anyway- I'm a big fan of avoiding complexity. OR/Mappers are notorious for creating this exact thing.
Requesting Gravatar... Evan Nov 25, 2006 1:49 PM
# re: Good Design Minimizes The Impact Of Changes
Rob,

Yes, I generally agree that the amount of code it produces is a bit crazy. There's definitely something to be said for avoiding the smell of Needless Complexity.

I'll have to play with SubSonic some more in the near future and get a better feel for it. SubSonic is definitely a top-notch solution. I probably just need some more exposure to it.

Oh, and I definitely agree with your point on traditional O/R mappers and their complexity. The reflection that .netTiers and SubSonic do with the database is both simpler and more elegant than having to maintain a large, ugly set of tool-specific map files for all your tables, views, columns, SPs, constraints, relationships, etc.

Evan
Requesting Gravatar... Rob Conery Nov 25, 2006 7:42 PM
# re: Good Design Minimizes The Impact Of Changes
If you have any questions pop over to our forums at http://actionpack.wekeroad.com. Also - we don't use Reflection in the .NET sense - it's all INFORMATION_SCHEMA (for SQL Server). I think you know this but I just wanted to be sure peeps knew :).

On a small tangent - I love CodeSmith but I found that it exponentially "echo-chambered" the amount of code that could possibly be produced for a website with .NET. In other words - code per site moving from ASP classic to .NET went up by an order of magnitude. This isn't necessarily a bad thing if your site is complex.

However geeks are prone to writing code to solve problems, and geeks using generators are even scarier, because they lose the carpal-tunnel warning sign that maybe they have too much code :).

My name is Rob and I'm a recovering CodeGen Addict :).
Requesting Gravatar... Mike Griffin Feb 23, 2007 7:47 AM
# re: Good Design Minimizes The Impact Of Changes
Like Scott said, give us a look, we're @ EntitySpaces

Here's a blog post of interest
SubSonic-vs-EntitySpaces--A-Battle-of-ORM

and our blog
Entityspaces Blog

EntitySpaces is extremely fast, you can switch between procs and pure dynamic sql with merely a config file entry, no recompiling, you can even run the same binary code against all of our supported databases. We have a very nartual dynamic query API, support binary and xml serialization, build full hierarchical lazy load data models and so on ...
Requesting Gravatar... Ryan Aug 25, 2010 1:01 PM
# re: Good Design Minimizes The Impact Of Changes
Great stuff as usual Phil! So glad that I ran into this site a few months back. Keep up the great work.:)

What do you have to say?

(will show your gravatar)
Please add 1 and 1 and type the answer here: