Peter Miller

in

Agile in Action – TDD Lessons Learned

As I continue to explore agile techniques at work, I had the opportunity to do some Test Driven Development, specifically Test First Development. The problem at hand was that our system is composed of several applications, all of which have various actions they have to take every hour or every day at a specific time. As the applications were developed, each application grew out its own time keeping infrastructure.

If you haven’t had the pleasure yet, working with time, dates and durations in .NET is not as easy as you’d like. It has gotten a lot better since framework 1.0, but it is still a great place for bugs to hatch. And not surprisingly, while each application was able to implement a system that worked most of the time, the code base was sprawling and behavior was unpredictable.

With the hindsight that comes after pushing a system to production, my team became convinced that we needed more then working most of the time, we wanted to prove that it worked all the time. Also, having abused the coding principle of (D)on’t (R)epeat (Y)ourself with multiple competing implementations we wanted to settle on one common implementation.

The approach we took was to throw out the old code, and first define an interface for our time keeper. Now it looks something like this:

 public interface ITimekeeper
 {
        event EventHandler HourChanged;
        event EventHandler DayChanged;

        void Initialize(TimeZoneInfo timeZone, DateTime dayChangeTime);
        void RegisterCustomEvent(DateTime time, TimeZoneInfo timeZone, 
					CustomEventCallback callback, object state);
        void Start();
        void Stop();
	...

	IClock Clock { get; set; }
}

Now is an important qualifier. We didn’t start out with the right interface, we took an educated guess and then started writing some tests. Importantly, and somewhat surprisingly to me, we got a lot of value out of just trying to write the tests themselves. It was a feedback loop as we’d try to write a test, find the interface clunky, refine the interface , write the test again and then move on.

We deliberately ignored the implementation at first and defined a reasonably wide set of tests that covered the basic functionality of our component. Then we subjected the interface to its sharpest critique by handing these tests off to another developer on the team and having him implement the code to make them pass.

In short, TDD drove our component level design to be more elegant, provided a natural way to break out tasks amongst the team, and of course provided us some confidence that the implementation would work.

I think I am taking a break from the bold prediction business, but this experience definitely has lead me to reconsider some of the points made over a year ago in this post of questionable origin:

http://blogs.claritycon.com/blogs/peter_miller/archive/2008/10/06/why-test-driven-development-is-a-hard-sell.aspx

   <--- A questionable dude…

--- Related Links ---

Hat tip to Philipp Sumi, who implemented a nice scheduling library of his own (which I found after I finished my efforts) and provided me some good feedback and insight on TDD.

http://www.hardcodet.net/2010/01/lightweight-task-slash-job-scheduling-with-silverlight-support

Also, for the eagle eyed amongst you, yes we do have an interface for the system clock, IClock. See Ayende Rahien’s post on why this seeming non sequitur can be useful:

http://ayende.com/Blog/archive/2008/07/07/Dealing-with-time-in-tests.aspx

Posted: Jan 16 2010, 07:46 AM by pmiller | with no comments
Filed under:

Comments

No Comments

Leave a Comment

(required) 

(required) 

(optional)

(required)