I am fascinated with test driven development/design (TDD). I am reading everything I can get my hands on about the topic. I highly recommend a Microsoft Press book written by Ron Jeffries titled “Extreme Programming Adventures in C#”. TDD speaks to me as a developer in so many ways that I cannot even begin to explain. If I write a line of code, how do I know that line of code works? More importantly than that question is the greatest question a person can ask: “Why?” More specifically, “Why did I write that line of code?”
Mike Roberts has a blog entry titled, “Popping the Why Stack ” where he took the idea of why in a different direction, but I think we end up in the same place. The last element in the TDD-Why stack should be: “Because it fills a specific need in this customer story.” That means that the ultimate answer to the question, “Why did I write that line of code?” should always be, “because it solves this problem for the customer.” How, then, do I get from a list of customer stories or requirements, to a single line of code? TDD has the answer to this, and it all has to do with being as lazy of a programmer as possible.
Being lazy is harder than it looks. It means that you should write the smallest amount of code that will solve a problem and not a single line more. TDD (and common sense) tells us that before I can solve a problem, I have to have a problem to solve. The problem that I need to solve is defined simply in a test, and let me tell you when that test fails it is a red light piercing my brain telling me I’m a screw up, a loser, nobody likes me, and my fellow programmers are all laughing at me. (Please note that I consider getting the system to compile without errors or warnings to be an implicit test.) So quickly I go and write the smallest amount of code required to get that test to pass. I say quickly because if I’m fast enough, none of you will notice that I had a failing test. Once the test is green, I can go and clean up my code (A.K.A. refactor), and write another test to start this whole cycle again.
Today, I had the opportunity to listen to a Microsoft MVP present an Education Day on an introduction to test driven development. It started at 8:30AM and was supposed to last until 5PM. I left at 2PM because I just couldn’t take it anymore. Maybe I’m wrong, but the step where you clean up your code, also known as refactoring, should not make any changes to the way your code operates, and should not introduce any new complexity. The reason for that is that there is no reason to change your code. What I mean is that all of the tests pass at this stage. You’ve solved all of the problems that need solving. If I have a section of code that loops through all the elements in an array, and that section of code is in two or more methods, then yeah, refactor that bad boy and move on. But if I only have one test and it is looking to see if 5 is returned from some method, I’m not going to change that method from “return 5;” to “return myFavoriteProperty;” unless I have some test that is failing.
This is where the presenter was driving me nuts. He would change it from “return 5;” to “return myFavoriteProperty;” and he was doing it under the guise of “code clean up”. He should have waited until he had a test that failed. He was trying to solve a problem before there was a problem to solve.
I understand that many of you that are reading this (I know there have been only 5 hits to this site since December, but I’m sure someone will come along soon) will tell me that he was just an experienced TDD’er and he was just thinking ahead. If that was the case I’d agree and let it go. However, you have to understand the audience. Half of the people had never heard of NUnit before. Also, you have to understand the topic he was selling (emphasis added), “an Introduction to test driven development.” All this adds up to the fact that there are now about 75 programmers out there that think that the third step in TDD is to change your code to fit a future requirement that has no test calling for a solution.
That is the point I am trying to make with this entry. I hope that if I am wrong you will be kind and provide constructive feedback. After all, we only practice programming to find a better solution.