Last week I was reading a series of articles by Ron Jefferies on Discovering Better Code and it got me thinking. I had read several posts on Test Driven Development (TDD) in the past, but I had been busy enough to simply say, "seems like a good idea, I guess." Last week I wasn't so busy and I spent my free time thinking about TDD and how I hadn't programmed any code for a long time. I pulled up my last coding experiment, a failed attempt at a chess program that played decent chess. I had stopped with all chess rules accounted for except check. I had given up trying to debug check because the code was so hard to follow and understand.
So why had I failed? One could argue that I didn't do enough design, but design wasn't the real issue. There just aren't that many classes in my code, the real issue was the actual code. It started out in good shape, but entropy had the gotten the better of it. It had grown to be a Big Ball of Mud. Also I had ZERO tests! So any major change to the code base was likely to result in more errors that would be even harder to run down and fix. Thus the reason for me giving up.
What does TDD have to do with any of this. The main point of TDD is that you start development with a test that doesn't run, then you write the simplest code that will make the test pass. Repeat until done. I had never really given TDD much thought. I thought it might work for some, but probably not for intelligent, experienced coders like myself! Haw, was I full of it. The real problem is getting over the fear of writing code that you know will be rewritten. I hate waste and I thought that TDD generated way too much waste. Wouldn't it be better just to write the correct code the first time..but I know no one can write correct code the first time. It always requires feedback and iterations to get it to work. So what was my problem again? The more I thought, the more I realized that I just didn't want to change the way I developed software. It had worked for 20 years, so why change it? This is funny, because my biggest obstacle in my current job is getting people to change what they always do. Funny isn't it!
So I was able to get past my fear of change and my fear of doing nothing and try it out. This occurred over the weekend. I downloaded a new Java IDE and started TDD Friday afternoon. So I began writing a test. The first thing I could think up was setting up the chess board. That is going to be a too big, so I decided to start smaller. How about an empty chess board. That was easy and some thoughts of waste started to creep in my head, but I beat them down and continued. Next, setup the pawns and so on and so forth. It wasn't long before the whole board was setup. Well at least my tests told me so, but I didn't trust them so I wanted to see it of myself.
I tried to generate a GUI and quickly decided that would take too long and imported my old GUI that wasn't too bad. It's biggest virtue was it was decoupled completely from the implementation. In no time I had a viewable chess board with all the pieces in the correct place! So then I started on movement of the pieces and then captures and viola. After ~7 hours I was back to the same spot I was before. I had a chess board that one could play a game against oneself except that check wasn't understood and neither was the end of a game.
To an outsider this would seem like a huge waste of time, but it was not. I was so productive. I generated 543 lines of code and 333 of it was test code. My old code, which took me much longer that 7 hours to write, had 495 lines of code with ZERO tests! Plus, I never got bogged down. I had bugs, but I could quickly find them because I was working in such short cycles of write small test, write code to make it pass, run all tests and see if I broke anything. Only one bug slipped though which I caught by trying to play a game. I went to fix it and told myself wait! I must have a failed test first. This discipline might seem silly, but it gave me such a good body of tests that when I went to clean up a section (to get the to queen move, I had cut and pasted the bishop and rook code) I wasn't worried because I knew the tests would show me any problems I might inject.
So that was a long post. I should have posted it in chunks over the weekend, but I spent much of the weekend disconnected from the web (my wife refuses to allow me to go wireless ;-) The next question is how hard will check be?? We shall see.