Recently on the C# Design Patterns mailing list, an email came over about this post by Andres Aguiar. In it, he makes an argument that I have heard several times before – why should I write a simple test when I know it’s going to fail, and besides, I know what it needs to do, so why shouldn’t I just do that?
I thought about this, because I see it a lot. People looking at the pattern and examples for Test Driven Development dismiss it without trying or after trying it only a little bit because they don’t feel it is necessary. After all, they write perfect code, right? Setting aside that there are other reasons for TDD (#1: It’s not about testing, #2: Requirements change, features get added, and modifications invariably happen, and you want a safety net for that, etc) I wanted to focus on the hump developers seem to run into when they try it. It usually goes like:
“Ok, I want to add this feature. I’ll try it TDD! Ok, first add a test. Hmm, alright. What should I put in it? Oh, huh, a call to what I want the feature to do. But that’s going to fail! I don’t even have the class built! But fine, I’ll do it.
Ok, so now make it work. Wait, do the simplest thing? What the heck, hard code the variable? What kind of nonsense is that?! I have more important things to do. This TDD stuff is for the birds!”
Which brings me to my guitar. I’m a musician at heart. I’ve been playing drums forever, and play a little guitar and keyboard (and now bass) on the side. I’m also an impatient person, who wants to get right to the point.
So, when I first got a guitar, I ran out and picked up a guitar magazine. It had tablature to several songs I knew and I figured, heck, how hard can this be? Then the whirlwind of chords, notes, rests and other symbols flashed in front of me. The chord above the notes said G, but the tablature said:
and then, 5 measures later, the chord above the notes said G again, but this time it showed:
How was I going to remember all of that?! I got so frustrated that I put down the book and would get mad just looking at it. I mean, there’s just six strings! This shouldn’t be that hard. Besides, those guys (and gals) can’t be human – who gets their fingers to bend like that anyway! Mine hurt from 10 minutes of playing. This is crazy, I’m going back to drums.
But, as the musicians in the crowd know, it’s not as bad as it sounds. Sure, *that* guitarist chose to play a G *that* way, but there’s plenty of other, easier ways to do it. In fact, my Mel Bay chord reference lists 14 different ways one can play a G-Chord including:
And the funny thing is, from the craziest way to play a G, to the simplest, the masters use them all. Sometimes you go for the open chord. Sometimes you go for the barre chord. Sometimes you pick it. Sometimes you turn on distortion and crank it.
So how does this relate to TDD? It’s a challenge, because we are in familiar territory. We’re using a language we know, in a familiar environment, with the same challenges that we normally face, and, even better, we know the workarounds to those challenges. We have a method, a procedure in place. We know our code. We’re comfortable.
TDD takes us out of the comfort zone. It forces us to think differently about our code, about our problems and tasks and stories and features. We have to do planning and thinking and breaking down of our tasks into bite size chunks that we can give definitive endpoints to. It makes us actually do *more* work then what we normally would have done upfront. When I see I need to calculate the total from some entries, I want to just calculate it, not think about how best to calculate it, what are some ways we could verify it is calculating, etc, etc. I just want to type:
decimal total = 0.0m;
foreach Order order in orders
total += order.total;
and be done with it. Just like I want to learn the silly Pearl Jam song, and be done with it. I don’t care about the nuances, or the harmonies. I just want to be done. I’m too busy – don’t bother me with the details.
Some people are like that. I heard a story about Slash, the former guitarist of Guns n’ Roses, walking into a music store, picking up a guitar magazine featuring one of their songs, and remarking, “Oh, so *that’s* what I play.” He didn’t need to know the details, or back it up with theory. He knew what worked, and reliably did it over and over. He couldn’t tell you that the turnaround sounds good with a B minor because that is the 6th of the root and traditionally is used as a turnaround. But he could play it.
Like Slash, I believe there are a small set of coders who can pull this off. They don’t make mistakes. They know the design. They get it right the first time. They’ve no need for tests, or refactoring tools, or design documents. Give them a whiteboard and a silent office with a door, and let them be. Two weeks later you’ll have your incredible new feature that works the first time.
But, I don’t know first-hand any Slash coders. I know I certainly am not one. I have to slug through learning the positioning of the G chords. I have to work and work to build up dexterity in my fingers and calluses at the tips. I have to read books on theory, books on chords, books on song writing, and above all, practice. Sure, I’m annoyed with having to do repetitive runs over and over. And when I’m learning a new style, it irks me to have to muddle through the beginner stuff, playing slow. I want to be fast. I want to be good. I want the pill that makes me a star now.
Since I don’t have the pill, I just have to practice. And along the way, I learn I don’t have to play a G chord barred. I don’t have to do a turnaround in B minor. I learn C# minor works (even though it’s a bear to play) in some circumstances.
Above all, I learn that as I learn, I find the shortcuts so that I don’t have to start at page 1 of every book. I know what works for me. I know where I stumble. And if I want to just open to the middle I can. And if I just want to write the class before I run the test, I do.
And when I fail, I go back to Page 1 until I don’t anymore.
So, the tests are frustrating because they slow us down at first. They slow us down because we are learning a new language in a familiar syntax. Sure, the references and methods and classes seem the same, but really it’s all brand new. Which means we aren’t going to be good at it at first. Its going to take some time to get through. Time of going back to basics and reteaching ourselves this new-fangled thing called TDD that happens to use the same syntax that we use in C# or Java or Ruby or Python. Time of going slow, making mistakes, getting frustrated and working through it. Time of learning where our strengths are, so that we can shortcut, and where our weaknesses are, so we make sure we don’t.
Scott Bellware likens this to the movie the Karate Kid. I think that’s a great analogy. Practice, doggedly at first, until you learn what you are capable of.
So, my advice to Andres would be, stick with it. If you don’t like the duplication, factor it out. It might seem easy to just revert back, but push through. Figure out how you can make the things you don’t like go away. It seems you are on a good road, and you’ll get there. And if you run into bump
s along the way, there’s a whole community waiting to help.