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 →