Seibeclass="underline" Other than having two million people using your software, what about programming do you enjoy?
Zawinski: It’s a hard question. The problem-solving aspect of it, I guess. It’s not quite like it’s a puzzle—I don’t really play many puzzletype games. Just figuring out how to get from point A to point B—how to make the machine do what you want. That’s the basic element that the satisfaction of programming comes from.
Seibeclass="underline" Do you find code beautiful? Is there an aesthetic beyond maintainability?
Zawinski: Yeah, definitely. Anything expressed just right, whether it’s being really concise or just capturing it—like anything, a really wellput-together sentence or a little doodle, a caricature that looks just like someone but only used four lines, that kind of thing—it’s the same sort of thing.
Seibeclass="underline" Do you find that programming and writing are similar intellectual exercises?
Zawinski: In some ways, yeah. Programming is obviously much more rigid. But as far as the overall ability to express a thought, they’re very similar. Not rambling, having an idea in your head of what you’re trying to say, and then being concise about it. I think that kind of thinking is the overlap between programming and writing prose.
It feels like they use similar parts of my brain, but it’s hard to express exactly what it is. A lot of times I’ll read things that just look like bad code. Like most contracts. The really rigid style they use—it’s so repetitive. I look at that and I’m like, why can’t you break this out into a subroutine—which we call paragraphs. And the way they usually begin with definitions, like, so and so, referred to as blah blah blah.
Seibeclass="underline" Lets talk a little bit about the nitty-gritty of programming. How do you design your code? How do you structure code? Maybe take your recent work on the OS X XScreenSaver as an example.
Zawinski: Well, first I messed around and made little demo programs that never ended up being used again. Just to figure out here’s how you put a window on the screen, and so on. Since I’m implementing X11, the first thing to do is pick one of the screen savers and make the list of all the X11 calls it makes.
Then I create stubs for each of those and then I slowly start filling them in, figuring out how am I going to implement this one, how am I going to implement this one.
At another level, on the Mac side of things, there’s the start-up code. How is the window getting on the screen? And at some point that’s going to call out to the X code. One of the trickier parts of that was really figuring out how to set up the build system to make that work in any kind of sane way. So a bunch of experimentation. Moving things around. At some point, maybe I’d had this piece of code on top and this piece of code being called by it. And then maybe those need to be turned inside out. So there’s a lot of cut-and-pasting until I kind of wrapped my head around a flow of control that seemed sensible. Then I went in and cleaned things up and put things in more appropriate files so this piece of code is together with this piece of code.
That was sort of the broad strokes, building the infrastructure. After that it was just a matter of moving on to the next screen saver; this one uses these three functions that the previous one hadn’t used before, so I’ve got to implement those. And each of those tasks was fairly straightforward. There were some that ended up being really tricky because the X11 API has a ton of options for putting text on the screen and moving rectangles around. So I kept having to make that piece of code hairier and hairier. But most of them were fairly straightforward.
Seibeclass="underline" So for each of these X11 calls you’re writing an implementation. Did you ever find that you were accumulating lots of bits of very similar code?
Zawinski: Oh, yeah, definitely. Usually by the second or third time you’ve cut and pasted that piece of code it’s like, alright, time to stop cutting and pasting and put it in a subroutine.
Seibeclass="underline" If you were doing something on the scale of writing a mail reader again, you mentioned starting with a few paragraphs of text and a list of features. Is that the finest granularity that you would get to before you would just start writing code?
Zawinski: Yeah. Maybe there’d be a vague description of the division between library and front end. But probably not. If I was working alone I wouldn’t bother with that because that part is just kind of obvious to me. And then the first thing I would do with something like that is either start at the top or at the bottom. So start with either, put a window on the screen that has some buttons on it, and then dig down and start building the stuff that those buttons do. Or you can start at the other side and start writing the thing that parses mailboxes and that saves mailboxes. Either way. Or both and meet in the middle.
I find that getting something on the screen as soon as possible really helps focus the problem for me. It helps me decide what to work on next. Because if you’re just looking at that big to-do list it’s like, eh, I don’t know which one I should do—does it matter which one I do? But if there’s something you can actually look at, even if it’s just the debug output of your mailbox parser, it’s like, OK, there! That’s something; what’s the next direction this needs to go in? OK, instead of just displaying a tree structure, now maybe I should be emitting HTML or something along those lines. Or parsing the headers in a more detailed way. You just look for the next thing to build on from there.
Seibeclass="underline" Do you refactor to keep the internal structure of the code coherent? Or do you just have a very good sense at the beginning how it’s all going to fit together?
Zawinski: I usually have a pretty good sense of that. I don’t remember too many occasions where I thought, “Oh, I did this whole thing inside out. I’m going to have to move everything around.” That does happen sometimes.
When I’m just writing the first version of the program, I tend to put everything in one file. And then I start seeing structure in that file. Like there’s this block of things that are pretty similar. That’s a thousand lines now, so why don’t I move that into another file. And the API sort of builds up organically that way. The design process is definitely an ongoing thing; you never know what the design is until the program is done. So I prefer to get my feet wet as early as possible; get something on the screen so I can look at it sideways.
Also, once you start writing the code, you’re gonna realize, “No, that was a dumb idea. Why did I think that this module was going to be really easy when actually it’s way more complicated than I thought?”
Which is something you’re not going to clue into until you actually start writing code and you feel it getting away from you.
Seibeclass="underline" What are the signs that something is getting away from you?
Zawinski: When you go into something and you have in your head, “Oh, this is going to take me half a day and it’s gonna be a chunk of code this size,” and then you start doing it and you get that sinking feeling like, “Oh, right, I need this other piece too; well, I’d better go off and do that. Oh, and that’s kind of a big problem.”
Seibeclass="underline" I’ve noticed that one thing that separates good programmers from bad programmers is that good programmers are more facile at jumping between layers of abstraction—they can keep the layers distinct while making changes and choose the right layer to make changes in.
Zawinski: There’s definitely got to be some style in where you decide to put things—it can matter a lot down the line. Being able to just hack it out somewhere up near the user versus making a maybe larger change that may have repercussions down at the bottom—either of those can be the right answer and it is tricky to know which is which.