Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Planning for vs. Reacting to Change

As a first post, I'll open with a favorite topic of mine...dealing with change.  When developing, I'm often torn between handling change by either planning and coding for it or by reacting to it when it comes up.  To deal with this, I try to:  avoid premature generalization, stick to the rule of "fool me once," code to interface when applicable, and architect judiciously.  To elaborate...

Premature Generalization
Often, I hear people talk about how they're writing their code to be reusable and configurable.  Eight times out of ten, when I find myself saying these very words, I find that either 1) it never ends up being reused or 2) the configurable parts I coded never needed reconfiguration. Unless you're building an application or framework specifically for a niche of reusability (such as an ORM), a better philosophy to stick to, to combat premature generalization while still preparing for change, is to keep your code as simple as possible and have no duplicated code.

Fool Me Once
Along with premature generalization, there are developers that fall into the bane of pattern-itus.  This is the developer that throws a design pattern at every opportunity in the name of preparing for change.  But if that area of the application never gets changed, then the pattern may have only introduced needless complexity to the application.  On the other hand, patterns are incredibly useful when change does occur; therefore, I (try to) stick to keeping things as simple as possible and introduce patterns only after the first change in code occurs.  To illustrate, suppose you have a two-case switch statement.  The state pattern, or other polymorphic solution, could be introduced to eliminate the switch statment...but what if the two-case switch statement never gets any bigger or never gets duplicated?  In this case, the state pattern only added a lot more complexity to the situation.  On the other hand, what if the two-case switch statement begins to grow or is needed in another area of the application.  This becomes the perfect opportunity to introduce a design pattern because we now know that this is an area likely to change again in the future.  Obviously, some design patterns are useful from the get go...which leads me to me to my next point...

Code to Interface
Although it's difficult to predict exactly where change will occur, coding to interface is a simple way to keep code loosely coupled while still avoiding excessive premature generalization.  Communications with a data-tier are perfect examples of good places to code to interface.  The data-tier is often mocked during unit testing and, generally, has a stable set of publicly exposed methods.  In this case, design patterns, such as the abstract factory pattern, are a perfect fit from the get-go of project development.  It could be argued that this itself is premature generalization...but, IMO, there are some patterns which are obviously applicable when a project begins...I'd call this architecting judiciously.

Architecting Judiciously
So after bemoaning on about premature generalization and needless complexity, general architecture still needs to be taken into account.  Third party tools and general architectural approaches should be carefully considered before beginning any project.  For instance, if I know I'll be building a data-driven application, then there are some patterns which, for me, almost become a given and need to be taken into account from day one; an example includes building a data-communications framework with NHibernate using the abstract factory pattern.  On the flip side, over-architecture can quickly lead to overly-complex applications that are difficult to understand and maintain.

There's certainly a delicate balance among premature generalization, coding to interface and architecting judiciously.  That balance is usually determined in each project by trial-and-error...with the goal being that each type of architectural error is only encountered once.  If you're successful at this, then your application is probably adapting well to change and will continue to do so in the future.

For some great resources with respect to...
...fool me once:  Martin Fowler's Refactoring and Joshua Kerievsky's Refactoring to Patterns.
...coding to interface:  Robert Martin's Agile Software Development.
...architecting judiciously:  Ken Pugh's Prefactoring and Martin Fowler's Patterns of Enterprise Application Architecture.

Billy


Posted 09-20-2006 2:21 PM by Billy McCafferty
Filed under:

[Advertisement]

Comments

goodenough wrote re: Planning for vs. Reacting to Change
on 09-20-2006 6:04 PM

Congrats on your new home! I have been reading your other blog for a while - always a pleasure. Also, have enjoyed your articles on NHibernate. They really helped me get a handle on what was going on.

Keep up the good work.

Don

Billy McCafferty wrote re: Planning for vs. Reacting to Change
on 09-20-2006 6:06 PM

Thanks Don, I appreciate the feedback!

Billy

Christopher Bennage wrote re: Planning for vs. Reacting to Change
on 09-21-2006 11:29 AM

I agree with every one of your points.  I was urged by the stakeholders in my current project to make _everything_ configurable.  In my opinion, it has turned out nightmarish; a vivid example of Premature Generalization. I find myself thinking YAGNI (http://www.c2.com/cgi/wiki?YouArentGonnaNeedIt).  Though, that can be easily overdone as well.

Have you read Jimmy Nilsson's Applying Domain-Driven Design and Patterns? I'm reading through it currently and reflects many of the same ideas (Nilsson borrows heavily from Martin Fowler and Eric Evans.)

Ben Rice wrote re: Planning for vs. Reacting to Change
on 09-21-2006 11:35 AM

Refactor, refactor, refactor.  I'm finding it's better to have developers simply spew code and then go back to refactor.  It's usually only with hindsight that we find out what needs to be "configurable" or "reusable" anyway.  You're right that in general too much time gets put in up front to try and figure that out.

In a team like ours, small, flexible, but overworked... (aren't we all), coding to interfaces makes things a lot simpler.  Even when we aren't sure if we necessarily need it, it doesn't involve a lot of upfront thought to simply create the interface and creates a good practice to follow for those times when it really IS needed.

We try and work in an Agile manner.  There is still a lot we need to do better.  It's not a matter of if you'll have to react to change, because it's a necessity almost daily.  It's a matter of how much effort is required to make change.  That said, there are two practices which we could and should do better which would help in this planning v. reaction area and those are test-driven development and design-by-contract.   You've said a lot, at least to me about test-driven dev.  Maybe you could talk a bit about design by contract?

Billy McCafferty wrote re: Planning for vs. Reacting to Change
on 09-21-2006 11:39 AM

I have that book sitting right in front of me but haven't read it yet...currently working on Javal Lowy's .NET Components.

Billy McCafferty wrote re: Planning for vs. Reacting to Change
on 09-21-2006 11:42 AM

Ah, design-by-contract, another favorite subject of mine! ;)  Sticking to design-by-contract principles has all but made the debugger obsolete in my day-to-day work...I'll be sure to post about that soon.

JMW wrote re: Planning for vs. Reacting to Change
on 10-02-2006 1:19 PM

Great article as usual Billy!

I think my tendancy towards "Premature Generalization" is currently due to me being a "learner" of all this. (but aren't we all though?)

Currently I want to do things the more general way (and often times more complicated) just to have a little bit of personal experience designing something that way.

But I definately see your point about not making things general when there will often times not be any use of that generalization.

And I see that the challenge is to be "Architecting Judiciously" and finding the appropriate balance for a project. (I like the word "judiciously", after all what is the symbol for justice? a balance right?)

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)