Coders at Work - by Peter Seibel

Jamie Zawinski

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.

Seibel: Earlier you said something about writing code in order to make it easier to read, which ties into maintenance. What are the characteristics that make code easier to read?

Zawinski: Well, comments obviously. Writing down what the assumptions are and what this does. If it's building up a data structure, describing the layout of it. A lot of times I find that pretty helpful.

You've got to say in the comment something that's not there already. What's it for? Either a higher-level or a lower-level description, depending on what's most important. Sometimes the most important thing is, what is this for? Why would I use it? And sometimes the most important thing is, what's the range of inputs that this expects? Long variable names. I'm not a fan of Hungarian notation, but I think using actual English words to describe things, except for loop iterators, where it's obvious. Just as much verbosity as possible, I guess.

I think one thing that's really important is to not be afraid of your ignorance. If you don't understand how something works, ask someone who does. A lot of people are skittish about that. And that doesn't help anybody. Not knowing something doesn't mean you're dumb—it just means you don't know it yet.


Brad Fitzpatrick

Seibel: Do you have any advice for self-taught programmers?

Fitzpatrick: Always try to do something a little harder, that's outside your reach. Read code. I heard this a lot, but it didn't really sink in until later. There were a number of years when I wrote a lot of code and never read anyone else's. Then I get on the Internet and there's all this open source code I could contribute to but I was just scared shitless that if it wasn't my code and the whole design wasn't in my head, that I couldn't dive in and understand it. Then I was sending in patches to Gaim, the GTK instant-messenger thing, and I was digging around that code and I just saw the whole design. Just seeing parts of it, I understood. I realized, after looking at other people's code, that it wasn't that I memorized all my own code; I was starting to see patterns. I would see their code and I was like, “Oh, OK. I understand the structure that they're going with.” Then I really enjoyed reading code, because whenever I didn't understand some pattern, I was like, “Wait, why the fuck did they do it like this?” and I would look around more, and I'd be like, “Wow, that is a really clever way to do this. I see how that pays off.” I would've done that earlier but I was afraid to do it because I was thinking that if it wasn't my code, I wouldn't understand it.

I start too many projects. I finish them because I have guilt if I don't finish them, but I definitely context-switch way too often and I'm spread too thin. This is why I really need pair programming—it forces me to sit down for three solid hours, or even two or one solid hour, and work on one thing with somebody else, and they force me to not be bored. If I hit a bored patch, they're like, “Come on. We've got to do it,” and we finish. I like working alone but I just bounce all over the place when I do. On a plane I'll bring extra laptop batteries and I have a whole development environment with local web servers and I'll be in a web browser, testing stuff. But I'll still be hitting new tabs, and typing “reddit” or “lwn”—sites I read. Autocomplete and hit Enter, and then—error message. I'll do this multiple times within a minute. Holy fuck! Do I do this at work? Am I reading web sites this often that I don't even think about it? It's scary. I had a friend, who had some iptables rule, that on connection to certain IP addresses between certain hours of the day would redirect to a “You should be working,” page. I haven't got around to doing that, but I need to do something like it, probably.

Seibel: In the early days of LiveJournal it seems your life was an endless series of late nights, sleeping late, and overall working long hours. How much of that is a necessary part of programming?

Fitzpatrick: I just thought it was the least stressful time. During the day, there's always something coming up, like another meal is coming up, or a class, or maybe you get a phone call. There's always some interruption. I can't relax. If I go into work two hours before some meeting, that two hours is less productive than if I didn't have that meeting that day or if the meeting was the first thing in the morning. Knowing that I have nothing coming up to bug me, I'm so much more relaxed. At night I feel like this is my time and I'm stealing this time because everyone else is sleeping. There's no noise and no interruptions, and I can do whatever. I still stay up late sometimes. I did it this weekend; I was up quite a bit working on different things. But that screws me up for days sleepwise. I did that mostly when I had to in college, because I had some project, and I was also doing LiveJournal on the side. The only time to do it was at night and also all our server maintenance had to be at night. And then in the summer, just because why not? There's no reason to wake up early in the morning to go to a class or anything, so might as well work at night.

Seibel: So you've hired for your own company, and I assume you've been involved in hiring at Google. How do you recognize a great programmer?

