Your Design Is Broken: It’s TDD, not TDYAR

Think about your last huge unrequited crush.

A real one, I’m talking. A crush so big you go to sleep thinking of your future together, and wake up, ummm, guilty. The kind of crush that great romantic stories are made from, and for. The wobbly-knee’d kind.

And a complete non-starter: when I say unrequited, I’m being clinical in an effort to minimize the likelihood of breaking out into laughter, as doctors and nurses in every ER around the world do.

Now, in that kind of crush, you have a vision, and that vision is glorious beyond compare. It captures entirely your ideal notions of successful love. I’m not going to ask you to describe it. In fact, please don’t describe it. I have sensitive comment readers here. But picture that imagined future, just for yourself.

Was it magnificent? Brilliant? A tale for the ages?

I’d bet it was all this and more.

In fact, there’s really only a single flaw in that entire vision.

That Future Romance Is In Your Head

That tremendous romantic vision is just that, a vision. And when it came time for that blueprint-for-love to hit the shredder we call real life, it just wasn’t up to the challenge.

Thus with your design.

You see, your design lives in your mind, like your romantic vision. Oh, it may have slightly more contact with reality, because, after all, I still can’t believe you thought that — never mind.

And, notice, I’m not suggesting you’re not the greatest software designer in known space. My point in no way depends on you being a sub-par designer. Surely, you’re not a sub-par designer of romantic visions for you, are you? Far from it.

Codeless Designs Are Relatively Worthless

A design in your head elides all messy details, tricky complications, and inevitable exceptions.

A problem your company wants to solve never does.

So how do you cope with this divergence?

You code up your design, and as the working code begins to implement the design in your head, you keep an eagle-like watch out for its inevitable infelicities, and you change the code — and your design — until it is still working and no longer has its problems.

That’s what TDD does. A sketch of a design leads to rolling some microtested working code which is re-designed in microsteps. Red. Green. Refactor. Commit.

Design-In-Head Vs. Design-In-Working-Code

When your starting design meets the emerging design that comes from repeatedly applying the TDD process, there will be clashes. Thankfully, most of them aren’t as bad as that great unrequited love. But, on the record, some of them are.

When it happens, which design is right?

The one in the working refactored microtested code is right.

Your Design Is Broken

That’s hard, but you have to let it go.

Use a mental design to work your way into the code using TDD, and your broken design will become a masterwork of productivity. Ignoring the code’s design in favor of the mind’s, and you will pay a great price, starting tomorrow and lasting until your company inevitably goes out of business.

People rail against TDD.

A great many of them are refusing to confront this basic clash of designs, and they just can’t let go of their mental construct in favor of their silicon one. (The most recent such, from the famous @DHH, reeks to me of this.)

And that explains for me a large amount of TDD criticism, and an even larger number of failed TDD adoption efforts.

If you think TDD is supposed to work w/o changing the shape of your designs, you have missed the point. It is not surprising to me that you find yourself hating TDD.

I see a lot of “TDD and my design clash, therefore TDD doesn’t work”. I’ve seen even more of it lately.

TDD Is Test Driven Development,

not

Test Driven “You Are Right”

One Page Intro To Microtests

A microtest has the following properties:

  • It is short, typically under a dozen lines of code.
  • It is *always* automated.
  • It does not test the object inside the running app, but instead in a purpose-built testing application.
  • It invokes only a tiny portion of the code, most usually a single branch of a single function.
  • It never *reaches* inside an object’s boundaries, though the tester may certainly *look* inside them.
  • It is coded to the same standard as shipping code, i.e. the team’s best current understanding of coding excellence.
  • It is vault-committed source, with a lifetime co-terminous with the functionality it tests.
  • In combination with all other microtests of an app, it serves as a ‘gateway-to-commit’.  A developer is encouraged to commit anytime all microtests run green.
  • It takes complete control of the object-under-test and is therefore self-contained, i.e. running with no dependencies on anything other than the testing code and its dependency graph.
  • It runs in an extremely short time, milliseconds per test.
  • It provides precise feedback on any errors that it encounters.
  • It usually (not always) runs entirely inside a single computer.
  • It usually (not always) runs entirely inside a single process, i.e. with few extra-process runtime dependencies.
  • It is part of a collection all or any subset of which can be invoked with a single programmer gesture.
  • It is written before the code-change it is meant to test.
  • It avoids most or all usage of ‘awkward’ collaborators via a variety of slip-and-fake techniques.
  • It rarely involves construction of more than a few classes of object, often one or two, usually under five.

 

We’re In This For The Money

(When I’m teaching and coaching, I have a number of themes that I discuss and that will show up somewhere in everything I do. Here’s the money theme, which I usually bring up at the earliest opportunity.)

Look, kids, we’re in this for the money.

Somehow you got the idea that TDD, pairing, micro-stepping, and refactoring are not about increasing your productivity.

