My dad was a mechanical engineer, who spent his career designing
spacecraft. I remember back even in the early days of the space program
how he and his colleagues analyzed seemingly every aspect of their
creations' behavior. Center of gravity calculations insured that the
vehicles were always balanced. Thermal studies guaranteed nothing got
too hot or too cold.
Detailed structural mode analysis even identified how the system
would vibrate, to avoid destructive resonances induced by the brutal
launch phase. Though they were creating products that worked in a harsh
and often unknown environment, their detailed computations profiled how
the systems would behave.
Think about civil engineers. Today no one builds a bridge without
"doing the math." That delicate web of cables supporting a thin dancing
roadway is simply going to work. Period. The calculations proved it
long before contractors started pouring concrete.
Airplane designers also use quantitative methods to predict
performance. When was the last time you heard of a new plane design
that wouldn't fly? Yet wing shapes are complex and notoriously
resistant to analytical methods. In the absence of adequate theory, the
engineers rely on extensive tables acquired over decades of wind tunnel
experiments. The engineers can still understand how their product will
work—in general—before bending metal.
Compare this to our field. Despite decades of research, formal
methods to prove software correctness are still impractical for real
systems. We embedded engineers build, then test, with no real proof
that our products will work. When we pick a CPU, clock speed, memory
size, we're betting that our off-the-cuff guesses will be adequate
when, a year later, we're starting to test 100,000+ lines of code.
Experience plays an important role in getting the resource
requirements right. All too often luck is even more critical. However,
hope is our chief tool, and the knowledge that generally, with enough
heroics, we can overcome most challenges.
In my position as embedded gadfly, looking into thousands of
projects, I figure some 10"15% are total failures due simply to the use
of inadequate resources. The 8051 just can't handle that fire hose
of data. The PowerPC part was a good choice but the program grew to
twice the size of available Flash, and with the new cost model the
product is not viable.
Recently I've been seeing quite a bit written about ways to make our
embedded systems more predictable, to insure they react fast enough to
external stimuli, to guarantee processes complete on time. To my
knowledge there is no realistically useful way to calculate
predictability. In most cases we build the system and start changing
stuff if it runs too slowly.
Compared to aerospace and civil engineers we're working in the dark.
It's especially hard to predict behavior when asynchronous activities
alter program flow. Multitasking and interrupts both lead to
impossible-to-analyze problems.
Recent threads on USENET, as well as some discussions at the
Embedded Systems Conference, suggest banning interrupts altogether! I
guess this does lead to a system that's easier to analyze, but the
solution strikes me as far too radical. I've built polled systems.
Yech.
Worse are applications that must deal with several different things,
more or less concurrently, without using multitasking. The software in
both situations is invariably a convoluted mess.