Main Pitfall of TDD–Refactoring

May 27, 2013

Many people have bad experience with TDD. Their main complaints are:

  1. They spend too much time maintaining tests. For example, to fix a small bug or a small change in the production code they need to fix many tests
  2. Even though they follow the TDD practice and always write tests before production code, the production code doesn’t become so “clean” and SOLID.
  3. It’s difficult to write tests that cover all lines of code and all cases
  4. Tests need very long and complicated setups of mock objects
  5. The tests become a maintenance head-ache. Every small change in the production code leads to many fixes in test code
  6. And beyond all of that – there are still many bugs…

My observation is that in most of these cases, these people don’t really understand what the “Refactor” stage, in the well-known Red-Green-Refactor cycle, really means in the context of TDD.

Let’s look at a very simple example:

Does 1+2=3?

Consider we want to write a simple method that adds two numbers. Trivial, isn’t it?

   1:  [TestMethod]
   2:  public void AddTwoNumbers()
   3:  {
   4:      var result = Add(2, 1);
   5:      Assert.AreEquals(3, result);
   6:  }

When we’ll run the test, at first it will fail with compiler errors, clearly because the Add method is not defined yet…

After we’ll add it and see it fails (at the beginning we’ll leave the “throw new NotImplementedException();” statement that Visual Studio or Resharper creates for us), we need to write the minimal code that makes the test pass. Even if it looks ridiculous, let’s stick with the process “by the book” and do just that:

   1:  public int Add(int x, int y)
   2:  {
   3:      return 3;
   4:  }

Ok, so now we have a “green bar” (i.e. the test passes). What’s next?

Usually when I ask this question, the answer I get is “add another test with different numbers”. But wait – what about the “Refactor” stage?

The code is so trivial and simple (only “return 3”…) what refactoring could there be?!

Most people that are not used to the TDD style of work, think about the term “Refactoring” as something that is done every once in a while, takes at least 2-3 days which goes more or less like that:

  • During the first day the code doesn’t compile…
  • During the 2nd day, the code finally compiles but many tests fail. You’re going one by one trying to understand what you should change in order to make them pass (and if they’re still relevant whatsoever?)
  • Only by the end of the 2nd day/beginning of the 3rd day you start running the application to verify that everything works, make final fixes, merge with the latest changes and finally check-in (just to find that you introduce new bugs J)

So what’s “Refactoring” really mean in the context of TDD?!

Kent Beck, (who’s considered to be the “father” of the TDD technique), in his book “Test Driven Development by Example” clarifies the Refactor phase and call it “Refactor to remove duplication”. Let’s look again at the code, both of the test and of the method:

   1:  [TestMethod]
   2:  public void AddTwoNumbers()
   3:  {
   4:      var result = Add(2, 1);
   5:      Assert.AreEquals(3, result);
   6:  }
   7:   
   8:  public int Add(int x, int y)
   9:  {
  10:      return 3;
  11:  }

Do you see the duplication now? Yes, it’s very small and “harmless”, but this little 3 is duplication! And yes, the duplication is between the test code and the production code! In fact, duplication between test code and production code (if not properly removed) is a very bad “smell” as it implies coupling between the tested code and the code that calls it (which the test is one place).

Remove Duplication

So how do we get rid of this duplicate “3”?

In order to remove this duplication we need to ask ourselves: “where is this ‘3’ came from”? well, clearly it came from the test, because 2+1=3… so let’s replace it (only in Add method) to:

   1:  public int Add(int x, int y)
   2:  {
   3:      return 2+1;
   4:  }

But now we ended up with even more duplication! Both the 2 and the 1 are duplication between the test and the method. So let’s remove this duplication too!

   1:  public int Add(int x, int y)
   2:  {
   3:      return x + y;
   4:  }

And now we completed remove the duplication!

What’s duplication anyway?

Does it mean that every constant that I have in multiple places in the code are duplication? If I have the constant value “4” in 2 places in my code:

  1. To describe the number of wheels in my car
  2. To describe the floor number of my apartment

Is it also duplication?

The answer is “no”, because duplication is determined by the intent and not by the implementation. So in this case, because the value “4” represents 2 distinct concepts, then it’s not duplication and should not be removed.

This rule also goes to the other direction: If you have 2 different pieces of code that are completely different, for example, a bubble-sort algorithm and a merge-sort algorithm, they can still be considered “duplication” because they both have the same purpose. In this case, choose one and remove the other.

Other kinds of duplication

Duplication in code can wear different shapes, and sometimes it’s less obvious than in other cases. While the example above only showed duplication between test and production code, obviously it can be between different places in production code and even between 2 tests! Also, sometimes it’s more technical and sometimes (as in the different algorithms example) it’s more a conceptual thing.

But duplication can also “hide” outside of the main programming language code. The duplication can be between c# code and SQL code, XAML, XML, XSD, configuration file entries, etc. While it may be more difficult to “refactor” these things out, you should always strive to remove the duplication.

Only when you thoroughly remove duplication, wherever it may exist, you’ll really see the great benefits of TDD and resolve the complaints mentioned in the beginning.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

2 comments

  1. BeatyMay 27, 2013 ב 19:59

    There has never been a more fun way for kids to get fit,
    then to have designed routines that combat different areas of the
    body and this is what makes it work so well. I plan to do the Shakeology fast for at least everything you’ve tested out so far it is time to have a look at the how to p90x workout. Kids will never get bored because these workouts have all the things kids all over the world and there are certainly other new customers everyday.

    Reply
  2. RichardsonMay 29, 2013 ב 3:09

    Pretty section of content. I simply stumbled upon
    your weblog and in accession capital to say that I acquire actually loved account your
    blog posts. Anyway I’ll be subscribing on your feeds or even I achievement you access consistently rapidly.

    Reply