On Forests and Trees

When an English speaker is drowning in details that make the big picture hard to see, she might complain, “I can’t see the forest for the trees.”

image credit: Miguel Virkkunen Carvalho (Flickr)

It’s an odd expression, partly ironic and partly humorous. When I hear it, I sometimes think of my sister, who, after moving from Indiana to Utah, complained that the mountains were getting in the way of her view. (Her tongue was firmly in her cheek… :-)

The expression also describes an important problem of software engineering–one that a lot of engineers don’t understand well enough. It’s a problem with generalization.
Continue reading

How Enums Spread Disease — And How To Cure It

Poorly handled enums can infect code with fragility and tight coupling like a digital Typhoid Mary.

Say you’re writing software that optimizes traffic flow patterns, and you need to model different vehicle types. So you code up something like this:

vehicle_type.h

enum VehicleType {
    eVTCar,
    eVTMotorcycle,
    eVTTruck,
    eVTSemi,
};

Then you press your enum into service:

route.cpp

if (vehicle.vt == eVTSemi || vehicle.vt == eVTTruck) {
    // These vehicle types sometimes have unusual weight, so we 
    // have to test whether they can use old bridges...
    if (vehicle.getWeight() > bridge.getMaxWeight()) {

Quickly your enum becomes handy in lots of other places as well:

if (vehicle.vt == eVTMotorcycle) {
    // vehicle is particularly sensitive to slippery roads

And…

switch (vehicle.vt) {
case eVTTruck:
case eVTSemi:
    // can't use high-occupancy/fuel-efficient lane
case eVTMotorcycle:
    // can always use high-occupancy/fuel-efficient lane
default:
    // can only use lane during off-peak hours
}

Diagnosis

The infection from your enum is already coursing through the bloodstream at this point. Do you recognize the warning signs?

  • Knowledge about the semantics of each member of the enum are spread throughout the code.
  • The members of the enum are incomplete. How will we account for cranes and bulldozers and tractors and vans?
  • Semantics are unsatisfying. We’re saying cars are never gas guzzlers or gas savers; what about massive old steel-framed jalopies and tiny new hybrids?

A vehicle that challenges our tidy enum. Photo credit: Manila Imperial Motor Sales (Flickr)

The infection amplifies when we want to represent the enum in a config file or a UI. Now we need to Continue reading

Good Code Is Optimized

(Another post in my “What is ‘Good Code’?” series…)

Yes, optimized.

But for what?

A lot of programmers seem to think that raw speed of execution is the only possible answer. If pushed, they may admit it’s also possible to optimize for minimal memory usage or minimal size of executable. Compilers have switches for that.

Get out of the box. Photo credit: lel4nd (Flickr).

Emerson said, “A foolish consistency is the hobgoblin of little minds.” In modern terms, he was deploring the lazy instinct to accept established wisdom instead of thinking outside the box. And I think optimization is one of those topics where we need a larger vision.

What about optimizing for:

  • Speed of coding (sometimes programmer time is the most constrained resource…)?
  • Ease of use (often, low learning curve and productive users outweighs all other factors…)?
  • Speed of testing (sometimes provably correct is the most important success criterion…)?
  • Full utilization (the major promise of physical-to-virtual-to-cloud migration)?
  • Ease of understanding and maintenance?
  • Integration with external systems?

Selecting the criteria against which you optimize is more than a technical question. It’s a strategic one, driven by business and organizational goals. Programmers who relentlessly pursue speed of execution to the exclusion of other considerations are not doing their teams or their companies a favor.

Action Item

Optimize one function for ease of understanding and maintenance. Make a short list of how your choices were different than they might have been if you optimized for speed of execution.