Tuesday, February 05, 2008

I recently listened to an interview between Rob Sanheim and Zed Shaw recorded at RailsConf. The podcast can be found in its entirety at Ajaxian.com (or direct link). Zed said a load of stuff during the interview but the thing I want to blog about is a statement that Zed made about the value of doing TDD.

Near the very end of the interview Rob asked Zed if he develops his software test first. Zed told Rob that he uses a development method that he created based on the principles of CMM from the SEI. Zed then offered Rob his thoughts on TDD. In the interview Zed said, “It doesn’t matter when you write your tests because they are just a measurement of the current quality of the system.” This is a statement that I have heard before and is the core belief at the center of the “Test After” myth. Zed goes on to say, “Tests don’t improve the quality of what you have. Tests just maintain whatever quality you have.” This is another frequently referenced tenant of “Test After”.

The comments made by Zed (referenced earlier) lead me to believe that Zed has not used TDD extensively. As a hardened TDD developer I can tell you that the process of creating tests as a driver for writing code does improve the quality of your code. I have been writing software for approximately 20 years (14 years professionally). I have spent the last 4 years of my life developing software test first. As a result of the success that I have had with TDD I will never go back to a "Test After" process.

In this article I will demonstrate that TDD will help you produce higher quality code than a "Test After" development approach. If you are reading this you probably already agree with this assertion. So I can only hope to empower you to share this information with the non-believers around you.


The Red-Green-Refactor Cycle

The Red-Green-Refactor cycle is at the heart of TDD. In its simplest form it works like this:

  1. Write a failing test
  2. Write the code to make the test pass
  3. Refactor the code to improve the quality, remove duplication, etc.
  4. Repeat
The process of writing a single failing test, making that test work and then cleaning up the code is incredibly powerful. It allows you to gradually introduce new capabilities into your software while ensuring that the code you are writing works and that your new code or changes to existing code haven't broken anything else. Additionally, it allows you to go incredibly fast because you aren't worried about breaking other parts of the application or if what you are doing is actually going to solve the problem. You have the comfort of knowing that when you run your tests you will instantly know if you have solved the failing test and if you have broken any other tests.

Refactoring
What's better than being able to write your code fast without having to worry about causing hard to identify problems in other parts of the application? I'll tell you what's better, being able to do all this coupled with the power of refactoring. Refactoring allows you to step back from the code that you just "banged out" to make the test pass and it allows you to improve that code and/or other code in and around your code. This is where TDD really shines because it is the existence of the tests that allows you the freedom to refactor. As Zed points out in the podcast, every new line of code or changed line of code you touch has the potential to introduce a bug. The tests give you the courage to change the design of the code, reorganize things, simplify the code, etc. because you will know immediately if what you have done has introduced any problems.

A Finite End State
A working test is a very finite end state. Using tests to drive your development can be helpful in eliminating that infamous "IT Gold Platting" that Fred Brooks has warned us about. If you have written a series of tests to implement a feature and there are no new facets of that feature requiring a test then you are done and it is time to go on to your next task. Developers are notorious for fiddling with things until they are perfect (or perceived as perfect in their mind). Giving a developer a finite end state can really help the developer move on the the next task at the appropriate pace. The additional benefit here is that you often get the simplest solution that satisfies the requirement. This is a plus because things that are simple are easier for others to pick up and maintain.

Myth Busted

With all respect to Zed and his personal approach to software development, I think we can now call this "Myth Busted". The benefits of TDD offer so much that you don't get with a typical "Test After" process. If you have other examples of the benefits of TDD or if you disagree with me, let me know by posting a comment to this article.

1 comments:

Anonymous said...

I think you are believing that most developers are going to be able to refactor a pile of test-driven development into a well-designed and reusable OO system, when in reality you are probably hamstringing them into keeping some structures written so that a test will work. I do not have examples off-hand, but I would challenge that some design patterns will not be facilitated by TDD.

Subscribe to RSS Feed Follow me on Twitter!