Fitzpatrick: I often look for people that have done, like, a lot of stuff on their own that wasn't asked of them. Not just their school project or just what their previous employer had them do. Somebody who was passionate about something and had some side project. How did they maintain it and how serious did they get with it? Or do they do a lot of quick hacks and abandon them?

Seibel: What do you think is the most important skill for a programmer to have?

Fitzpatrick: Thinking like a scientist; changing one thing at a time. Patience and trying to understand the root cause of things. Especially when you're debugging something or designing something that's not quite working. I've seen young programmers say, “Oh, shit, it doesn't work,” and then rewrite it all. Stop. Try to figure out what's going on. Learn how to write things incrementally so that at each stage you could verify it.


Douglas Crockford

Crockford: One of the things I've been pushing is code reading. I think that is the most useful thing that a community of programmers can do for each other—spend time on a regular basis reading each other's code. There's a tendency in project management just to let the programmers go off independently and then we have the big merge and if it builds then we ship it and we're done and we forget about it. One of the consequences of that is that if you have weak or confused programmers you're not aware of their actual situation until much too late. And so the risks to the project, that you're going to have to build with stuff that's bad and the delays that that causes, that's unacceptable. The other thing is that you may have brilliant programmers on the project who are not adequately mentoring the other people on the team. Code reading solves both of those problems.

Seibel: Can you talk a bit about how you conduct a code reading?

Crockford: At each meeting, someone's responsible for reading their code, and they'll walk us through everything, and the rest of us will observe. It's a really good chance for the rest of the team to understand how their stuff is going to have to fit with that stuff. We get everybody around the table; everybody gets a stack of paper. We also blow it up on the screen. And we all read through it together. And we're all commenting on the code as we go along. People say, “I don't understand this comment,” or, “This comment doesn't seem to describe the code.” That kind of stuff can be so valuable because as a programmer you stop reading your own comments and you're not aware that you're misdirecting the reader. Having the people you work with helping to keep your code clean is a huge service—you find defects that you never would've found on your own. I think an hour of code reading is worth two weeks of QA. It's just a really effective way of removing errors. If you have someone who is strong reading, then the novices around them are going to learn a lot that they wouldn't be learning otherwise, and if you have a novice reading, he's going to get a lot of really good advice. And it shouldn't be something that we save for the end. Back in the old days, we would schedule a code reading just as we were finishing a project and usually it would be canceled because we were late. I now believe that code reading should be happening all the time throughout the life of the project. That's something that took me a while to figure out but there are so many benefits that come from that. For one thing it makes it easier to track the project, because we can actually see what progress people are making. And we can see much sooner if they're going off the rails or not. I've managed projects where we're up against a deadline and we had people saying, “Yeah, I'm almost done,” and then you get the code, and there's nothing there, or it's crap, or whatever, and they're nowhere close to done. In management, those are the experiences you hate the most and I think code reading is the best way of not getting trapped like that.

Seibel: Do you find that you have to teach people how to do code readings? I can imagine it'd be hard to find the right balance of being critical enough to be worthwhile without making the code's author feel personally attacked.

Crockford: Yeah, it requires a lot of trust on the part of the team members so there have to be clear rules as to what's in bounds and what's not. If you had a dysfunctional team, you don't want to be doing this, because they'll tear themselves apart. And if you have a dysfunctional team and you're not aware of it, this will reveal it pretty quickly. There's a lot that you can learn, a lot that's revealed by this process. It feels unnatural at first, although once you get into the rhythm of it, it feels extremely natural. Another aspect is writing your code such that it can be read. Neatness counts, as it turns out, and style is important. And all of those things will increase the quality of the code base going forward and increase the competence of the programming community.

Readability of code is now my first priority. It's more important than being fast, almost as important as being correct, but I think being readable is actually the most likely way of making it correct. So I think it's probably not good code and they probably made the wrong trade-offs if the code turned out to be in the state that it's not easily readable.

Seibel: Do you consider yourself a scientist, an engineer, an artist, a craftsman, or something else?

Crockford: I think of myself as a writer. Sometimes I write in English and sometimes I write in JavaScript. It all comes down to communication and the structures that you use in order to facilitate that communication. Human language and computer languages work very differently in many ways, but ultimately I judge a good computer program by its ability to communicate with a human who reads that program. So at that level, they're not that different.

