By Jack Ganssle

The Failure of Reuse

Published 12/07/2001

Reuse is the holy grail of software engineering, one that is so entrenched in our belief system no one dares to question its virtue. The quest for reusable components is one of the foundations of object oriented programming and all of the tools and languages that OOP has spawned.

Yet, my observations suggest that at least in the embedded space reuse has been a dismal failure.

First, let me define "reuse". We can talk about carrying-over code, or salvaged code, both of which imply grabbing big source files and beating them into submission till a new product appears. Not to knock that; it's much better than starting from scratch each time. But real reuse, though, means leaving the freakin' source code alone. We're in reuse nirvana when we're able to pluck a module from the virtual shelf and drop it in, unchanged.

Martin Griss and others have observed that a module isn't really reuseable till it's been reused three times. No matter how good our intentions, the first time we try to reuse something we discover a facet of the new problem the old module just can't manage. So we tune it. This happens a couple of times till the thing is generally reusable. That's not because we're stupid; it's simply because domain analysis is hard. No one is smart enough to understand how a function might get used in other apps.

It's expensive to do a forward-looking design of a function or module. You'll always save money -in the short term - solving today's very specific problem, ignoring the anticipated demands of future projects. If you elect to pursue a careful program of reuse your projects will initially come in late and over-budget.

Reuse is hard. It's like a savings account. My kids complain that if they stick a few bucks in the bank then that's money they can't use. and it's just a piddling sum anyway. Sure. The value of savings comes after making regular deposits. Ditto for reuse. The cost is all up-front, the benefits come from withdrawals made in later years.

Sure, we all know the long-term outweighs today's concerns. Betcha most bosses won't agree. They'll usually buy into the idea of the benefits of reuse, without being willing to stand the pain of creating the reuseable components. And that's the rub. When the ship date looms closer, most bosses will tell us to toss out any sort of discipline that has long-term benefits in pursuit of a near-term release. So, in practice, reuse often fails since schedules generally dominate over any other parameter.

I also suspect most of us don't want to reuse code. 70% of RTOSes are homebrew, despite at least 100 commercial - free and otherwise - products on the market. Nothing is easier to beg, borrow or buy than an RTOS, yet most of us still refuse to practice even this most simple of all reuse strategies. Why is this? I've heard many specious arguments (too expensive, yet there are plenty of freebies; we don't trust the code, but some are safety certified, etc), plus a few really good arguments (it's all legacy code, no one is willing to make risky changes).

I saw numbers recently that suggested 20% of embedded TCP/IP stacks are home-made. Surely some very few embedded apps do need a highly customized protocol stack. But for the rest of us writing our own must be one of the most incredibly irresponsible waste of talent and dollars imaginable.

I think aggressive reuse is our only hope of salvation from the morass of expensive and unreliable code. Building correct firmware is so difficult that we and our bosses have a fiduciary responsibility to find ways to make it reuseable.

But we're not doing it. Sure it's hard. Yes, it's initially expensive. And of course we cannot reuse everything; a lot of what we build will always be inherently unreusable, like hardware drivers that get tossed with each new spin of the design.

So what's the deal? Why is reuse such a failure? Is the best we can do, or chose to do, is to salvage old source files?