Wednesday, March 10, 2010

When The Test Goes Green

My assertion today is: If we would read the code we're writing, we wouldn't write the code we're writing.

We know the red->green->refactor cycle, but I find repeatedly that programmers are "optimizing" out the last step. It tends to run more like red->green->next. Perhaps there is confusion over what is supposed to happen when the test turns green.

The first thing that is supposed to happen is that you read the code you've just written to see if it makes any sense at all. While this sounds perfectly sensible, it often does not happen. Programming is not just typing. It is easy for programmers to rush to complete their assignments and never really examine their work.

I saw an example recently where the old code said:

DateTime date = DateTime.Parse(datestring);
As a minimal-perturbation change to push to green, the developer changed the code to say

DateTime date = DateTime.Parse(DateTime.Now.ToString());
Had he or his partner actually read that code, they would have realized that it was a little silly, and replaced it with

DateTime date = DateTime.Now;
However, I suspect that they never examined it past the green bar. It worked, and that is a virtue, but it was doing too much and the team would be totally embarrassed to see their blunder in print. I fixed it, and the programmers remain anonymous here. They're good programmers, but this time it seems they sailed past the green bar without a thought.

When the bar turns green, read your code. Read the test code and read the code it invokes. It is not at all unusual to find that you have done something short-sighted, complicated, or (God forbid) clever. That code needs to be cleaned up before your peers see it!

For a brilliant example, see Raymond Hettinger's video on pythonic code.

Once you read the code, you will know what is wrong with it, and then you can use the various refactorings provided by your development tool or outlined in the fine Refactoring book. You can take your code from one "green" (all tests passing)_ state to another until it is no longer apparent that you ever did anything silly to begin with.

Be particularly suspicious of any code you've written into your tests or test fixtures that ought to be in the classes you are testing. Tests are meant to be extremely lean and fast-running, whereas business objects are meant to be capable. If you start writing capable test fixtures that call upon lean business objects you know you've gone wrong. Refactor the code.

I wish that we could lengthen the sequence to red->green->read->refactor so people would understand the process and apply it. I suppose that we take too much of "refactor" for granted. Nevertheless, the secret to TDD is in that third step, and all refactoring begins with reading and evaluating the code we've written.

After all, a program unexamined is not worth writing.


  1. From my experiences they do think they do a refactor but from their sheer inexperience or lack of caring they simply don't see the need.

    There is a distinguishing point between a lean/clean developer, and a make it work developer. Typically from my 10-11 years of experience in this field about 80% of all developers fall under the "make it work" umbrella. Occasionally I will meet another developer that is lean/clean, and it's a joy to work with them. But usually that joy is countered by the rest of the team being "make it work", so as it goes.

    I've actually paired up with these types of developers before and its maddening. Not only do you have to watch there very slow ability to navigate the IDE, windows all over the place, tiny little window where the code is showing, etc. But you have to constantly intervene and sound like a broken record, you should move that into another method, "Why?", because you need to refactor it. "But it works and I don't wanna change it since its working", etc.

    When I was in charge of a team, I actually forced the entire development team to watch a video on Clean Code that was recorded at the Agile 2009 conference that a friend of mine Scott Ford recorded and it didn't matter, they still didn't get it.

  2. Do you suppose it would help if we had a shared idea of what good code looks like? At my other project with Jeff Langr, we added a card on code virtues. We are accepting comments and trying to improve it, so your input is welcome.

    I hope that we can infect programmers with shared values so that we can start to instruct the workaday practice of writing excellent code.