Pain And TDD

“We were doing TDD just like we’re supposed to, but at some point it started hurting, so we not only quit, we told everyone else on the interwebs that TDD doesn’t work.”

I met Kent Beck after a couple of years reading and writing around him, at the first ObjectMentor Extreme Programming (XP) Immersion, a wonderful week I’ll never forget, where I met so many awesome geeks and coaches. (Kent Beck, Mike Feathers, James Grenning, Bob Martin, Ron Jeffries, Martin Fowler, and more! You get the idea it was a special week?)

And Beck, answering a question, told the old Smith & Dale joke:

SMITH: Doctor, it hurts when I do this.
DALE: Don’t do that.

(The visuals include a funny wagging arm movement by Smith.)

Don’t Do That!

I chuckled. It was merely years before I grasped the deeper level of this old joke.

One might interpret it as saying “TDD hurts me, so I won’t do TDD,” but that’s actually the wrong way to interpret the joke.

You see, TDD works for some of us. And it works very well.

But it’s really important that you hear what I’m not saying.

I’m not saying that you didn’t — or aren’t — feeling pain. I’m not saying you weren’t — or aren’t — trying. I’m not saying TDD works for us because we’re smart and you’re stupid. 

What I’m saying is that you are not responding to the pain you’re feeling in the TDD way.

Pain Means Something Is Wrong

TDD is not painful.

I don’t mean that it’s not painful in the sense of “you’ll just feel a little pinch”. I mean it’s not painful at all, really.

So when we feel pain while doing TDD, something is going wrong.

The somethings that could go wrong are exactly three:

  • You are working in legacy.
  • You are learning.
  • You are working with code that needs refactoring.

That’s it. There are really no other situations where TDD should be causing pain.

Legacy Pain

TDD can leverage you out of legacy. I’ve done it. But working in legacy is just painful.

The key to successful legacy work is to become a master of extraction refactorings. Before you TDD a change, extract the change site so that it is optimal for microtesting.

When you can’t write a real microtest because of the location or accessibility or complexity, either move, extract, or simplify the code via refactorings. It’s not hard, but it’s tedious as hell, and it takes a certain boldness.

This will help. It will ease your immediate TDD pain, and it will — very gradually — lift you out of legacy work altogether.

But yeah. Legacy hurts for as long as it’s legacy, and there are not two ways about it.

Learning Pain

Most of the time, learning is a source of great joy to us. After all, we’re geeks. That’s what we do, is learn things and delight in them.

But there are some situations where learning hurts. Most of these are situations where you have to learn something while 7 people are shouting at you that if we don’t fix this we will simply all die. Let me tell you, that’s gonna hurt no matter what you do. Suggesting, of course, that we teach people not to do that.

There’s another time when it hurts. It hurts to learn when your current goal is too far over your head.

I have worked from time to time with folks with weak TDD, weak confidence, and weak knowledge of a language or a domain. That’s a painful combination.

If you are stuck at the incantation stage in a language, where you’re just barely avoiding syntax errors, and the fundamentals of the language are not yet within your grasp, it’s sore tempting to drop TDD altogether and just focus on typing the magic in correctly.

But it’s contraindicated. The reason TDD is a great design technique is because it organizes the design. That organization, plus simple extended exposure, is going to be the thing that ratchets your knowledge up most rapidly. Abandoning TDD will slow down your learning, not speed up.

Code Pain

Ahhhhhhh. Now we come to it.

I have a strong belief that code pain is the main reason people leave TDD behind.

And here’s what they’re doing wrong: gritting their teeth and trying to play through it.

That’s not the TDD way. In TDD, when we feel pain we change the code until we don’t feel it anymore. And we add what we’ve learned to our daily codesense.

Codesense isn’t one trick, it’s a thousand. And it isn’t an algorithm. Codesense comes into play at large scales and at smalls. But it all comes from feeling pain and resolving not to feel it any more.

