Faster! Can we design embedded systems faster, cheaper, better?
In the 1940s all software was crafted in machine code. The '50s saw the introduction of the first compiled language, Fortran, which boosted coding efficiency almost overnight. Fortran came at the cost of bigger, slower code, a tradeoff that was then deemed unacceptable by too many engineers. But those who embraced Fortran were proven to be the vanguard of the future.
Today we hear the same arguments about modeling, C++ and Java. Too slow, too big. Yet clearly continuing to crank out millions of lines of C is not going to solve any problems; hand coding is no longer giving the productivity boosts absolutely required to keep up with increasing product demands.
Advanced languages offer us the power of abstraction, of working with higher level views of our project. Abstraction is fundamental to our future. We can no longer afford to be concerned with bits and bytes. Whether you love or hate it, the Windows API gives desktop developers an ineffably rich set of resources only a masochist would care to recreate.
Tools of various flavors are the enabling ingredient in abstracting us from lower level details. The first Fortran compiler, by today's standard laughably simple, gave engineers of the '50s a formidable weapon. Today we have even more choices.
We largely accept the extra overhead associated with compilers. Other tools, all of which abstract us further from the code, cost more in overhead, yet promise faster and better delivery. Modeling tools like UML have been successful in some domains. Too few developers grok LabVIEW and MATLAB, yet they are both important parts of the embedded landscape.
Tools that automatically search out bugs promise much for programmer productivity. Coverity, Klocwork, Polyspace, Green Hills, and GrammaTech all push static analyzers that look for run-time problems. The tools certainly can't find all bugs, but they offer a schedule-cheating weapon that as yet has little market penetration.
Tools that help us write more code faster are but a part of the solution, though. Clearly a new model of reuse is desperately needed. A product composed of a million lines of code is just too big to be built a line at a time, especially when the boss wants it shipped today.
Barring some fantastic new development in software engineering, the future simply must belong to reuse. Until we manage to beg, borrow, steal, or buy huge chunks of the code base, we'll be forever doomed to writing every last bloody line ourselves. That's intolerable.
Reuse means much more than hacking up some code we salvaged from a previous project. It's more than recycling 20% of the firmware. Million-line-plus systems require extreme level of reuse.
But let's define a few terms to show what reuse is, and what it's not. Software salvaging is using code again that was never designed for reuse. That is, hacking away at a base of crummy old source to somehow shoehorn it into a new application.
Carrying-over code is porting firmware from an old project to a new one. Like salvaging, it's largely a matter of heroic source hacking.
True reuse is building systems a component at a time, not a line at a time. It's working with big blocks that work in well-defined ways, without digging into the guts to tweak, debug or improve. Richard Selby found that, when porting old code to a new project, if more than about 25% gets modified, there's not much of a schedule boost. Reuse works best when done in the large.
The gritty truth is, though, that before a package is truly reuseable, it must have been reused at least three times. In other words, domain analysis is hard. We're not smart enough to truly understand the range of applications where a chunk of software may be used. Every domain requires its own unique features and tweaks; till we've actually used the code several times, over a wide enough range of apps, we won't have generalized it enough to have it truly reuseable.
This suggests that reuse is terribly expensive. We spend money like mad making decent code but don't reap the benefits till we've reused it three times. How many of us have the patience and discipline--and time--to create code for a future need? Reuse is like a savings account: there's no value till you've put a lot into the account. The more you invest, the more benefit accrues.
When will we be able to buy big chunks of our applications, rather than write them all from scratch? Is the software IC even possible?
The future belongs to people brave and clever enough to discard old modes of thinking and adopt and create new ideas. We will find ways to design products using previously-written code. The benefits are too compelling to continue building systems a line at a time. It may mean tossing resources, memory, and high-end CPUs at low-end apps. It may mean new tools. Surely we'll design systems differently. Though some of the implementation details are murky today, the outcome is pretty clear.
The biggest change will be in our attitudes, our approach to building products. Someday each of us, supported by management, will recognize two critical factors: firmware is the most expensive thing in the universe, and any idiot can write code. The future belongs to developers who find better ways to build products, not to super-coders.
So, to my friend Kirk and all the rest of the nonengineering world, we do work under enormous scheduling pressures. You, the public, demand it. Your digitally stabilized binoculars, that $100 GPS, the digital camera, and all of the other electronic products that make up your world all come from engineers struggling under impossible deadlines to produce amazingly inexpensive and reliable systems.
Once in a while, when you use one of these systems, think of us! We're back in the lab, working on version 2.0.