How TDD and Pairing Increase Production

"Test-driven Development" and "Pair Programming" are two of the most widely known of agile practices, yet are still largely not being practiced by many agile teams. Often, people will cite being "too busy" to adopt such practices as TDD and pairing; in essence, implying that striving for high code quality will reduce productivity. Mike Hill explains how this logic is seriously flawed.

Not only is it not true that you can trade internal quality for more features, it’s actually the exact opposite case: the more productivity you seek, the higher you should raise your standard of internal quality.
...If you want more production, look first to raising your internal quality.

And then he tells us why:

So, how can such things be?

Because internal quality and external quality are not the same things.

Because the biggest single determinant in today’s production is the quality of yesterday’s production.

Because typing is not now and never has been the bottleneck in writing code.

Mike follows by expanding on these three reasons. First, he clarifies the word "quality" to distinguish external quality, which can be thought of as the amount of features in your product, from internal quality, which refers to the code that is behind those features. He makes this distinction to note that while external quality can be lowered to shorten time-to-market, internal quality cannot.

All day long, every time you make a move, you will be depending on the code that’s already there. Every line of it you have to study will slow you down. Every extra open dependency will slow you down. Every bad variable name will slow you down. Every flawed design decision, be it big or small, will slow you down.

If you want to work as fast as you can, you want to work with clean code. Period.

Finally, Mike takes on the common misconception that pairing and TDD decrease throughput (productivity) because you'll have [this author's words] "half as many people typing half as much production code". He gives a list of 11 common activities that occur when someone "codes", then has this to say:

Notice that writing code into the machine occupies only a very small portion of this list. That’s because the hard part of programming is the thinking, not the typing. Everything else on that list (except possibly the throwing stuff) is about thinking, not typing.

TDD increases your production because it serves as a thinking-aid. It limits back-tracking and gold-plating and it reduces code-study and debugging. Pairing increases your production for the very same reason. Two developers together don’t type as fast as two developers separately, but we don’t care: the bottleneck is the thinking [not the typing], and pairing and TDDing both improve it.

So, Mike's first point highlights that we in the software industry cannot safely say the word "quality" (by itself) and expect all audiences to hear the same thing we do.

Namely, as Mike touches on, we often confuse 'quality' in the scope, customer-facing sense with 'quality' in the clean-code, programmer-facing sense... and in the end the programmer-facing 'quality' gets the short end of the stick on our software projects.

This was the fundamental topic of my "Killing Quality" article from a little while back, you might find that a useful related read as well.

But what is usually not clear is how. Most people have a hard time grasping how on earth TDD (very specifically, not just any kind of test). Whenever I make the point on selling TDD to people I end up actually talking about some of the hidden concepts behind it (most of spelled by Kent Beck):

* Simplicity: when you write the test first, you can much more easily avoid over engineering, making simpler and smaller code (better production in speed and cost)* Requirements become clearer faster: you focus on what you need to do, and reflect upon this, taking out much of the risk on doing things that the client does not need, or that the client did not realize that needed a little more thought.* Documentation: TDD foments tests as docs, as the requirements are tackled much earlier, and the implementation details do not blur the whole view.* Tests: (I know, quite obvious) you get a test suite. Which helps you with migrating underlying architecture/infrastructure/libraries, and even adapting to change. Also ensures that the software is working as intended as more features are added.

Pair programming can go extremely well with TDD (with great synergy) as well on the style Ping pong pair programming. But pair programming alone also does increase productivity, but making the case for it deserves a post in itself.

I'll have to disagree. As an example, just today I was forced to work alone trying to wade my way through the creation of an Eclipse Plugin that, among other things, can launch a particular Java programs. Sounds straightforward enough, eh?

Well, the entire day was a rather frustrating struggle - one that, in retrospect, I am absolutely sure would have been WAY more productive had I pair to bounce all my experimental ideas off of, to stop me from going down some very stupid paths, to help me remember all the things I had learned along the way, and more.

A prime example of "coding is 80% thinking, 20% typing", no matter how good you are.\

Which I tend to disagree with, since I'm not sure how you can pair program without TDD. Though your example, Mike, makes me think about pairing on a non-programming task such as configuring a development tool. On that kind of task, pairing could create major improvements in efficiency. Maybe I just haven't thought it through all the way.

Exactly. Pair programming with one person is possible, but it is only an alternative to some very people.

Which I tend to disagree with, since I'm not sure how you can pair program without TDD.

It can bed done, mostly on tasks such as configuration and environment setup (which is not technicaly programming, but pairing helps a lot here as well), doing regression integration tests, and even adding features on a non TDD fashion (I think this is possible, it is weird, but it is possible).

Of course, this is suboptimal, as TDD and Pair Programming have great synergy. But so other engineering practices, such as continuous integration, coding standards, collective code ownership, sustainable pace, etc. The point is: they don't have to be all implemented in order to be able to get production gains.

Okay, I'm sorry, I read Daniel's comment as "Pairing alone does NOT help" - which is why I disagreed. Sorry Daniel (and other readers for confusion).

So, Daniel, I agree with everything you've said.

Björn, while I think TDD and pairing are very much a natural fit (each improves the other), I would not go as far as to say you cannot pair without practicing TDD. Whether it's a "config" task or a "code" task (BTW, my example involved both). Making a computer do things (ie. "programming"), no matter what tool you might be weilding, is a dirty job, one that takes continuous thought - and pairing is about improved thinking, which is the ultimate point of Mike's original article.