The Need For Speed 30
Yesterday was the day we felt the accelleration.
As you may know, we’ve been working on a largish web application to use as a running example in our new Principles, Patterns, and Practices course. The first couple of days of development were typically slow; and we all felt the pressure of getting “too little” done. But we stuck to our disciplines and wrote tests, and kept the code as clean as possible.
Working this way is not easy. We have a deadline that is very real; and there is a lot of money tied to it. So we all feel “the need for speed”. But all of us also know that Brian Marick is right when he says: “When it comes to software, it doesn’t pay to rush.” So we’ve nervously tolerated the pace and continued to practice TDD and continuous refactoring.
On the third day it started to pay off. The structure of our code is clean and simple enough that new features are starting to be able to take advantage of older features. We have enough tests (~90% coverage) to ensure that minor refactorings to facilitate reuse aren’t risky. And so we were able to twist the code a little here, and tweak it a little there, and within a single day triple the functionality of the code.
Let me make this more concrete. We have a set of stories. We’ve estimated those stories with point values. The sum of our velocity on Monday was close to zero. On Tuesday we got 11 points done. On Wednesday we got 26 points done. This acceleration is due to the fact that we were able to take advantage of the similarities in the features and craft the new features into place by making fine adjustments to the existing structure.
I don’t need to tell you that if we’d been practicing cut-and-paste programming we would not have had that option. Instead of a carefully crafted structure that allows new features to be easily melded, we’d have feature silos with much duplicated code and messy tangles.
I got tired and debugged! 22
My grandaughter slept over last night. She’s an early riser. She and I had breakfast at 6am. My wife got a new cell phone (TREO680) yesterday, and I helped her set it up. So I didn’t go to bed until late. In short, I didn’t get a lot of sleep.
A bunch of us are working on a new training example for object oriented design principles and patterns. It’s a large-ish web-based system that has lots of interesting lessons to learn. We’ll be presenting it as a series of exercises throughout the course. Anyway, we’ve all been working as a team, writing this software. It’s been a lot of fun!
Anyway, about 3pm I started to get really tired. I should have stopped. But I wanted to finish one last story! (You know the feeling.) So I pressed on.
I ran accross a small dependency problem between two of the classes. So I started an elaborate refactoring to resolve the issue. An hour later I had to back out the whole refactoring because it didn’t solve the problem, or even come close! I don’t know what I was thinking. The real solution was much simpler and took just 10 minutes or so to implement. I should have stopped then, but, well, you know…
I needed to leave at 5pm. By 4:30 I was executing my unit tests. There was a problem. It didn’t make sense. You know the kind! I stared at the code for a long time, but my brain was mush. I couldn’t think. The lines of code swam before my eyes, but did not speak to me. I should have stopped then.
But no. Instead, I did something I barely ever do. Something I haven’t done in many months. I set a breakpoint! Egad! I was single-stepping through the code. And then I would do that horrible little dance where you step to a point in a module and realize you’ve gone a step or two too far. The variables don’t make sense. So you start over, and step back to just before where you were. Hideous! I should have stopped! But I kept at it. Over and over, breaking, stepping, breaking, stepping.
Debuggers feed you a torrent of information. Even when you are awake it’s easy to misread them. When tired, you see what you want to see, not what you really see. And nothing I saw made any sense. I finally got to the point where an if statement comparing two identical strings was failing! (Or so I thought.) I demanded that the stupid machine was lying. I rebuilt the application. I rebooted my machine. I redid the breakpoint, over and over. No change.
Now it was after 5pm. I really needed to go. I also really needed to fix this damned problem and check in the code. So I did the only thing that might make a bit of sense (other than stopping, which is what I should have done 2 hours before), I turned off the debugger and asked my pair-partner James for some help.
James had been busy helping one of the other guys get subversion working with Eclipse, so he’d been somewhat distracted while I was spinning myself into a debug rathole. He came right over and looked at my unit test. He said “Oh, shouldn’t that fravitz be a dorvitz?”
...
Duh. Yes, that fravitz should have been a dorvitz. It was obvious. It was simple. It was a 2 second change, and the tests all passed. (sigh).
So I, once again, reinforce my rule about debuggers. They are a horrible time-sink. When you find you must debug, it’s time to get help or go home.