Tuesday, December 26, 2006

Functionality Over Elegance

I'm reading Where Wizards Stay Up Late which is a book about the people that invented the internet.  It's the story of ARPA and BBN and the creation of essentially the first computer network.  I ran across an interesting quote from one of the programmers of the first networking gear (the IMP).  Dave Walden said, "There was an infinity of ways we could go wrong, and a substantials number of ways to go right.  Good engineers find one of the ways of going right."  He was pointing out the difference between a computer scientist and a computer engineer.  The scientist looks for the ultimate way of doing things.  The one that trumps all others.  The engineer just looks for a way.*

This isn't to say that all ways are equal.  There are tradeoffs that must be made and their consequences considered.  However, given a time budget, reliability requirements, and performance metrics, a number of solutions often make the grade.  A scientist might continue to investigate which one is best whereas an engineer picks one and moves on. 

The author says it this way:  "At its core, all engineering comes down to making tradeoffs between the perfect and the workable."  He makes the point that when you are trying to ship a product, functionality trumps beauty and elegance. 

As I stated in my essay on the subject of design, sometimes you just need to go with a solution.  It is the job of those of us in the trenches to find a solution and make it work.  It is all too easy to continue to pursue the better in the face of the adequate.  More often than not, doing so leads to overdesign and missed deadlines.  The place where this bites most engineers is in the desire to rewrite.  How often have you heard someone say "This whole module needs to be rewritten."?  Sometimes it really does but more often it comes from a sense of aesthetics.  The code isn't written the way we would have done it or it isn't written as optimally as possible. 

As software engineers, we must remember that the ultimate goal is the shipping of a product.  We must make decisions with that goal in mind.  When faced with the temptation to rewrite a whole section of code, we must resist.  If a simple patch will solve the problem, go with the patch.  The product will thank you.


* The use of engineer and scientist here is my choice, not necessarily Walden's.


  1. Good explanation of the process. I would suspect that Windows products have a good mix of these philosophies depending on the module that you are talking about and the group that was working on it.
    By the way, did you really mean penultimate in the article? I would think that most scientists would say that they are looking for the ultimate solution.

  2. Good catch.  No, I didn't mean penultimate.  I'll change that.
    The philosphy used to develop a product does vary based on the group and on the point in the product cycle.  Early on (like we are now for the next version of Windows), we can afford to spend more time doing research and searching for ultimate solutions.  As we move farther into the product cycle, we start making more engineering decisions.  
    I want to make clear that I'm not saying engineers cut corners.  They should not.  Instead, they make tradeoffs.  There is a particular bar of functionality that you must hit for a product.  Going beyond that bar has diminishing returns.  An example from the IMP project that the quotations come from.  Bob Kahn had an idea that the IMP network could deadlock under certain conditions.  He kept pushing the team to rework their protocols to avoid this situation.  For the intitial release, they pushed back and decided that likelihood of a lockup was too small.  In the end, both sides were right.  The lockups didn't happen in practice with the early ARPAnet but Kahn proved them to exist and they were later fixed.  The decision of the initial engineering team was a good one.  The ultimate solution was to fix the lockups but at that point, they didn't really manifest and so could be dealt with later.

  3. One of the best trade-offs to make is refactoring instead of rewriting.  Have I mentioned refactoring before?  Refactoring makes ugly, awkward code nice to use again, at a fraction of the risk of starting from scratch.
    Triage is process of deciding which bugs/features to work on and something a scientist would really not understand.  Fix them all!  Build them all!  Try working for a product manager with that attitude -- I have.

  4. I once worked with a developer with basically that attitude.  There was an issue we weren't able to fix because it was in code that we didn't have source code to any longer but couldn't pull from the product.  I had come up with a workaround that eliminated 98% of the problem and was having it reviewed.  This one developer kept saying "But it doesn't fix the whole problem.  It isn't good enough."  I know, but the only alternative was to lose all of the functionality.  In the end we went with my fix and all was well.