What Test-Driven Development Has Taught Me So Far

Since the past year, I’ve been practicing the art of writing unit tests to help me drive a design before writing any code to support it. It came to my surprise that this practice, whether known as Test-Driven Development(TDD) or Behavior-Driven Development(BDD), has been used and preached by many leaders of our field for quite some time. In fact, Martin Fowler, a thought leader in software development for the enterprise and in his excellent book about refactoring, "Refactoring: Improving the Design of Existing Code", which was published in 1999 (almost ten years already), mentions the practice of testing your design with unit tests before writing your business or logic code. The fourth chapter of that book, entitled "Building Tests", is dedicated to promote this activity in your software development process. And guess what? It doesn’t even mention the "test-driven" word! Is this an easy route to follow or even to diverge from our comfortable and traditional way of writing code before even fully understanding a requirement?

"Of course, it is not so easy to persuade others to follow this route. Writing the tests is a lot of extra code to write. Unless you have actually experienced the way it speeds programming, self-testing does not seem to make sense. This is not helped by the fact that many people have never learned to write tests or even to think about tests. […] In fact, one of the most useful times to write tests is before you start programming. When you need to add a feature, begin by writing the test. This isn’t as backward as it sounds. By writing the test you are asking yourself what needs to be done to add the function." – Martin Fowler, Chapter 4 "Building Tests". An excerpt of "Refactoring: Improving the Design of Existing Code".

In my opinion and experience, the reason why TDD works is because it helps us to build correctly something that we don’t fully comprehend. This is especially true if the project domain is new to us, if we don’t have all the requirements set before us, if our experience in designing and thinking about software isn’t as broad as other experts, etc. Of course, we might have a general, high-level idea of what the application must do or should do, yet we don’t fully grasp the mechanics behind it. By mechanics, I also throw in the vision the software is trying to realize. Knowing what it must do or should do is a good starting point for laying a foundation on which the rest of the application can be built. Writing or thinking about unit testing helps to understand what the foundation should look like, and feel like, from the user’s point of view of our code. I tend to think it as paint artist drawing a painting. Most of the time, he doesn’t know immediately how to draw something very specific (a shape, a concept, an angle, a shade, etc.) and which exact color will be used to paint it. But, he sure knows what he wants to draw or what needs to be painted. It’s the same thing in music, in martial arts, in cooking and yes, even in software development. It’s the constant battle that goes on in front of a whiteboard, a sheet of paper or a CASE tool when designing and coding. Have you guessed it? The answer is pretty simple. It’s the battle between the what and the how. "What should this functionality accomplish versus how it should be implemented?" "What should this method expect versus how it should handle the expectation?" As a side note, I once heard that Linus Torvalds, the author of the Linux kernel, is an exemption to this reality. Apparently, he sees the code that needs to be written in his head and writes it; and if you tried to reverse engineer his code, it’ll produce a very solid design. Because there aren’t many Linus Torvalds within our organizations, we can look to useful, simple and pragmatic practices. Writing unit tests upfront helps me to drive a design that’s not entirely understood, but at a minimum, partially understood. It also helps me to bring forth changes to my design. In software development, these kinds of changes are known as refactoring. I highly recommend Martin Fowler’s book on refactoring to learn more about the patterns for effective refactoring. So what did the test-first approach to software development taught me so far?

  • It taught me that refactoring my work can be done in a much easier and safer way
  • It taught me that I would understand the design, therefore the application, much better if I see it through the eyes of someone who will use my code
  • It taught me that there is an ongoing battle in my head about knowing WHAT my class should do and HOW the code should do it. This sort of "mental war" is a good one to have, since it forces me to carefully think about various OO principles (encapsulation, relationships, inheritance, etc.) when designing and coding
  • It taught me that the old, traditional way of developing software (Big Design And Requirements Upfront) doesn’t work for every projects nowadays
  • The concept of testing is not the same as "verification", but rather points to a way of thinking about a solution (how can you verify something that doesn’t still exist?). And that solution is not absolute. It might be the seed to another and better solution. From my experience, this pattern is recursive.

In my next post, I’ll write about some tools and techniques which I use when writing unit tests up front, and which I hope will help you to better use TDD for your advantage. Until then, feel free to share your thoughts on the topic!

Recommended articles for this topic:

  • Dave Astels wrote a nice article about Behavior-Driven Design and how it compares to TDD. I think the principles behind his article have more weight than arguing about the naming of such practices. Check out his article about A New Look At Test-Driven Development.
  • Thought leader, Scott Ambler, has written a ton of articles about all things related to agile development and TDD. Two of his papers on TDD, Introduction to Test Driven Design and Quality in an Agile World, are highly recommended to learn more about this practice.
  • The Way of Testivus is a cool piece of writing from Alberto Savoia in which he shares some funny and smart remarks about unit testing in general.
  • TestDriven is a useful site about test-driven development in general (.NET, Java, etc.). Lots of news and awareness on this topic.
  • And of course, Google is your friend for more writings on this topic.
This post has been viewed: 2087 times. kick it on DotNetKicks.com

 

Similar posts you might be interested in reading:

One Comment

  1. Jimmy Bogard:

    Yep, that’s pretty much what I learned too :)

Leave a comment

Powered by WP Hashcash