I want people who can write, because we spend a lot of time writing to each other. We're writing email or documentation. We're writing plans. We're writing specifications. I want to know that the people on my team are capable of doing that, and that turns out to be a really difficult skill. So I would actually rather see people start as English majors than as math majors to get into programming.

Seibel: I think Dijkstra had another quote about that along the lines of, “If you can't write in your native language, give it up.”

Crockford: I agree with that one.


Brendan Eich

When I was an undergrad I was really affected by Pirsig's Zen and the Art of Motorcycle Maintenance. And I had been going through Plato and the early philosophers. I was, at that point, inclined more towards idealism in some philosophical sense. I thought little-endian byte order was superior to big-endian, because after all, the least significant digits are in the lowest address—there was some kind of harmony or geometry in that. But try reading a hex dump. Practical things matter; particulars matter. The famous School of Athens painting with Aristotle pointing down and Plato pointing up—I'm more on the pointing-down side now. As I get older I get more and more skeptical and more and more interested in what works. When I'm interviewing people, when I'm looking for talent, it's very hard for me to not stick with particulars and practicalities.


Joshua Bloch

Seibel: Are there any books that every programmer should read?

Bloch: An obvious one, which I have slightly mixed feelings about but I still think everyone should read, is Design Patterns. It gives us a common vocabulary. There are a lot of good ideas in there. On the other hand, there's sort of a mish-mash of styles and languages, and it's beginning to show its age. But I think it's absolutely worth reading. Another is Elements of Style, which isn't even a programming book. You should read it for two reasons: The first is that a large part of every software engineer's job is writing prose. If you can't write precise, coherent, readable specs, nobody is going to be able to use your stuff. So anything that improves your prose style is good. The second reason is that most of the ideas in that book are also applicable to programs.

Another old one is Frederick Brooks's The Mythical Man Month. It's 40 years old and still as true today as when it was written. And it's just a joy to read. Everyone should read that. The main message of the book is “adding people to a late software project makes it later,” and it's still true. But there are a lot of other important things in it. Some of the details are beginning to age, but everyone should read it anyway.

Seibel: Other than naming your variables better, and cutting and pasting less, is there anything else about how you approach programming that has changed as you gained experience?

Bloch: The older I get, the more I realize it isn't just about making it work; it's about producing an artifact that is readable, maintainable, and efficient. Generally speaking, I find that, contrary to popular belief, the cleaner and nicer the program, the faster it's going to run. And if it doesn't, it'll be easy to make it fast. As they say, it's easier to optimize correct code than to correct optimized code.

Seibel: Can you say anything about how to speed up the process of getting to fluency in a new language?

Bloch: I think it's a lot like spoken languages. One way is by knowing a lot of languages—if you already know Italian and Spanish and you want to learn Portuguese, you're not going to have a very hard time doing it. The more you know, the more you have to draw on. When you're learning a new language, come in with all that you've learned, but remain open-minded. I know people who have sort of decided, “This is the way that all programs should be written.” I won't mention any languages, but some languages, for whatever reason, cause people to get this way. Whenever they go to a new language, they criticize it to the extent it isn't like God's true language, whatever that happens to be. And when they use the new language, they try to program in God's true language to the extent that you can in the new language. Often you're missing what makes a language special if you do that. It's like if the only tool you have is a hammer and someone gives you a screwdriver, and you say, “Well, this isn't a very good hammer but I guess I can hold the blade in my hand and whack with the handle.” You have a crappy hammer when in fact you could have used it as a fine screwdriver. So, a combination of open-mindedness and a willingness to apply everything you already do know. And of course, code, code, code! The more you use the language, the faster you'll learn it.

Seibel: What is your process for designing software? Do you fire up Emacs and start writing code and then move it around until it looks right? Or do you sit down on your couch with a pad of paper?

Bloch: The most important thing is to know what you're trying to build: what problem you're trying to solve. The importance of requirements analysis can't be overstated. Coming up with a good set of use cases is the most important thing you can do at this stage. Once you have that, you have a benchmark against which you can measure any possible solution. It's OK if you spend a lot of time getting it reasonably close to right, because if you get it wrong, you're already dead. The rest of the process will be an exercise in futility.