Coming soon to a blog near you: live-action codesense examples, where pain leads to refactoring leads to new design.

We don’t play through the pain in TDD.

We use it to change our behavior & build our codesense.

Codesense: The Basis of Successful TDD

Okay, so, I’ve been a little grumpy lately.

But of course, it’s not enough to just shout at people who think TDD doesn’t work.

It must be a big weakness of our pedagogy that so many people feel that way. So I ask myself, what are we not teaching, or not teaching enough of, or not enough of us teaching?

Given the descriptions from the unfortunates who tried not-TDD under the guise of TDD, it seems clear we’ve under-emphasized the means by which the process detects flaws and forces code change.

(In one sentence, I’ll describe TDD as a process. You can go back all over this blog and to get details.  The TDD process is a matter of deciding what to change, forcing that change using one or more microtests, and concurrently optimizing the design by using your sense of the new friction, coupling, and general infelicity of the code that works.)

Wait. There it is.

Codesense Is Critical

TDD was created *by* geeks of a very high caliber. But it was created *for* all geeks, of any caliber. The result is that whole swath’s of technique have been somewhat assumed, when such assumptions were ill-warranted. To be clear, many folks have contributed much wisdom, but that wisdom is insufficiently studied and taught.

I will tell you now, as I’ve said before in the context of advocating microtests and microsteps: TDD will not work without good codesense.

Codesense is the developer’s basic sense that a given chunk of code is or isn’t optimal.

It’s how we know we’re coding well or less well.

I say the word ‘optimal’ like we’re supposed to already know that that means. The fact is there are bazillions of definitions of code optimality. Many of them capture all or part of what I mean, but others capture little or nothing.

Codesense is like common sense in three ways:

  • it’s incredibly difficult to teach;
  • once learned it seems obvious;
  • it’s noticeably uncommon.

Judgment Is The Keystone Of Codesense and of TDD

I’m gonna go off-track for a moment to make one really important point: there is no algorithm for measuring the goodness of code.

Converting codesense into mechanism is a mug’s game, but it’s been ridiculously common in the industry, and still is. There are dozens of applications you can download, buy, or liberate that purport to identify “code goodness” categorically. Some have great ideas, but they don’t really work.

If I could tell every developer — and consumer of developer services — in the world just one thing, it would be this: people write code, not computers, and that is because individual human judgment is required.

In software development, we are permanently, irrevocably, irremediably, and happily, dependent on individuals using their individual judgment.

Maybe the biggest consequence of this dependence: there are very few fixed rules in assessing code.

Codesense Changes Over Time

What rules we do have frequently change. Nothing anyone said ten years ago should be taken as for-granted truth. Nothing. The game changes too often for that.

To take a straightforward case: structured programming, and there are many many people in our field who were raised on structured programming, says that every method should have exactly one entrance and exactly one exit.

The modern synthesis is different. Nowadays we’d write this code like so:

Is the difference important? I’ll re-use a sentence I wrote nearly ten years ago:

“To a professional, *everything* counts.”

Getting Started

So, this is my first blog about codesense, but I guarantee it won’t be my last. And now that we’ve met the creature in the abstract, let’s get down to brass tacks.

Codesense is hard to teach, but it’s not that hard to learn. It starts with heightening your sensitivity to code.

I can readily recommend all of these books:

It’s important to understand: I’m not telling you to do everything these guys tell you to do. It’s not about getting an instruction book.

I’m telling you to *think* and *observe* and *notice* the code you write and what happens to it.

What’s worth noticing? What’s worth changing? How might you change it? These books and others will help you get your mind open to codesense.

Once that happens, it’s time to start looking at your daily existence as a software geek. There is no substitute for this work. The folks above are top-notch writers and thinkers about programming. They can help you learn how to judge. But the judging will still be yours.

One last thought.

Start Today, With Pain.

Notice Every Pain Code Brings You