8

I try to understand better what the statement below means on Uncle Bob's TDD Harms Architecture,

"As the tests get more specific, the production code gets more generic."

Below is my understanding on how to get more generic on production code:

  • Using abstraction for method arguments, and return type, if possible
  • is there more on this?

What about test code?

Ideally, code example will help understand it.

1
  • @EricLippert, I agree ... so I removed the tags... ;)
    – David Arno
    Commented Jul 17, 2017 at 22:30

1 Answer 1

13

Let's say I try to test drive a calculator addition function.

Test 1:

public void Adding_0_And_0_Should_Return_0() { ... }

Production 1:

public int Add(int a, int b)
{
   return 0;
}

Test 2:

public void Adding_3_And_0_Should_Return_3() { ... }

Production 2:

public int Add(int a, int b)
{
   return a;
}

Test 3:

public void Adding_6_And_4_Should_Return_10() { ... }

Production 3:

public int Add(int a, int b)
{
   return a + b;
}

You can see the tests gradually becoming more specific (taken as a whole - by applying more constraints with each case), and as a consequence, with each iteration, the implementation ends up more generic, because a single implementation needs to handle an increasing number of specific test cases.

So initially your production code can only handle a single case where the result of addition is 1. Then with the second iteration you can handle a more generic case, where your first number can be anything you want, as long as you're adding it to 0. With the final case, you become completely generic, by being able to add any two numbers, not just the specific ones from the earlier tests.

19
  • 3
    @Eternal21, if you do, make sure you include a licence! FizzBuzz Enterprise Edition doesn't have one, so we couldn't use it. We had to employ 10 contractors for a year, sealed in an internet-free room, to write us our own version! Such a huge cost could have been avoided if they'd only provided a licence of some sort. :(
    – David Arno
    Commented Jul 17, 2017 at 17:06
  • 2
    @Giorgio Because one of the tenets of TDD is to do the simplest thing possible to get the test to pass. Returning a constant happened to be the smallest step to take there. Obviously this is a contrived example, but it's a good practice to follow, as it prevents you from making assumptions about how the final solution should look, and allows to arrive at it in small steps, flushing out all required tests in the process.
    – Eternal21
    Commented Jul 17, 2017 at 18:40
  • 2
    @Giorgio In case you find it hard to decide what the smallest step is you can consult the Transformation Priority Premise Commented Jul 17, 2017 at 19:31
  • 3
    @TimothyTruckle: And if you want to practice taking those small steps, Keith Braithwaite has created an exercise he calls TDD As If You Meant It. It consists of a set of rules (based on Uncle Bob Martin's Three Rules of TDD, but much stricter) that you must strictly follow and that are designed to steer you towards applying TDD more rigorously. Commented Jul 17, 2017 at 23:09
  • 3
    The problem for me is that TDD seems clear in these "toy" examples (though flawed. Why did you jump so quickly to using +, if you didn't already know this was the end goal?), and never for real-world examples. Please note you simply cannot generalize/derive + simply from writing a few examples and writing "the simplest code that would work", not even with Uncle Bob's "transformation" rules. I do not trust these toy examples, and have never seen a real algorithm -- i.e. one which is unknown from the start -- derived like this.
    – Andres F.
    Commented Jul 19, 2017 at 2:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.