I started reading Kent Beck's Test-Driven Development: By Example over the weekend. Tim Bray mentioned the book a while back and his impression of TDD differed from mine so I figured I was overlooking something. Boy, I sure was.
I thought TDD (Test-Driven Development) was just development with a strong emphasis on tests. It's more than that. What threw me off was the word 'development' which encompasses the entire development process including design, implemention, evolution, etc. The core gem of an idea behind TDD impacts the design phase most heavily and it's uncovered in rather tedious detail by Kent Beck. Tedious yet startling is what I felt.
The simple idea is this:
Design software by writing tests first.
By 'software', I mean services, frameworks, modules, components, and objects.
Since tests are written before the module being tested is written, the experience of writing of the test drives the module's designing process. More importantly, you are looking at the API, of the module being designed, from the API client's perspective. Net result is higher quality API design.
While TDD during the design process is enough of a benefit for engineers to put into use immediately, TDD has problems because test cases are software and there are maintenance cost associated with them. Having a tool like Eclipse helps but much more is needed to help the engineers document the tests, keep track of them, and reuse as needed.
I think a visual tool that lets engineers drag and drop tests into test suites for various purposes like release testing, runtime testing, diagnostic testing is essential. TDD also encourages refactoring through out the development process which calls for more flexible source control system than CVS.
TDD Experience:
It ain't real until it's real so I put TDD into practice to write a small module. The experience is definitely different than the usual way of designing and implementing software. Deep thoughts are pushed to the background where it continues to churn while I am hacking and slashing in frenzy to make the JUnit bar turn green. Everytime the bar turns green, deep thoughts surfaced and I dutifully jotted them down before I dived back in. It felt very much like the way I felt while playing an intense video game.
To get started on a module, I just created a separate Java project using Eclipse because I could just drag and drop classes into the main project when I am done and Eclipse takes care of all the refactoring automatically. I then added an empty class which represents one of the objects in the module I am writing. No heavy thinking there. Just something to get started with and refactor later. I should have created a JUnit test case first, but it doesn't really make a big difference at this phrase.
I then created a test case for the classes and filled it in with a bunch of TODOs. Eclipse picks up those TODOs and populated the Problems view so I can easily keep track of all the outstanding tasks in this TDD run, sort of like the missions view in RPG games that lists all the tasks one has to perform to clear an area.
I replaced the first TODOs with code to instantiate the object and then made an method call. Eclipse flagged the line immediately because the method didn't exist. I clicked on the flag and selected a QuickFix command that told Eclipse to create the method. Wham. It's there ready to be filled in. Since I just want the bar green, I made it return a constant string value which should have been fetched from elsewhere. Back in the test case, I wrote an assert statement that checked for the value. I then rigth-clicked on the test case and selected Run > JUnit Test. Woohoo. I see a green bar!
This process was repeated at a furious pace over a couple of hours, during which I continue to added more TODO items and change TODO items into DONE status until there were all DONE. Through it all, Java classes and JUnit test cases were added, removed or refactored. In the end, I got a nice module with reasonably easy to use API and a set of test cases. Whew. What a workout.
Is TDD effective? I don't think it's for everyone just as not everyone enjoys playing video games. But it was productive for me. I got more immersed into the design than I normally would have and finished with a more polished end product earlier than I would have. Usually, I would render a first cut of a design and then sit on it for a few hours to a few days to get the kinks out. With TDD, I went through tens of iterations per hour. So the speed of development is definitely not a concern for TDD although I did feel a bit of adrenaline withdrawl symtoms at the end of it.
Will I do it again? You bet. I have to get to the next level, don't I? 🙂
Update:
I thought I should make it clear that I am not a proponent of TDD and I am not recommending it to everyone. TDD is just a new tool I am adding to my bag of tricks because I find it useful and I enjoy the experience. As I wrote above, I don't think everyone will find TDD useful. It's up to you whether decide to try TDD or not. If current style of development works for you, I don't see why you should look for something else.