So get those use cases and then write a skeletal API. It should be really, really short. The whole thing should, usually, fit on a page. It doesn't have to be terribly precise. You want declarations for the packages, classes, and methods and, if it's not clear what they should do, then maybe a one-sentence description for each. But this is not documentation of the quality that you will end up distributing. The whole idea is to stay agile at this stage, to flesh the API out just enough that you can take the use cases and code them up with this nascent API to see if it it's up to the task. It's just amazing, there are so many things that are obvious in hindsight but when you're designing the API, even with the use cases in mind, you get them wrong. Then when you try to code up the use cases you say, “Oh, yeah, this is fundamentally wrong; I have too many classes here; these should be combined, these need to be broken out,” whatever it is. Luckily, your API doc is only a page long, so it's easy to fix it. As your confidence in the API increases, then you flesh it out. But the fundamental rule is, write the code that uses the API before you write the code that implements it. Because otherwise you may be wasting your time writing implementation code that won't get used. In fact, write the code that uses the API before you even flesh out the spec, because otherwise you may be wasting your time writing detailed specs for something that's fundamentally broken. That's how I go about designing stuff.

As I write the program, I say to myself, what it is that must be true here? And it's very important to put those assertions into the code, to preserve them for posterity. If your language lets you do it with an assert construct, use it; if not, put assertions in comments. Either way, the information is too valuable to lose. It's what you need to understand the program six months down the road, and what your colleague needs to understand the program any time at all.

Seibel: OK, different topic: how do you prefer to work with other programmers?

Bloch: I'm actually quite flexible. I love “buddy programming” where you're working with someone else but not at the same keyboard. You're writing different parts of the system—you trade the code back and forth. You don't even have to be in the same hemisphere. Doug Lea and I have worked that way extensively over the years. One of us will write an interface and the other one will say, “Well this is great but this part sucks and I changed it this way.” Eventually we arrive at some interface that we like and I'll implement the nonconcurrent version and he'll implement the concurrent version and as we do that, we'll find out all the things that we did wrong and take another crack at the interface. And we'll read each other's code and he'll say, “Well, you can make this much faster this way,” and I'll say, “You're right, Doug, you can.” He's very good at making things go fast—he kind of communes with the VM. So that's one style that I like a lot. And that lends itself to remote collaborations. I do like sitting at the same terminal with someone and working on code, but I haven't written many programs that way from the ground up. Typically it's in the context of a code review where I'll get some code to review and there'll be a lot of changes and I'll say, “Why don't we just sit together at a machine and bash it into shape?” That's good for a whole bunch of reasons. I think it's a great way to teach, to pass knowledge down from one generation of hacker to the next. I don't like working in total isolation. When I'm writing a program and I come to a tricky design decision, I just have to bounce it off someone else. At every place I've worked, I've had one or more colleagues I could bounce ideas off of. That's critically important for me; I need that feedback.

Seibel: Is that for the feedback you get or just for the chance to talk it through?

Bloch: Both. There's so much craft in what we do—it's often the case that there's no one right solution, or if there is, it's not apparent until you've used it. You have to go from the gut and talking to someone with a different perspective can be very helpful. I've known people who don't feel this way—who are willing to program in a vacuum. I think it hurts them. You will discover your bugs earlier—you really want to discover problems with a design long before it hits the point of code. So when you're wrestling with different approaches or even different features—should I support this and this or simply that—you just have to bounce it off other people. On the other hand, you can't take what each person says as gospel because you'll get conflicting opinions, and ultimately, you are responsible for your own work.


Joe Armstrong

Seibel: Comparing how you think about programming now with how you thought when you were starting out, what's the biggest change in your thinking?

