First, some thoughts on TDD.
A Twitter thread yesterday revolved around whether TDD is an “advanced skill” that requires “discipline” and “practice” to master. Reacting primarily to the word “discipline”, which I associate with power-over, imposition, and the possibility of punishment as a form of discipline, I said:
As with all programming, we get more benefit from TDD as we develop skill with it. That doesn’t mean that it is a particularly advanced skill: I can show a beginner how to benefit. To learn it, we have to do it. One way is “discipline”, which to me means “force yourself”.
But TDD can be fun, and practicing something we enjoy is better than forcing it.
I do this stuff because I enjoy doing it better and better. You couldn’t shout loud enough to force me, frown enough to shame me, nor pay me enough to induce me.
TDD is fun, smooth, and helps me go fast. It helps me do my thing, which is programming better today than yesterday.
That draws me in to the practice. You couldn’t discipline me into it.
Joy got me into it and keeps me there.
Joy, yes. Discipline, no, not for me.
There is, of course. a relatively benign notion of “discipline”, connoting something like a rich and deep subject which does require practice to become expert. And surely, TDD in all its implications is something that will benefit from as much practice as we can give it. I have practiced it for years, and when working on something where I know how to apply it, I practice it daily. I wouldn’t do that because someone told me to do it. I pretty much won’t do anything because someone tells me to do it. I do things because I want to, and because I enjoy them. I try never to tell others what to do, and I try never to be in situations where someone else can tell me what to do.
So my reaction to the thread was around the word “discipline”, which to me and to many people carries that connotation of “do this or you’re a bad person, not a crafts person, not a professional” and so on.
“I tried TDD and it didn’t work.”
In any such thread, folks turned up to say that they had tried TDD, and that it doesn’t work, and that people trust TDD more than they do the actual code, and that TDD is a religion, and such. Now, as it happens, I have used TDD over wide range of languages, systems, and problems, and I have found it useful enough, pleasant enough, and valuable enough that I prefer to use it always. So my initial reaction to “I tried TDD and it didn’t work” is a bit cynical.
But … if in fact someone, call them Jerry, is trying a thing they think is TDD, and it isn’t giving them the same benefits that I get, there’s something going on. I’d like to know what, though in most cases I never will, and I consider a number of possibilities:
There could be a kind of problem where TDD isn’t very helpful. I find this credible, because I know of at least one case. The individual or team who don’t like TDD could be working on such an area.
There could be a style of programmed solution where TDD isn’t helpful, even though, working in the same area, my form of solution would be helpful. “The way we program, TDD doesn’t help”. I have seen this happen, so I consider this a possible explanation.
The thing they’re doing might not be the same thing that I’m doing when I do the thing I call TDD. And I have seen that happen. I’ve seen it happen more often than I’ve seen the other two, so I freely grant that it is the first thing that comes to my mind when someone “has tried TDD and it didn’t work”. I suspect they weren’t doing the same kind of thing I would have done in the same situation. And, in that case, I would go so far as to say “they’re not really doing TDD at all”.
- Where is TDD not so helpful?
- I find TDD not to be very helpful when the aspect of the program that I’m concerned about is how it looks. Does the spaceship respond to gravity in a way that makes sense? Does the demon jump out from hiding at the right moment to startle me but not so close that I can’t defend myself? Does the text in the window scroll up to become visible as it should?
I assess those things using my eyes, and while I might — might — TDD some of the gravity code, by and large I try things until they look right. There might be a way to get more TDD benefit in those situations, but if there is, I don’t know it.
- What style of programming interferes with TDD?
- TDD is about small steps and rapid feedback. If it takes a minute even to start the tests up, TDD becomes Tedious DD and I’ll stop doing it: it only helps with small steps.
If a developer’s style of programming doesn’t support small steps, TDD will not be very helpful. Programmers who produce large methods and functions, who use few objects, will not get much value from TDD. For TDD to be useful, you really want to ask the computer “can you do this”, have it reply “not yet”, and work until it says “yes, I can”, all over a span of a small number of minutes. For me, small means twenty minutes or less.
I have seen successful programmers who work in chunks of code of 20, 40, 100 or many more lines. For them, TDD can be too fine-grained to serve them well, and tests that are to scale with their large functions aren’t what we think of as TDD tests at all. Now, unless these programmers are very very good, or quite fortunate, they’ll work for hours on something, and then debug for hours to make it work. I believe that if they went in smaller steps, they’d go faster. I could even be right. But working as they are, TDD won’t help them.
- What isn’t real TDD?
- If our tests are not pretty easy to write, what we’re doing isn’t near the sweet nougaty center of TDD. If our tests have to check many conditions to be sure that one single step has worked, we’re not in the tasty crunchy part of TDD. If we can’t make our test run with a few lines of code, we’re not in the juicy nutritious part of TDD. If our tests take several minutes to run, we’re not experiencing the sense of satisfaction that goes with a good breakfast1. TDD might apply well in our situation, but we’re not doing TDD, we’re doing something else.
- How can we tell? What should we do?
- Is our difficulty with TDD just an inevitable result of our problem space? Is it a built-in aspect of our programming style, such that it would only pay off if we changed style? Or are we just not doing it right? How can we know? What should we do?
You can’t trick me. I won’t tell you what you should do: that would violate my personal preference for not being told what to do, and therefore trying hard not to tell others what to do. But if a person wasn’t having success with TDD, and they wanted to know why, I think they’d get benefit from working with someone who does have success with TDD. Not that they’d have to hire such a person. they might have such a person in a team near them. They might drop a line to someone they know. They might even send out a probe to some expert, to exchange some emails, or have a chat with them. Most of my pals would engage for a few emails or a chat with someone who seemed truly interested in learning2.
As a “rule”, I think that if someone is working in an area where others do have success with TDD, it’s likely that they really aren’t quite writing the right kind of tests, and it’s not unlikely that the code they’re working on isn’t modular enough to benefit from TDD. And I think that if they were to find a way to work a bit with TDD, they’d find it pleasant enough to continue. But I won’t say they “should” have the “discipline” to be “a professional”, and bear down hard enough to work on TDD. If they want to, I’d try to help. If they don’t want to, that’s fine with me.
Enough about TDD. I want to code something. See you over there.
Yeah, I am kind of getting hungry, why do you ask? ↩
And, if someone just wanted to prove to us that what we’re doing doesn’t work, or doesn’t work for them, well, we aren’t interested in that. We know it works for us, and we believe a person when they say it isn’t working for them. We’re curious about why, but not to the the extreme that we want to endure a rant from them. Curiosity, yes. Being told that what we’re doing doesn’t work, not so much. ↩