The Bridge-Color Problem and The Engineering of Software

Back To Tips Page

One of the problems we face, both in the construction of software and in its reverse-engineering, is a problem I refer to as the bridge-color problem.

It goes like this: suppose you are an engineer designing a bridge. The bridge is built. When it is built, it has a color.

How do you choose the color?

The bridge color, like most other problems, is an engineering problem. It is based on a number of engineering constraints, which include the constraints imposed by the purchaser.

For example, if you are building a bridge somewhere arbitrary, you can say the color is arbitrary. It can be anything you want.

But if you are building it in downtown Pittsburgh, you have no degrees of freedom at all. It will be Pantone® color thus-and-such, the official Pittsburgh Gold color. There is no other option.

If you are doing the bridge for someone who has budgetary problems, you might be constrained to choose the cheapest color paint. If the paint company is offering a paint which meets every other constraint, but is the overstock of Hot Pink, and is selling for 10% of the cost of any other color, you may have a Hot Pink bridge.

This works unless the county council you are dealing with is homophobic and see such a bridge color as an endorsement of a lifestyle they do not condone. Then you might end up with a Lime Green bridge, although the paint costs twice as much.

If you are building the bridge on, say, the Atlantic Coast, you can use any color you want as long as it is one of the four colors that are available in salt-resistant paint.

It is painted black because all bridges are always painted black. 

It is made of Cor-Ten steel and is not painted at all. 

You can use the $50/gallon paint that only needs to be re-applied every 20 years, or the $20/gallon paint that needs to be applied every five years. Note that the long-term cost in the first case is $50/gallon/20 years but the long-term cost of the second is $80/gallon/20 years. Suppose your bridge requires 1000 gallons of paint. The budget may be better able to handle an every-five-year expenditure of $20,000 than a one-time cost of $50,000, because there is only $30,000 in the total available budget and there is no hope of deficit spending. 

But then, suppose that the painting takes two weeks, and during that time the bridge has to be shut down. Having a major artery shut down every five years, or having the same disruption every 20 years, produces a different analysis of cost.

So we've determined the color. Now what happens?

Five years from now, everyone has forgotten the decision that the bridge needs to be repainted, or for some reason there really is no money available. Now the bridge goes another five years without new paint, and sustains long-term damage that will cost $150,000 to repair. 

Or, everyone forgets why the bridge is Lime Green and they feel compelled to do the new paint job in Lime Green, only this year the color no longer exists in the product line, and to get a custom run of 1000 gallons will cost $70/gallon. This is a legacy maintenance problem. And we're into Reverse Engineering.

So how does all this apply to software?

When you are writing code, you have to have all the subroutines coded to make the program work. Sometimes we write

void WhateverThisDoes(SomeType arg)
    return; // code this sometime soon

or we write

BOOL result = SomeAPIFunction(arg);
   { /* failed */
     DWORD err = ::GetLastError();
     // NYI: code better error handling here
     return FALSE;
   } /* failed */

I always add the comment "NYI:" (Not Yet Implemented). When I get towards the completion of a product, I will scan the code for all the NYI comments and finish up what was intended.

Assuming I remember what I intended. And why was this hole drilled here in the girder?

This is, of course, one of the major differences between how we construct software and how we construct bridges. The entire bridge plan is created and approved before construction starts. Only in some limited contexts do we find the same phenomenon in software (for example, control systems for missiles, nuclear power stations, and medical systems). The rest of the time, we tend to work from the engineering equivalent of a bridge designed on the back of an envelope. Something such as might happen when a corps of engineers has to throw a bridge across a river during an assault. But unlike these temporary structures, our structures tend to last for years, perhaps decades.

Nonetheless, when we are confronted with a software artifact, our problem is to determine which components might need to be painted a different color, or replaced with a different material, or simply cut off and discarded as excrescences with no particular value. This involves attempting to re-create the design space in which the original decisions were made. 

There is no particularly easy way to do this if you are not the original designer. It is hard enough when you are the original designer! But it is critical to recognize that not all decisions, whether of structure, algorithm choice, or data representation, were critical decisions. Some of them were bridge color decisions. And some were unconstrained except, perhaps, by the personal preferences of the original designer, and therefore are not at all deep decisions. 

Note that deep decisions and pervasive effects are separable. A particular choice of representation (a vector or a linked list) can have profound impact on the overall organization of the code. But this does not mean the decision itself was profound. On the other hand, a particular choice of representation might have been a fundamental design choice, and all the code was shaped around this decision. 

What about that Cor-Ten bridge? Well, in my System Programming course and our Device Driver course, I have a catch phrase: "The best synchronization is no synchronization". This means that the best designs are those which require no synchronization at all. Synchronization is like moving surfaces. It is a place in your algorithm that generates friction. As we know from mechanical systems, friction wastes energy and generates heat. The presence of synchronization is a point of contact. Overuse of synchronization is like unlubricated surfaces moving together. Lots of energy wasted; lots of heat generated. So a good bridge design here is one that requires no paint. But like a bridge that is not Cor-Ten, where if you need paint, you have no choice but to use it, when you need synchronization, you must use it. But like any mechanical system, you want to expose the smallest possible "surface area" of the program to rub together.

Next time you look at a bridge, think about how its color came to be.

[Dividing Line Image]

The views expressed in these essays are those of the author, and in no way represent, nor are they endorsed by, Microsoft.

Send mail to with questions or comments about this web site.
Copyright © 1999 The Joseph M. Newcomer Co. All Rights Reserved.
Last modified: May 14, 2011