Armstrong: The second thing that's happened is intuition. When I was younger, I would do the all-night hacks, programming to four in the morning and you get really tired and it's macho programming—you hack the code in hour after hour. And it's not going well and you persevere and you get it working. And I would program when the intuition wasn't there. And what I've learned is, programming when you're tired, you write crap and you throw it all away the next day. And 20 years ago I would program although I was getting a strong feeling that this isn't right—there's something wrong with this code. I have noticed over the years, the really good code I would write was when I'm in complete flow—just totally unaware of time: not even really thinking about the program, just sitting there in a relaxed state just typing this stuff and watching it come out on the screen as I type it in. That code's going to be OK. The stuff where you can't concentrate and something's saying, “No, no, no, this is wrong, wrong, wrong”—I was ignoring that years ago. And I'd throw it all away. Now I can't program anymore if it says, “No.” I just know from experience, stop—don't write code. Stop with the problem. Do something else. Because I was good at math and that sort of stuff at school, I thought, “Oh, I'm a logical person.” But I took these psychology tests and got way high scores on intuition. And quite low scores on logical thinking. Not low—I can do math and stuff; I'm quite good at them. But because I was good at math I thought science was about logic and math. But I wouldn't say that now. I'd say it's an awful lot of intuition, just knowing what's right.

Seibel: So now that you spend more time thinking before you code, what are you actually doing in that stage?

Armstrong: Oh, I'm writing notes—I'm not just thinking. Doodling on paper. I'm probably not committing much to code. If you were to monitor my activity it'd be mostly thinking, a bit of doodling. And another thing, very important for problem solving, is asking my colleagues, “How would you solve this?” It happens so many times that you go to them and you say, “I've been wondering about whether I should do it this way or that way. I've got to choose between A and B,” and you describe A and B to them and then halfway through that you go, “Yeah, B. Thank you, thank you very much.” You need this intelligent white board—if you just did it yourself on a white board there's no feedback. But a human being, you're explaining to them on the white board the alternative solutions and they join in the conversation and suggest the odd thing. And then suddenly you see the answer. To me that doesn't extend to writing code. But the dialog with your colleagues who are in the same problem space is very valuable.

Seibel: Do you think it's those little bits of feedback or questions? Or is it just the fact of explaining it?

Armstrong: I think it is because you are forcing it to move it from the part of your brain that has solved it to the part of your brain that has verbalized it and they are different parts of the brain. I think it's because you're forcing that to happen.

Seibel: Are there other skills that are not directly related to programming that you feel have improved your programming or that are valuable to have as a programmer?

Armstrong: Writing is. There's some computer scientist that said, “Oh, if you're no good at English you'll never be a very good programmer.”

Seibel: I think Dijkstra had something about that.

Armstrong: I've occasionally been asked to advise people at universities on choice of syllabus subjects for computer science courses, being as how I work for industry—what does industry want? And I say, “Well, turn 'em out being able to write and argue cogently.” Most graduates who come out, and they've got degrees in computer science, writing's not their strong point. I think it's actually very difficult to teach because it's very individual. Somebody's got to take your text and a red pen and explain to you what you did wrong. And that's very time consuming. Have you ever read Hamming's advice to young researchers?

Seibel:You and Your Research”?

Armstrong: He says things like, “Do good stuff.” He says, “If you don't do good stuff, in good areas, it doesn't matter what you do.” And Hamming said, “I always spend a day a week learning new stuff. That means I spend 20 percent more of my time than my colleagues learning new stuff. Now 20 percent at compound interest means that after four and a half years I will know twice as much as them. And because of compound interest, this 20 percent extra, one day a week, after five years I will know three times as much,” or whatever the figures are. And I think that's very true. Because I do research I don't spend 20 percent of my time thinking about new stuff, I spend 40 percent of my time thinking about new stuff. And I've done it for 30 years. So I've noticed that I know a lot of stuff. When I get pulled in as a troubleshooter, boom, do it that way, do it that way. You were asking earlier what should one do to become a better programmer? Spend 20 percent of your time learning stuff—because it's compounded. Read Hamming's paper. It's good. Very good.

Seibel: Do you find some code beautiful?

Armstrong: Yes. Why this is I don't know. The funny thing is, if you give two programmers the same problem—it depends on the problem, but problems of a more mathematical nature, they can often end up writing the same code. Subject to just formatting issues and relabeling the variables and the function names, it's isomorphic—it's exactly the same algorithms. Are we creating these things or are we just pulling the cobwebs off? It's like a statue that's there and we're pulling the cobwebs off and revealing the algorithm that's always been there. So are we inventing a new algorithm or are we inventing a structure that already exists? Some algorithms feel like that. I think it's more the mathematical algorithms. I don't get that feeling when I'm implementing a telephony protocol or something. That's not a statue that I'm pulling the cobwebs off.

