Friday, March 21, 2008

Test Driven Development in the Time of Dragons

Well, the office is abuzz with excitement over TDD. I could not be more pleased! I am genuinely happy that we are actively moving toward embracing developer testing across all of our applications. I started this job seven months ago with the goal of introducing continuous integration and developer testing to the group, and through the efforts of myself and others, that day has definitely arrived. My next goal is to get our development and business stakeholders to embrace Agile project management. I think the path towards that goal is through developer testing. We are starting out on a new project now spanning multiple applications, and we have unit testing built into our development plans. That’s something to be truly excited about. But beware: There be dragons here!

The Waterfall Dragon Achieving widespread adoption of TDD in our office is still an uphill effort though. Our main obstacle is our current project management process: waterfall. In the minds of our business stakeholders (and many of our technical stakeholders), the way you create software is a four-step process: 1) Make all your decisions, both business and technical, up front. Include a decision on when the software will be delivered. 2) Have the development team go away for a few months and build something. 3) Get back together at a pre-determined date to compare what was built to a specification which is now out of step with what the business really needs. 4) Whip the development team for getting it wrong, no matter how much overtime they worked, and then release the product anyway. The waterfall process doesn’t really lend itself to an iterative, collaborative approach focused on coding business rules in testable code. And our business stakeholders (and many of our technical stakeholders) do not yet grasp the idea that a working suite of tests is a very valuable deliverable. Ideally, we would work directly with the business stakeholders, building the application up by delivering multiple small releases, each focusing on a very small set of features. Instead, we’re trying to cram some XP practices, TDD and continuous integration in particular, into a process that just wasn’t built to accommodate them. I don’t want to sound cynical though: I’m thankful we’ve at least been given the green light to use a test-driven approach in this project. I think over time, as our test suite grows to cover large swaths of our code base, we will be able to prove to our management that it will be much easier to accommodate changes, or at least that we can determine the impact of those changes much earlier than without the test suite. With a healthy code base, we’ll be in a much better position to embrace Agile development. The Legacy Code Dragon I think our second biggest obstacle is legacy code. Our code base stretches back through time, several years in some places, to a time when .Net development was still very new, and almost no .Net developers had even heard of automated developer testing. Code which seemed perfectly reasonable when it was first written has grown a bit gangrenous with age. So we’re starting out saddled with untestable legacy code. In this new project, we will create code we will share among a few applications, and we’ll make changes to those front-end applications too. We will test as much of our new code as possible, and we will learn how to deal with untestable legacy code along the way. Now the TDD fans among us have varying amounts of experience with test-first development, but no one is a TDD black-belt yet. Some of us have had exposure to TDD at previous gigs, and we’ve all read books, tried samples, attended code camps, and learned some very helpful techniques. But most of the code camp-style TDD presentations that I’ve seen assume the developer will be writing a new app from the ground up, with a completely supportive Agile process to nurture it’s growth and success. We need some advice on how to work TDD into an organization and a code base which have been around a while. Toward that end, I just ordered Working with Legacy Code by Michael Feathers. In the meantime, we’re starting by keeping Jeremy Miller’s First Rule of TDD in mind: “isolate the ugly stuff.” (By they way, if you haven’t read Jeremy’s blog, what are you doing here? Stop reading this drivel, and go read his stuff now.)

Next time, I’m going to look at designing and coding a user story in a legacy app.

No comments: