Thus, writing a clever piece of code that works is one thing; designing something that can support a long-lasting business is quite another. Commercial software design and production is, or should be, a rigorous, capital-intensive activity. Software products should be based on a broad, deep structure that can support much more than whatever the product contains at any given time. In addition to code that works, you need documentation, help functions, error handling, multi-platform support, and multiple languages. You also need an underlying architecture that allows you to add and change features, purchase and integrated external software components, and allows other software vendors to make their products talk to yours, add customized widgets to it, embed your product inside something larger of their own. A good architecture, one that will carry you for a decade's worth of unpredictable technology and marked changes, take months to develop. But if you skip this step, as Netscape did, you have made a truly Faustian bargain. The problem with this [building just what you need, instead of planning ahead] is that these systems start getting ferociously complicated. It comes time to fix a mistake, add a feature, replace something and you discover that everything is connected to everything else in ways you can't even begin to understand. Because you're doing something more ambitious than the initial academic prototype, it's big enough that you need to partition it across a team. The members of the team need to have a clear idea of how their work relates to everyone else's, and they need to be able to communicate to the testers whose job it is to find errors. Otherwise [in other words], you give the patient a kidney transplant and his heart suddenly fails; then you give him a heart drug, but that makes his lungs collapse. You don't know why, and you're screwed. And then the future comes, and you're really screwed. Later releases of the product inevitably are more complex, because they must continue to support previous version while adding new capabilities. You discover that the original developers have quit or been promoted or have forgotten what they did, and it's time to keep up with the competition by adding new features, supporting more platforms, translating into Japanese, and so forth. The engineering team has to quadruple in size. You start discovering things like three different groups need to change the same piece of code, and each set of changes causes problems for the others, and nobody else can test their work until that piece of code is stable, so a hundred people twiddle their thumbs for a week. Or you want to use an existing function for some new purpose, but you can't isolate it from everything else, so you have to write it all over again. This not only means that you have the extra time and cost of writing and maintaining twice as much code, but you probably have to ensure that the two versions work exactly alike, which they almost certainly won't. With each successive release, these problems get worse. By the time you're on your fifth release, the decision to do your first product the quick and dirty way has probably cost you ten times what it originally saved. A program like Microsoft's Windows 98 is tens of millions of lines of code. Nobody can keep that much complexity in their head or hope to manage it effectively. So you need an architecture that says to everyone, "Here's how this thing works, and to do your part, you need to understand only these five things, and don't you dare touch anything else."