The “How I Work (Test-Driving Mix)” drew some questions and comment.
Here’s one: a respondent says, “If I write a lot of small tests and I change how a feature works, I have to change or throw out all those microtests, which is a lot of work.”
(The respondent proposed an answer for this problem, and it’s not a bad one, but raises some other questions we might get to later.)
The one-liner response: “For me, it’s *significantly* less work to do that than to work in any other way I’ve tried to date.”
I’m not gonna stop with the one-liner, cuz this is actually pretty important and we need to work it out in some detail.
I’ve written a lot about five underplayed premises of my TDD. These are kind of “baked in” parts of my approach, and that of at least some other TDD’ers. They’re really important, but they’re also frequently “underplayed”. We don’t feature them enough in our pedagogy.
We use them day in and day out, and think nothing of it. And “before TDD”, they make little sense to others, but “after TDD” they’re almost invisible to us, because they’re the very air we breathe. They’re underplayed because once you’re a TDD’er, you take them for granted.
The first of my five underplayed premises is The Money Premise, and it goes like this:
“We’re in this for the money.”
I do TDD because doing TDD lets me ship more value faster, and shipping more value faster is how I make money.
And I need you to hear me: this is not my theory, this is my direct and actual experience:
When I do have microtested TDD available to me, I add value more quickly. When I don’t have it available to me, I add value more slowly.
Do I *have* a theory?
Oh for crying out loud, of course I have a theory. What kind of fat old bearded geek grayhair would I be if I didn’t have a theory?!?
I have a theory so big that it actually reaches far beyond the realm of programming for money, and into the higher reaches of generically harvesting the value of change, no less.
Hmph. “Do I have a theory.” The nerve of some people.
Gotta have a theory in a case like this, because the data — anecdotal for you but incredibly real for me — is anomalous. When I first began TDD’ing for keeps, I started producing results for myself that, not to put too fine a point on it, didn’t make any sense to me.
The anamoly, expressed snarkily:
Spoze I write 100 lines of production code a day. TDD says write microtests, also code, at ratio around 1 to 1. That means now it’s only 50 prod & 50 test. Therefore, TDD must be less productive.
QED, friends, because *math*!!
I hasten to say: it’s not always expressed rudely. In fact, the logic there is so common to the programming trade, even a cheerful TDD’er, a perfectly receptive audience, can fall right into it. It’s implied, for instance, in respondent’s original comment, above, from a friend.
I’ll go ahead and give the snarky reply anyway: “How the hell did you find a job where typing 4 words a minute that pays $80K? *I* want that job.”
(100 lines of 80 characters divided by the standard 5 chars per word and 420 minutes a day.)
And in the shocked reply, “There’s more to being a programmer than typing,” we can already see the theory of how TDD makes me ship more value faster than non-TDD.
Okay, let’s de-escalate. 🙂
I have this experience — to me it’s data, but I’m not here to argue that today — that I ship more value faster when I TDD. Basic math doesn’t account for this, so I need a theory that *does* account for it.
The one-liner of the theory: My TDD trades a *cost-increase* in the amount of code-editing involved in programming for a *cost-decrease* in a number of other activities that are also involved in programming, to produce an overall significant improvement in my productivity.
I want to list these cost-decreases, but before I do, I need to draw your attention to the operational/artifactual distinction.
It’s common, and sadly it is often taught, to believe that TDD gets most or all of its value from the artifacts, the text that makes up the tests. I actually get a huge amount of my value from the behavior, the many things I do while *creating* the text that makes up that value.
There are benefits to the artifact, but I don’t believe they’re sufficient to justify TDD. If they were, then large-scale tests would be more valuable, and auto-generated tests would be more valuable. Neither of those have been my experience.
Reminder: this is my microtest TDD I’m sepaking of. I write short, precise, descriptive, fast, grok-at-a-glance, executable demonstrations that what I said was what the computer heard was what I meant, and I do it interactively, one microtest at a time.
In no particular order, and with some overlap, here’s the cost-decreases. Things I spend less time, energy, and stress on, when I can work in a full microtest TDD way.
- It costs less to think because the microtests structure progress in small steps. Each step involves only a very tiny slice of function, with fewer mental entities. If I think of problem-solving as juggling, this equates to “fewer balls in the air”, so I do it faster.
- It costs less to worry about risk because the microtests form an executable demonstration that everything I thought was true *before* a change is still true *after* the change.
- It costs less to store up juice, because microtest TDD is a sequence of “green to green” steps, and each green gives me a positive dose of energy. (Think of me as a rat pressing a lever and getting a food pellet.)
- It costs less to make strong OO designs, because the microtests value all the same things good OO design does, things roughly encapsulated nowadays in what we call the SOLID principles.
- It costs less to find out if a change I made had the desired effect, because microtests are executed in a custom program that is *not* the shipping application.
- It costs less to debug my WIP because the microtests are fast, easily repeatable, and don’t require the whole app. (I debug less than I used to, but nothing ever fully eliminates debug mode.)
- It costs less to debug *non*-WIP, that is, incoming bugs from the field, because it’s easy to posit a “possible issue” and go to the microtests. It’s already tested for, or it’s easy to add a test for it, but either way, I find out faster whether my posit was valid.
- It costs less to go work with code someone else wrote (or I wrote a while back) because the tests give me executable documentation about what the code does.
- It costs less to get or give help with colleagues, because we can narrow our focus to a microtest or two and communicate quickly and deterimistically.
So, that’s a long list, and this is a long thread, and it’s time to wrap up both of them.
To come back to respondent’s comment: when I change how a feature works, I *do* change or throw out microtests. This doesn’t bother me, because the productivity gain I get from 1) having them and 2) making them in the first place, far outweights that cost.
(There’s a future muse about “feature”, which is probably more germane to what respondent proposes, but that’s another day.)
It’s cold outside, but one good thing I’ll say about winter is it gives me an excuse to wear my flannel-lined blue-jeans. I get to walk around in pajamas all day and no one even *knows*.
I hope you have a secret comforting thing going on today, too!
GeePaw’s Camerata is a community of software developers leading in changing the industry. Becoming a member also gives you exclusive access and discounts on the site.
The GeePaw Podcast
If you love the GeePaw Podcast, show your support with a monthly donation to help keep the content flowing. Support GeePaw Here. You can also show your support by sending in voice messages to be included in the podcasts. These can be questions, comments, etc. Submit Voice Message Here.