|For novel ideas about building embedded systems (both hardware and firmware), join the 25,000+ engineers who subscribe to The Embedded Muse, a free biweekly newsletter. The Muse has no hype, no vendor PR. It takes just a few seconds (just enter your email, which is shared with absolutely no one) to subscribe.|
By Jack Ganssle
Keep It Clean
Old fashioned air-cooled Volkswagons required an oil change and valve adjustment every three thousand miles. I change my sailboat's diesel engine's oil and all of the oil and fuel filters every 100 hours of operating time. Every season - if I think of it - I change the oil in that lawnmower I loathe so much.
Jiffy Lube has built an international company around providing this sort of preventative maintenance for cars. No one questions the need to regularly invest a bit of time and money to keep engines running well.
It's a shame we're not so farsighted in the firmware business.
Code is like the oil in an engine. When it gets dirty - nasty, convoluted, patched into an unmaintainable mess - it gums up the application. Eventually, things get so bad the system seizes - it can no longer be improved since the cost of dealing with the chaos is so high.
Many agile methods push continuous refactoring, or rewriting crummy code. Some suggest we rewrite all code that can be improved. Like world peace, it's a great concept that isn't really possible in the grimy trenches of getting a product out the door. Perfection, as desirable as it is, will never override all other considerations.
The second law of thermodynamics says that disorder increases in closed systems. Entropy increases. Programs are no more exempt from this depressing truth than the expanding universe. Successive maintenance cycles increase the software's fragility, making each additional change that much more difficult.
Software is like fish. It rots. Over time, as hastily-written patch after panicked feature change accumulate in the code, the quality of the code erodes. Maintenance costs increase.
As Ron Jeffries has pointed out, maintenance without refactoring increases the code's entropy by adding a "mess" factor (m) to each release. That is, we're practicing really great software engineering all throughout a maintenance upgrade. and then a bit of business reality means we slam in the last few changes as a spaghetti mess.
The cost to produce each release looks something like: (1+m)(1+m)(1+m).., or (1+m)n, where n is the number of releases. Maintenance costs grow exponentially as we grapple with more and more hacks and sloppy shortcuts. This explains that bit of programmer wisdom that infuriates management: "the program is too much of a mess to maintain".
But many advocate starting release N+1 by first refactoring the mess left behind in version N's mad scramble to ship. Refactoring incurs its own cost, r. But it eliminates the mess factor, so releases cost 1+r+r+r., which is linear.
Luke Hohmann calls this "post release entropy reduction." It's critical we pay off the technical debt incurred in being abusive to the software. Maintenance is more than cramming in new features; it's also reducing accrued entropy.
It's sort of like changing the oil on a regular basis to keep things humming smoothing along.