We spoke of two questions in the recent re-visiting of the money premise.
- How/why does TDD make changing layered branching logic faster?
- What’s the capital outlay to change to it?
I’ll stall a little further on 2, but let’s do 1.
Some provisos before we get started, and they’re pretty important.
We are speaking here of a particular kind of test applied at a particular time during development, specifically, microtests applied right before (and sometimes right after) the code that makes them pass.
Not every test is a microtest. If u need more info about what they are, ask me or check the site, there’s tons of material there. As for the timing, we work roughly one microtest followed by one snippet that passes it. There’s jiggle there, but that’s the target experience.
A practitioner will have to learn how to do this, will have to practice it, and will have to take progressively larger tasks on in this way. It is not a one-paragraph-teaches all kind of thing. (Thus the capital outlay).
There are smilin’ faces — to allude to a surprising lyric in a well-known song from my youth — that will wish so hard for it to be otherwise, they will tell people TDD is easy to get good at. It is not. It’s a whole approach, not a "this one weird trick" kinda thing.
It is especially hard to learn how to do it in a TDD-unfriendly codebase. Note: it’s only a little harder to do it there, once you know how, but learning how is a good deal more difficult in that setting.
If you’re gonna start TDD in a massive j2ee or an already-deployed rails app, that’s fine. You can do that. But you are going to want to find expert help to start learning how.
So, with those provisos in mind…
I have made the claim that microtested TDD lets you change layered branching logic more quickly than not doing TDD.
I’m gonna sketch the answers pretty quickly here. Myself and others have far lengthier explanations of these. Ask if you want some of mine.
1: Microtests let you write and forget.
Every geek has had the experience of getting A to work, then implementing B, then implementing C, then discovering that A is now broken. With microtests, A will never break quietly. This makes you faster, because it reduces the number of things you have to hold in your head at one time. It reduces your mental bandwidth requirement for making changes.
(Attacking this mental bandwidth is a hallmark of the TDD approach. We’ve discussed at some length what we know about how much humans can hold in their focus at one time, and it’s terribly small. When we push the bandwidth, we don’t gradually degrade, we drop like a stone.)
2: Microtests provide a second executable layer of description on top of the code itself.
When you are using TDD’d code instead of writing it in the instant, the microtests provide powerful working examples of how the code was intended to be used. This lets us go faster because we spend less time in detailed reading of code that is not in our current focus. Microtests are typically far more revealing than comments or javadoc. Faster handling of strange code means more time to work on our focused code.
3: TDD strongly encourages and supports us breaking our design into very modest pieces, and especially into very modular pieces.
All that theory we read about modularity?
TDD tests naturally demand that. Writing with TDD is like having an "elements of style" guide all the time. This makes us faster in a strange & indirect way. Because the TDD approach makes some design smells more immediately unpleasant to TDD, we tend to move to better design naturally. We can still write bad designs, but the TDD makes it more annoying to do so. Result: we do it less.
Real-world analogy: most drivers, with very little thought, quietly swerve around half-wide speed bumps. They could go over them, they’re not barriers. But they don’t, cuz they’re just that little bit of push one needs to swerve.
4: TDD makes us faster because it matches amount of effort more closely to complexity of defect.
TDD’s microtests are almost like syntax-directed editors: they tell you right away you did something dumb, and very little expense. Non-TDD approaches cost you the same amount for a defect whether it’s a rocket-science multi-threading race condition that only happens on Thursdays or dumb-assed off-by-one error. TDD charges you less to find latter than the former.
(And ya know what? Grow up. The overwhelming majority of the shipping defects in your house are not rocket-science multi-threading thurday-only race conditions. They’re one-liner typos-that-aren’t-syntax-errors. That snark is going out to my embedded friends with love.)
5: A TDD’er reads, writes, runs, and debugs microtests without invoking the app.
No server. No database. No browser. No supporting threads. No container. No upstream microservices. Just little bundles of code in a separate app meant for that purpose.
This makes us go faster because c’mon do I really have to explain this? I watch people in web-to-database houses especially, all day long, launch 5 apps to see what their change did. Or 4, cuz they forgot one. Or wait, did they remember that one? Idunno, let’s bounce it again.
6: Skilled TDD’ers write assertions that say exactly what needs asserting. They don’t use a human to read a log or even stdout.
Well, I’m talking reduction, not elimination. We all use stdout sometimes. We go faster because we’re letting a computer do what it’s best at, and freeing the human to do more of what she’s best at. Fewer cycles on human-parsing output means more cycles on producing change.
Believe it or not, there’s more. But I am going to stop right there.
Now, for the doubters, I need you to understand where this text is coming from. THIS IS NOT AN ATTEMPT TO PROVE MY CASE. What I am doing with this list is offering you a prima facie case that those of us who use and advocate TDD are not obviously patently insane.
It begs the question, of course, can I? Can I prove my case?
Well. I certainly can’t prove it as efficiently or as compellingly as you can.
If I had my druthers, I’d druther you use these ideas not to convince yourself that TDD does what I say it does, but to let me and others help you actually try it and find out.
What I’m after here is to expose you to a snortling experience. You likely don’t know that word, cuz I just made it up. Remember the first time you did a cool regex? Or maybe a colleague or stack-overflow gave you some unlikely snippet, and u dropped it in and it just worked?
You made a sound — maybe just in your head — half-snort, half-chuckle, meaning "well I’ll be damned. Just like that." nothing closes a case like a snortle. But I can’t get you there until you have a keyboard under your fingers and a problem in front of you. That’s what i’m trying to do here.
It’s not free, either the experiment or, if it works, the full-on transition. But it’s affordable, and when the ducks are lined up, you even start getting the return very quickly.
But it’s not free. In the next muse, we’ll tackle the capital outlay. How much is this gonna cost?