Seibel: So that's similar to the beauty of math, because it's part of nature. Then there are other levels at which code sort of has an aesthetic.

Armstrong: Yeah. It's kind of feng shui. I like minimalistic code, very beautifully poised, structured code. If you start removing things, if you get to the point where if you were to remove anything more it would not work any more—at this point it is beautiful. Where every change that you could conceivably make, makes it a worse algorithm, at that point it becomes beautiful.

Seibel: What makes a good programmer? If you are hiring programmers—what do you look for?

Armstrong: Choice of problem, I think. Are you driven by the problems or by the solutions? I tend to favor the people who say, “I've got this really interesting problem.” Then you ask, “What was the most fun project you ever wrote; show me the code for this stuff. How would you solve this problem?” I'm not so hung up on what they know about language X or Y. From what I've seen of programmers, they're either good at all languages or good at none. The guy who's a good C programmer will be good at Erlang—it's an incredibly good predictor. I have seen exceptions to that but the mental skills necessary to be good at one language seem to convert to other languages.


Simon Peyton Jones

Seibel: What is programming to you? Do you think of yourself as a scientist or an engineer or a craftsman? Or something else entirely?

Peyton Jones: Have you read Fred Brooks's paper about this, the one called, “The Computer Scientist as Toolsmith”? I reread it recently. It's very nice. I think it's good to remember that we're concerned with building things. I think that's why programming is so interesting. At the same time I'm really keen on trying to extract principles of enduring value. I have a paper about how to write a good paper or give a good research talk and one of the high-order bits is, don't describe an artifact. An artifact is an implementation of an idea. What is the idea, the reusable brain-thing that you're trying to transfer into the minds of your listeners? There's something that's useful to them. It's the business of academics, I think, to abstract reusable ideas from concrete artifacts. Now that's still not science in the sense of discovering laws. But it is a kind of abstraction into reusable thought-stuff out of the morass of real life that I think is very important.

The most depressing thing about life as a programmer, I think, is if you're faced with a chunk of code that either someone else wrote or, worse still, you wrote yourself but you no longer dare to modify. That's depressing.


Peter Norvig

Seibel: So is there any essential skill needed to be a good programmer? Different domains obviously have different requirements but ultimately is there some commonality to writing code regardless of the domain?

Norvig: You've got to be able to make progress and then improve on it. That's all you need to be able to do in life. You've got to have some idea and say, “Here's the direction to go,” and then be able to say, “Now I've got to refine it.” And refinement can be, “I didn't quite get it right; there are cases I didn't handle,” or it can be, “Now that I understand it better, I'm going to write a tool so that it's more abstract and next time I can write a system like this more easily.” Which I guess is that level of introspection to say, “Where was I going? How did I get there? Is there a better way to get there?” Seibel: So do you think that that skill—essentially make it; debug it; iterate—is a kind of thinking that lots of people should learn, even people who aren't going to ultimately be programmers? If you were making a grade-school or junior-high or high-school curriculum, would you want everyone to be exposed to the idea of programming? Or is it too specialized a skill? Norvig: I think it's specialized. I think it's one example of this type of thinking. But I'd be just as happy if you brought other examples like some type of mechanical problem. “Here's a bunch of pieces. How can I move some water from here to here and get it into this cup?” It doesn't have to be manipulating lines of code. It could be manipulating many kinds of pieces and seeing how they work together.

Seibel: Why is it so tempting to solve a problem we don't really have?

Norvig: You want to be clever and you want closure; you want to complete something and move on to something else. I think people are built to only handle a certain amount of stuff and you want to say, “This is completely done; I can put it out of my mind and then I can go on.” But you have to calculate, well, what's the return on investment for solving it completely? There's always this sort of S-shaped curve and by the time you get up to 80 or 90 percent completion, you're starting to get diminishing returns. There are 100 other things you could be doing that are just at the bottom of the curve where you get much better returns. And at some point you have to say, “Enough is enough, let's stop and go do something where we get a better return.”

Seibel: And how can programmers learn to better recognize where they are on that curve?

