Writing code is awesome. At least I’ve always thought so. I started programming on an Apple II+ that my dad bought and me and my brother Pat spent countless hours learning Applesoft BASIC. One of our first lessons was in the importance of language standards and what happens when you don’t have them. My dad bought as a book full from Creative Computing that was full of listings of computer games. Games! Did you hear me? Games! They had names like Schmoo and TV Plot Generator. We would type them in and there were two problems: first, the version of BASIC they were coded in was not quite like Applesoft so we essentially had to port them. The second was that we introduced bugs typing them in.
But the joy of getting them to work was what kept us going. I call this joy “making the monkey dance”. It is seeing the product of pure thought turn into action.
Unfortunately, the process is a roller coaster ride. You hold onto the possibility of joy but there are inevitably problems and it make take hours, days, or worse weeks to find the thing or things that caused the problem.
Working on Acrobat, we had bugs that we talked about metaphorically. For example, if Acrobat was a house, we would describe the process of reproducing a complicated bug as “You go in through the front door, go upstairs, go into the bathroom, close the door, climb out the window, shinny down the drainpipe, then open and close the back door 4 times and then the toilet explodes.
And while you’re running through these steps, you start setting traps in the code to catch the thing that is causing the toilet to explode. And then you spot the problem, isolate it and (sadly) more often than not, put in a hack to ensure that particular case can’t happen. Ta-da: no more exploding toilet. Unfortunately, without taking the time to look at the bigger picture of the code and how the problem fits in, you will inevitably cause something else in the house to explode later.
Worse still are the bugs that reveal that you built your code on a leaky abstraction. You hack it to make it fit and your code gets worse. And when the sink explodes, you hack it again. And again. And it gets worse and worse.
I remember working on one particular bug on Acrobat late in the release cycle and I went into Alan Wootton’s office to really just complain about not wanting to fix the bug the right way. I had a fix that I could put in, but it was a patch on patchy code already and I described it as putting a Band-Aid on a cancer. Alan tolerated my complaints and then asked the more important question which was “why don’t I go fix the whole thing?” The answer comes down to three things:
- I was tired
- I was feeling lazy
- I feared the onslaught of late-cycle bugs that would result from this
Still, I did the right thing and went through a cycle of “refactoring with a hammer” and fixed up overall code and the inevitably the bug.
As I’ve become more experienced, I’ve become more pragmatic and less bitchy about broken code. Sometimes it’s a case of “well, better to take the time to fix this right.” Other times, there isn’t enough time to do it right (now), so take notes on how to make it better in the future.
I was working on a new feature in my current code, which is unfortunately much more complicated than I’d like. I wrote a unit test first and it failed, as expected. As I worked on it, it was failing in ways I wasn’t expecting. In looking at the fallout for implementing this feature, I was reading through some older code that was affected by the new feature. My internal dialog was, “Huh. That will never work. Past me must have really enjoyed being so blissfully naive.” So I rewrote the older code and the new feature worked. But in the process, I had found something in my internal run-time type system that I had missed, so I fixed that – easy. That in turn caused 24 unit tests to fail, each one ultimately related to the type system fix, and in each case the incorrect code had all the pieces necessary to avoid the problem, it just didn’t take them into account.
And rather than suffering from the downs of bugs and design flaws, I’ve learned to relish the process of finding the ultimate problem and the fallout as well as when everything works. I do recognize that when I’m deep in the process, it does still affect my mood, but not nearly as much as when I was younger.