Seibel: So if you changed jobs and went somewhere where they programmed C or Java in a different style than you prefer, would you say, “Well, I’ll switch and I know that after a little bit, I’ll be happy to see this style”? Or would you just not take the job?
Crockford: Maybe that’s something that people should look at—what is the house of style here? Are we on the left or the right? And maybe not go work at a place that gets them on the wrong side. It does take on a Dr. Seuss quality where you get really upset about whether you’ve got a star on your belly or not. Ultimately you have to embrace the house style and you hope that the people who put the house style together knew what they were doing. They probably didn’t; maybe it doesn’t matter. It’s more important that everybody be on the same page.
Seibel: So when you’re reading code you start with a typographical cleanup, how deeply or dramatically do you refactor things?
Crockford: I’ll rearrange code so that everything is declared and set up before it’s called. Some languages give you a lot of flexibility around that so you don’t have to. I don’t want that flexibility.
Seibel: So you want no forward references?
Crockford: Right, or if there is a forward reference, I want it to be explicit. I don’t want code to come in any random order unless I’m doing a literate programming thing in which I’m explicitly breaking the code in terms of a presentational order rather than the order that the language wants, and I like that a lot. But unless you’re actually using literate tools, you shouldn’t be doing that.
Seibel: In one of your talks you quoted Exodus 23:10 and 11: “And six years thou shalt sow thy land, and shalt gather in the fruits thereof: But the seventh year thou shalt let it rest and lie still” and suggested that every seventh sprint should be spent cleaning up code. What is the right time frame for that?
Crockford: Six cycles—whatever the cycle is between when you ship something. If you’re on a monthly delivery cycle then I think every half year you should skip a cycle and just spend time cleaning the code up.
Seibel: So if you don’t clean up every seventh cycle you may be faced with the choice of whether or not to do a big rewrite. How do you know when, if ever, it’s time for a big rewrite?
Crockford: Generally the team knows when it’s time. Management finds out a lot later. The team is getting beat up pretty regularly, making too many bugs; the code’s too big, it’s too slow; we’re falling behind. They know why. It’s not because they became stupider or lazier. It’s because the code base is no longer serving the purpose that it needs to.
It’s a really difficult thing for management to see, particularly managers who are not programmers. But even programming managers have trouble with this because you’ve seen that you’ve invested so much time to get to this point. And starting over means we’ve got to go all the way back to there and bring it up. And in the meantime we’re not going to be going forward on anything else and it’s just impossible. No, we go forward with what we have.
The fallacy is that it’s going to take that amount of time again, though there are counterexamples. You’ve got the second-system problem where people who’ve had some success are given a blank slate and allowed to do whatever they want. Generally, they will fail because they’ll be too ambitious, they won’t understand the limits. And you get nothing out of that. You have to have extreme discipline to say, “It’s not a blank slate; it’s reimplementing what we had here; it’s doing what we knew.”
Part of what makes programming difficult is most of the time we’re doing stuff we’ve never done before. If it was stuff that had been done before we’d be reusing something else. For most of what we do, we’re doing something that we haven’t done before. And doing things that you haven’t done before is hard. It’s a lot of fun but it’s difficult. Particularly if you’re using a classical methodology you’re having to do classification on systems that you don’t fully understand. And the likelihood that you’re going to get the classification wrong is high.
Seibel: By “classical” you mean using classes.
Crockford: Right. I’ve found it’s less of a problem in the prototypal world because you focus on the instances. If you can find one instance which is sort of typical of what the problem is, you’re done. And generally you don’t have to refactor those. But in a classical system you can’t do that—you’re always working from the abstract back to the instance. And then making hierarchy out of that is really difficult to get right. So ultimately when you understand the problem better you have to go back and refactor it. But often that can have a huge impact on the code, particularly if the code’s gotten big since you figured it out. So you don’t. So you keep bundling these new things on top of it to try to patch the problems that were in the original hierarchy and it gets cruftier and worse.
Seibel: But you do think that refactoring can work, if you take every seventh interval to do it? You don’t have to end up needing a big rewrite?
Crockford: I think it can work. Throw it out and start over should only be considered in the cases where you didn’t do that or you did it badly or something went wrong and you’ve got a code base that has become unworkable. And you can make a reasonable judgment that it will be faster to replace it than to fix it.
Seibel: What about the risk that you don’t fully understand what the code you want to rewrite actually does. Because any piece of code contains bits of embedded knowledge—little bits of cruft that are hard-won functionality that you don’t think of when you say, “Oh, we can just rewrite this.”
Crockford: That is a real problem. One of the reasons that we’re in the mess that we’re in is that the Web is so poorly specified. The specifications were incomplete and were largely misinterpreted and many of those misinterpretations have become part of the canon. So these systems are way more complicated than they should be due to those historical reasons. Working at that level, yeah, I have huge sympathy for that, that there is a lot of undocumented knowledge that is reflected in the code base.
Microsoft has a similar problem with their operating systems, in that they shipped crap for too many years and then they had to remain compatible with all the bad stuff that was based on the bad stuff that they had done. And so the constraints that puts on the design of their next system are just horrendous. So it’s really hard going forward with that. Ultimately they may find that they can’t go forward anymore either.
Those sort of specification errors are really, really hard. And we have them in the Ajax world. Most of our problems in the Ajax world are due to the differences at the browser level. Doing the cross-browser stuff is much harder than it should be because the Web is not specified well and because the implementations are so variable.
We’ve gotten a lot better at that over the last few years, particularly with the advent of the Ajax libraries. Most of them do a very good job—not a complete job yet—but a pretty good job of boosting the level of programming that you do. So we’re not having to deal directly with the browser guts; we have a sort of virtualized application layer that we can work on that is fairly resilient and pretty portable. We have one group here at Yahoo! which is primarily responsible for dealing with the pain that the browser causes. And when they do their job right, it makes it easier for all the other developers here. So that’s good.
Seibel: On the other hand, rewrites don’t always work out. You just mentioned the second-system effect and in one of your talks, you described seeing it in action as “heartbreaking.” When was that?