My house has been struck by plague. On Tuesday, Liesl stayed home; on Wednesday, Liesl and Miranda stayed home; on Thursday, Liesl, Miranda and I all stayed home; on Friday, there wasn’t anybody else to pass the cold to (the dogs don’t get colds from us, fortunately, and they stay home all the time anyways), but we weren’t getting any better, either. Fortunately, Miranda was more or less on the mend by Saturday, and I think Liesl and I will be able to go to work on Monday. We’ll see.
Does having a cold make you more sensitive to the smell and taste of milk? Because either I’m having incredibly bad luck, or every store in Mountain View is full of spoiled milk, or something. At first I thought something was wrong with the temperature control in our fridge, and that may actually be the case, but milk is now smelling strange to me as soon as I bring it home. And it’s not just me – Miranda has been complaining about the taste, too. Maybe it’s a recent switch from 2% to 1% milk – does milk with a lower fat content go bad faster?
One of the benefits of staying home is that I’ve had lots of time to play games. In my last entry, I talked about how wonderful Katamari Damashii is. And I just want to emphasize that further; I’ve been playing through the game again, and it (and its music) really is fabulous. In fact, I was going to say that it’s the second best video game I’ve played this generation, after Metroid Prime, but looking at my shelves, that’s an exaggeration. It probably is the best video game I’ve played in the last two years, but all that says is how front-loaded this generation is. Hmm: Are generations always front-loaded? I guess I would believe that as a general rule: in the first two years, you see new gameplay ideas that wouldn’t have been possible in previous generations of hardware, while the three years after that give you games that are largely refinements of ideas that you’ve seen before. So early in this generation we got Metroid Prime, Animal Crossing, the Resident Evil remake, ICO, Golden Sun, Advance Wars, and the beautiful short life of the Dreamcast (Shenmue, Jet Grind Radio, Space Channel 5, Soul Calibur). While now the best games, while often quite good (Prince of Persia, SSX 3), usually don’t excite me as much.
I’m finally getting to the end of my first big refactoring project at work. Two or three months ago, I inherited some badly written, completely untested code, so my top priority was to clean it up, so I’d be able to fix bugs in it and adapt it for new situations. It’s been quite an educational experience. One thing that I learned from my last refactoring project is that, if you start your refactoring at the top, then it will probably be very helpful in understanding the structure of the code, but it won’t make it any easier to test – you’ll still be left with big classes, albeit better-structured ones, and writing unit tests for big classes sucks. So I was happy a month and a half ago when I found a couple of nice little classes that I could split off from this code and write unit tests for. And, while doing that, I noticed some bugs in the code, bugs I never would have found without cleaning it up like that. This week I finally got to a situation where the main class involved in this program is small enough for me to test.
Except that the tests were too simple. Which points at a way in which I was misunderstanding the program. This program doesn’t actually do anything itself – it just takes user requests and passes them off to other programs to carry out the actual work. And there are only a couple of important user requests, so it turns out that there are two unit tests at the core of this program. But, while it’s a small program, it’s not that small. And, when I look at the code, I see that the real story is the error cases. If you’re dealing with a program that just talks to lots of other programs, then the question isn’t what happens if everything goes right: the question is what happens if you get queries or responses in an unexpected order, what happens if one of the other programs goes down, what happens if this program goes down and has to try to recover its state.
So I’ll be spending the next two weeks refactoring code with that aspect of it in mind (I’ve already done most of the relevant refactoring, of course) and bringing it under test. And then I’ll move on to something else – there’s another program that I’m in charge of that is starting to cause problems and need refactoring, or maybe I’ll have to refit this program with different external interfaces. (Which will be a lot easier now: that’s the whole point of refactoring, after all, and developments in our business plan make me think that I’m getting this done just in time.)
I really love the way that code development via refactoring works. I didn’t try to understand the whole program at once and come up with a better way to do things. Instead, I started by looking for places in the code that I knew I didn’t like the look of (or the smell of, as the refactoring book puts it), and improving them. Every few days, I’d get sick of fixing some particular thing over and over (or, worse yet, not fixing it), and at that point I’d have enough of an understanding of the problem that I could usually come up with a general solution. Usually the solutions (whether specific or general) weren’t perfect; I’d add a FIXME comment, and a couple of weeks later the surrounding code would have changed enough that the FIXME comment could be dealt with much more easily. For a long time, I had a hard time telling how much progress I was making (and, in particular, when I’d be done), but all of a sudden this week I looked up and realized that the bad smells had greatly receded: they were still there in the fringes of the program, but a strong core had appeared, one which will serve us well going forward.
There are no revisions for this post.