Norvig: I think you set the right environment, where it's results-oriented. And I think people can train themselves. You want to optimize, but left to yourself you optimize your own sense of comfort and that's different from what you really should be optimizing—some people would say return on investment for the company, others would say satisfaction of your customers. You have to think how much is it going to benefit the customer if I go from 95 percent to 100 percent on this feature vs. working on these ten other features that are at 0 percent. At Google, I think it's easy because we have this “launch early and often” philosophy. And because of the way the company is, for a number of reasons: one, most of our products we don't charge any money for so it's easy to say, well, go ahead and ship it; how much could they complain? The other one is we're not stamping CDs and putting them in a box so if there's something that's not complete today or even if it has a bug, it's not a disaster. Most of the software is on our servers so we can fix it tomorrow and everybody gets the update instantly. We don't have this nightmare of installing updates. So it makes it easier for us to say, “We're just going to launch things and get some feedback from the users and fix the stuff that needs to be fixed and don't worry about the other stuff.”

Seibel: Why is it so tempting to solve a problem we don't really have?

Norvig: You want to be clever and you want closure; you want to complete something and move on to something else. I think people are built to only handle a certain amount of stuff and you want to say, “This is completely done; I can put it out of my mind and then I can go on.” But you have to calculate, well, what's the return on investment for solving it completely? There's always this sort of S-shaped curve and by the time you get up to 80 or 90 percent completion, you're starting to get diminishing returns. There are 100 other things you could be doing that are just at the bottom of the curve where you get much better returns. And at some point you have to say, “Enough is enough, let's stop and go do something where we get a better return.”

Seibel: And how can programmers learn to better recognize where they are on that curve?

Norvig: I think you set the right environment, where it's results-oriented. And I think people can train themselves. You want to optimize, but left to yourself you optimize your own sense of comfort and that's different from what you really should be optimizing—some people would say return on investment for the company, others would say satisfaction of your customers. You have to think how much is it going to benefit the customer if I go from 95 percent to 100 percent on this feature vs. working on these ten other features that are at 0 percent. At Google, I think it's easy because we have this “launch early and often” philosophy. And because of the way the company is, for a number of reasons: one, most of our products we don't charge any money for so it's easy to say, well, go ahead and ship it; how much could they complain? The other one is we're not stamping CDs and putting them in a box so if there's something that's not complete today or even if it has a bug, it's not a disaster. Most of the software is on our servers so we can fix it tomorrow and everybody gets the update instantly. We don't have this nightmare of installing updates. So it makes it easier for us to say, “We're just going to launch things and get some feedback from the users and fix the stuff that needs to be fixed and don't worry about the other stuff.”

Seibel: A lot of companies say they should do reviews but it's very rarely followed through on. You must, at some level, train people how to do that.

Norvig: I think it was something that had always been done and so people accept it. Well, I shouldn't say that completely. Some people it takes a while to get used to it. One of the typical failure cases is a new hire comes in and they're not used to doing this kind of thing so they just start an experimental branch and they have all their code in there and you keep on telling them, “Gee, you don't have any check-ins yet.” And they say, “Yeah, yeah, yeah, I'm just cleaning it up—I'll check it in tomorrow.” And then another week goes by and another week goes by and eventually they have this one gigantic check-in. And then it's a problem that too much time has gone by, it's hard to evaluate it all at once, and some of the things they're comparing against have changed out from underneath them. Then they see what a headache it is and they learn not to do that.


Ken Thompson

Some people write fragile code and some people write very structurally sound code, and this is a condition of people. I think in almost any language you can write fragile code. My definition of fragile code is, suppose you want to add a feature—good code, there's one place where you add that feature and it fits; fragile code, you've got to touch ten places.


Bernie Cosell

Seibel: Do you have any advice for the many programmers who are self-taught?

Cosell: Write a lot of programs. That's certainly what worked for me. Looking at the various courses I've taken, writing programs is what really did it. Not programming just to while away the hours but specifically, “I ought to learn something about this; why don't I try writing a little program to do it?” That really does it. You can't see how these things work and how they interact until you've done it some. You don't know what programming practices are dangerous until you've seen which ones make your programs take weeks to debug and then seen a good programmer fix it in five minutes. I don't think you can get that from classes. Classes can give you a lot of stuff, but in the end programming is a craft you have to perfect by plying it. If you're lucky, you can do it at work. But even in a work environment, where you're learning on the job, I think that to really be good you have to learn faster than your job will make you learn things. You have to supplement what your job is asking you to do. If your job requires that you do a Tcl thing, just learning enough Tcl to build the interface for the job is barely adequate. The right thing is, that weekend start hacking up some Tcl things so that by Monday morning you're pretty well versed in the mechanics of it.