It could be the misguided craftsmanship movement, who give you the excuse to say “we don’t have time for art.” Or maybe you heard it from nay-sayers who are against these notions from the get-go. Maybe you read stuff from the early days, when we still didn’t understand that internal quality was such a huge determinant of success. Or, worst of all, some of you heard it from people who are in favor of these ideas, but get lost in the thick of things and say stuff they really should know better than to say.

It doesn’t matter how you got the idea, though. The simple fact is it’s entirely untrue.

TDD is in every respect about increasing software development productivity.

It is not about craftsmanship or art or beauty.

It is not about being a good citizen.

It is not about taking some illusory long view instead of the short.

It is not about you being a better person.

It’s not about improving quality.

It’s about money.

Do you want to make more money? Does your company want to make more money?

There are various goals you could aim at to do that. Maybe you need to ship more quality. Maybe you need lots more features. Maybe you need a whole new approach to the problem.

Funny thing, though. No matter what your target is, or even what time-scale it lives in, you will get there faster if you are more productive.

Driving with microtests increases productivity.

The microtests do a number of things to make us faster. See my articles on how TDD works its magic, for the many cases:

  • They multiply developer intentions, which provides a powerful “online” memory.
  • They demonstrate with a flick of the wrist that a change you just made did not hurt anything.
  • Their blinding speed far exceeds any other means of feedback in utility.
  • They *force* us to work in small objects with small methods.

In a single phrase? TDD increases productivity because the hard part of programming is thinking, and they make thinking faster.

Pairing increases productivity.

This one’s been demonstrated so many times its not funny. Pairing — at a real pairing station — has the following impacts on productivity:

  • Pairs find dumb-assed syntax errors faster than solos.
  • Pairs find *shared* language for programmer intention, the most subtle and elusive part of the primary task of programming, which is understanding the code in front of you at a  glance.
  • Pairs share energy back and forth, which means they can focus on a single task for far longer than solos.
  • Pairs are more fun. (Okay, that’s not about productivity. Fine.)
  • Pairing is the most efficient mechanism for knowledge transfer.

In a single phrase? Pairing increases productivity because the hard part of programming is thinking, and they make the thinking go faster.

Refactoring increases productivity.

The reason this one’s so hard for the noobs to get is that they haven’t yet understood that the code-to-which-you-are-adding is the single biggest determinant of the speed with which you add. Continuous micro-refactoring provides these benefits to productivity:

  • They render the code-base smaller. Smaller = less to grasp. Less to grasp = faster to change.
  • They reveal intention, which is the hardest part of code-grasping. Not, “what does this code do”, but “why do we want this code to do this”.
  • They continuously improve the overall design, including performance, of the code.

So, you know, in a single phrase? Refactoring increases productivity because the hard part of programming is the thinking, and they make the thinking go faster.

Micro-stepping increases productivity.

We do all of our work, testing, designing, refactoring, really *everything*, guided by one simple question: “what’s the smallest interesting step I can take?” And we do this because micro-steps improve our productivity in these ways:

  • They mean smaller scope, meaning fewer independent concepts, meaning easier reasoning.
  • They make most bugs emerge in those same small scopes. Time debugging is dramatically reduced.
  • They provide readily testable and trackable change. Continuous change is faster than chunky change.

Oh, in a single phrase? Micro-stepping increases productivity because the hard part of programming is the thinking, and micro-stepping makes the thinking go faster.

In The Beginning…

The only time these activities slow you down is in the beginning, when — guess what — you’re still learning their basic mechanics.

Here’s the deep dark secret: working this way is not how you learned to work. How you learned to work was either on-the-job-under-the-gun or buttressed around with perfectly reasonable theories that have no bearing on actual successful practice.

Learning to work this way is hardest for skilled geeks: they have a lot more practice to unlearn. But they’ll also have the biggest productivity gains once they get it.

Step Zero? Set up a decent comfortable pairing rig and invite experts to come and play. They’ll come. Pairing is the beginning, not the end, of this technique.

Learn Your Damned Trade

Too busy to TDD?

Too busy to pair?

Too busy to refactor?

Too busy to micro-test?

I call bullshit. My buddy Erik Meade calls it Stupid Busy, and I think that nails it pretty well. All you’re really saying is that you’re too busy to go faster.

We’re In This For The Money

So Stop Screwing Around And Start Going Faster

Welcome to GeePawHill.Org

monkeyHello, folks, and welcome to my new blog!

In many ways, this is a continuation of my former work over at http://anarchycreek.com, which you should take a gander at if you want to know where I’m heading.

This blog is about three topics, usually intermingled herein;

  • Programmers — People who create software for a living.
  • Code – the actual stuff that programmers write.
  • Thinking — the part of programming that is the hardest.

That’s it, for now, but my next steps are to move the DoubleDawgDare series here, finish it, and launch a new one.

Enjoy, and comment, and subscribe, and write me!

Sincerely,
GeePaw