How is Software Like a Skyscraper?
When I first got started working as a software developer, I was a little disappointed that I hardly ever got to build something new. I mean, sure, some of it was new, but the new piece was always added on to the existing system. Adding anything new always seemed to take twice as long as it should because the existing system was complicated, imposed many constraints that were the consequence of past design decisions, and adding something new would end up breaking a few things that you’d then have to fix too.
I was experiencing a common reaction that a brand new software developer has when encountering a legacy system. Almost every developer feels at some point that the best solution would be to scrap the existing system and rewrite it from scratch. And in almost every situation, it is the wrong thing to do.
It’s wrong because building something from scratch take a long time, usually a lot longer than you think, and often a lot longer than you’ve got. For example, Microsoft built the first versions of Windows on top of DOS, their existing operating system, but this was constraining their ability to develop a really secure and solid system, and so in 1988 they launched a team internally to create the successor to DOS and Windows that would become Windows NT.
Without going into the details of the building of Windows NT (for that you can read the book, Show Shopper!: The Breakneck Race to Create Windows NT and the Next Generation at Microsoft), it is significant just to note that even at a “breakneck” pace, the first version of Windows NT wasn’t released until 1993, a whole five years later. And when it was released, it wasn’t very popular because despite the technological advances, all most users could see was that Windows NT could run some, but not all, of their current Windows applications, and it would run them slower while requiring more memory and disk space to do it.
It wasn’t really until Windows XP (released in 2001) that Microsoft released a version of Windows NT that allowed them to retire the old Windows. Microsoft wisely chose to continue to evolve their old DOS-based line of Windows operating systems (with six major releases over that time period) because their users would not have stuck around patiently for a decade waiting for Windows NT to catch up.
One lesson to learn from that example is that it is usually worthwhile to modify an existing system rather than build a new one, and given that, it is worthwhile to make your existing system easy to modify.
In some ways this is analogous to constructing a building. When faced with a choice between remodeling an existing building or knocking it down and building a new one, it is often the best choice to strategically remodel the building you have rather than undertaking the costly and lengthy process of constructing an entirely new building.
One of the great things about working for LinkedIn in New York City is that we are in the Empire State Building. The building itself is a monument to what can be accomplished by renovating an existing platform. The building was completed in 1931. The original builders could not have known that someday it would be wired up for computer networks and WiFi, that the doors would open with RFID cards, or that the elevators would have touch screens and speaking voices.
Yet today the Empire State Building has these things because people figured out ways to retrofit new technology into the existing structure. It was obvious that if these things were to be done, they must work with the existing structure. You can’t just knock down the Empire State Building and build a new one. You can’t tell the more than 20,000 people who work here that they’ll just need to go somewhere else for a few months while it’s closed for renovations. No, the building is simultaneously open for business while also undergoing constant upgrades.
A software developer has to think of building a major software system like building a skyscraper. Most of the time will be spent modifying the existing system, and for those times when you are actually building a new system, you still need to be thinking about how what you are building is built to be built upon.
All programming is maintenance programming.
-- Dave Thomas ( The Pragmatic Programmer)
So, if rebuilding a system from scratch is almost always the wrong thing to do, why is it so common for developers to be tempted to, as it were, knock down the skyscraper and build it up again from the ground? One reason is, as pithily stated by Joel Spolsky, “It’s harder to read code than to write it. [emphasis in the original]” Moreover, the formal education that a future software developer receives in a university computer science program will probably have the student spend much more time writing code than reading code. Only later do you realize that a practicing software developer spends much more time reading code than writing code.
It's harder to read code than to write it.
-- Joel Spolsky ( Joel on Software)
What follows is that if you want to become a better software developer, you should improve your skills at reading code. And even when you are writing code, you must remember that your code will be read many times after it is written. You should strive to write code that not only works, but also is clear and understandable.
When a coworker makes a code review comment on some part of your code (or the old code that is right next to your new code) that is some variation of, “This could be made clearer,” you are actually getting the most valuable feedback. Somebody else just read this code found something that wasn’t easy to understand. If you can fix that now, you’ve just removed a potential source of confusion for every developer who tries to read the same bit of code in the future.
I came upon a recent post by Shaun McCormick pointing out, “Technical debt is only debt in that it hampers agility.” In other words, your code should clear and understandable, but if you also want to avoid incurring technical debt, your code also should afford future changes. You owe it to the next developer who has to read your code and possibly change it not to make their job more difficult than it already is.
Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.
-- Donald Knuth
The most ambitious plan I’ve seen for directing software developers towards making code easier to read came from Donald Knuth, one of the giants who laid the foundation for analysis of algorithms. About 30 years ago he invented a paradigm for mixing computer code with the code’s documentation that put readability as the primary goal.
Knuth slyly chose the call his form “literate” programming with the hope that the name itself would make programmers feel obligated to adopt the practice. “Surely,” he wrote, “nobody wants to admit writing an illiterate program.” and proceeded to endorse the practice with gusto, “In fact, my enthusiasm is so great that I must warn the reader to discount much of what I shall say as the ravings of a fanatic who thinks he has just seen a great light.”
Literate Programming as Knuth envisioned it didn't catch on widely, although it can be argued that documentation generation systems, like javadoc, are partly inspired by it. Knuth himself built a demonstration system. He decided to name his system WEB for the stated reason that (and I find this completely hilarious for the way it unintentionally demonstrates how much the world of computer technology has changed since 1984), “it was one of the few three-letter words of English that hadn’t already been applied to computers. [emphasis added]”
Even without actually adopting Literate Programming, grab onto the sentiment. Write code that not only instructs the computer but also serves to explain to human beings what we want a computer to do. Develop your skill for reading code and improving the readability of code that you modify. Your software systems may not last as long as the Empire State Building, but at least you can save your systems from an untimely visit from the wrecking ball.
Addendum
-- added May 21, 2015--
Based on a number of your comments I thought it worthwhile at add a few points.
First of all, the analogy between software development and skyscraper construction is not perfect. There are many important differences between software and buildings that were pointed out by several of you who know a whole lot more about building construction than I do. And I am told that the Empire State Building was particularly well-built from the quality of materials, excellence of craftsmanship, and even in its innovative team-design approach that made it possible for the entire 102 stories to be erected in 1 year and 45 days. It even underwent an elaborate retrofit, analogous to a "major refactoring", that allowed the building to save millions of dollars each year in energy costs.
Second, in advocating that you should almost never rewrite your software from scratch, a number of you pointed out that I have omitted the flip side -- when should you rewrite your software from scratch? And I inclined the discussion in the never direction by implicitly talking about large mature systems as compared to skyscrapers. But there are very different scales of buildings and software.
Grady Booch made the same analogy, pointing out that with software development, just as with construction, sometimes you're building a doghouse, sometimes you're building a house, and sometimes you're building a high-rise office building, and the process that works for a doghouse won't work for a high rise.
For a small enough software system, a complete rebuild is no big deal. And sometimes even for large systems, a new start is needed because, even knowing that it will be a huge project, it is the best among the available options. See Windows NT above. Some especially unambiguous examples that I've personally been a part of:
- An essential program can no longer be maintained because it was written in VB6. The program was maintained with old tools for years, but eventually there was no alternative to replacing it with something completely different.
- A major system was running on VAX mainframe computers running VMS. The platform is on life support inside HP, which came to own it through acquiring Compaq, having acquired the creators of the platform DEC in 1998. The machines are based on Alpha processors, which HP stopped selling in 2007.
How do you know exactly when it's the right decision to rewrite your major software system from scratch instead of incrementally refactoring your way to your destination? I don't have a complete answer (others might have better answers), just that the decision to scrap the old system and create a new one should be recognized as a major undertaking.
I design products. In return, my Products define me!!! Difference maker across product vision, strategy and go to market.
9 年Interesting read. Surely brought back memories of making code readable as a goo practice when starting my career as a software engineer. Rewrite vs Refactor is a subjective issue - one shoe won't fit all. Liked the analogy to a skyscraper.
Excellent analysis and explanation! I will share it with some programmers..
Inventor | Senior Engineer at Amazon
9 年I've always thought of software more like a burrito.
Experienced Software Engineer and Educator (Retired)
9 年Choosing refactoring versus completely rewriting isn't always an either/or decision. I once worked on a project where we evolved a system by replacing one component at a time, keeping the system live over a period of years while the legacy code, hardware, and networking were eventually all replaced. Although the term Service Oriented Architecture wasn't in vogue at the time, that was the basic approach that we used, and it worked. Was that a complete rewrite or an incremental refactor? Yes, it was both. On a related note, if you're interested in the idea of refactoring physical buildings, be sure to take a look at the book "How Buildings Learn" by Stewart Brand. The analogy between buildings and software is closer than you might expect.
Engineering Manager at Facebook
9 年I enjoyed reading this article. I feel that it touches on two separate but related topics, the cost of refactoring and the cost of rebuilding and I think each of these topics deserves its own separate post. The first is a dilemma that spans refactoring at different scales, ground-up being the most costly. Cost itself though is relative depending on the scale of the change and the benefits to be attained from it. The second dilema is far more controversial and I'd rather not get into at all ;)