Another thing that Frank did, on other projects, was design reviews. He had the most scary design reviews and I actually carried that idea forward. People would quake in their boots at his design reviews. This was sort of like taking your orals for your dissertation. He would have a hand-picked collection of people in the audience and you would have to present your design. The people he picked were always good. The thing that made his design reviews so scary is he knew when you were bluffing. I'm sure you've done design reviews where you didn't work on some part of it real well and so you kind of slide past that part. You think you got this right but you didn't really do the analysis so you don't know quite what's going on. He had an instinct, and it was abetted by having a good crew in there, of catching you when you were bluffing, catching you when you hadn't thought it through. The parts that you did absolutely fine hardly got a mention. We all said, “Oh.” But the part that you were most uncomfortable with, we would focus in on. I know some people were terrified of it. The trouble is if you were an insecure programmer you assumed that this was an attack and that you have now been shown up as being incompetent, and life sucks for you. The reality—I got to be on the good side of the table occasionally—was it wasn't. The design review was to help you get your program right. There's nothing we can do to help you for the parts that you got right and now what you've got is four of the brightest people at BBN helping you fix this part that you hadn't thought through. Tell us why you didn't think it through. Tell us what you were thinking. What did you get wrong? We have 15 minutes and we can help you. That takes enough confidence in your skill as an engineer, to say, “Well that's wonderful. Here's my problem. I couldn't figure out how to do this and I was hoping you guys wouldn't notice so you'd give me an OK on the design review.” The implicit answer was, “Of course you're going to get an OK on the design review because it looks OK. Let's fix that problem while we've got all the good guys here so you don't flounder with it for another week or two.”

I have a couple of rules that I try to impress on people, usually people fresh out of college, who believe that they understand everything there is to know about programming. The first is the idea that there are very few inherently hard programs. If you're looking at a piece of code and it looks very hard—if you can't understand what this thing is supposed to be doing—that's almost always an indication that it was poorly thought through. At that point you don't roll up your sleeves and try to fix the code; you take a step back and think it through again. When you've thought it through enough, you'll find out that it's easy.

The other rule is to realize that programs are meant to be read. Even though I'm guilty of writing pages of TECO macros back in my early days, I very quickly—probably when I was working on the PDP-1 time-sharing system and the complexity of the time-sharing system started to sink in— came to the belief that computer-program source code is for people, not for computers.

The other rule is to realize that programs are meant to be read. Even though I'm guilty of writing pages of TECO macros back in my early days, I very quickly—probably when I was working on the PDP-1 time-sharing system and the complexity of the time-sharing system started to sink in— came to the belief that computer-program source code is for people, not for computers. Computers don't care.

Seibel: Did you have particular rules for how much or how little to comment?

Cosell: I don't put a lot of comments in my code because I think you should be writing your code so that it is readable and your algorithms and thoughts are clear in the code. I put comments that say this routine is supposed to do this, and usually some description of how you call it—what do you do when you get exceptions, what the order of the arguments is, and things like that. But the code itself should clearly express what you are doing. The only place I tend to put comments in my code is when my instinct says, “This particular piece of code, even though it works, doesn't clearly state what I'm trying to accomplish.”


Donald Knuth

The first rule of writing is to understand your audience—the better you know your reader the better you can write, of course. The second rule, for technical writing, is say everything twice in complementary ways so that the person who's reading it has a chance to put the ideas into his or her brain in ways that reinforce each other. So in technical writing usually there's redundancy. Things are said both formally and informally. Or you give a definition and then you say, “Therefore, such and such is true,” which you can only understand if you've understood the definition.

So literate programming is based on this idea that the best way to communicate is to say things both informally and formally that are related. And it just provides a natural framework for switching between the natural language, English, and the formal language, C or Lisp or whatever is your formal language, and putting this together. So that, to me, has to be a win for documentation.