CAPÍTULO 2: MARCO TEÓRICO
2.6 LA IMPORTANCIA DE LA GEOGRAFÍA EN NUESTRAS VIDAS
It ’ s hard to remember life before the web. Standing in lines to buy stuff and mail-ordering from out-of-date print catalogs were frustrations everyone accepted. But today many of those problems are long gone, replaced by sophisticated software that accepts orders on-line. For instance, Figure 3.6 shows the result of an order I tried to place with
Defender last year. I was tempted to complete the transaction to see my credit card burst into fl ames.
At least they didn ’ t charge tax, though it would be nearly enough to pay off the national debt. Inspection Error List
Project: Author: Function Name: Date:
Rework required?
Location Error Description Major Minor
63 The Code
Thirty-fi ve years ago, as student’s in a college Fortran class, we were admonished by the instructors to check our results. Test the goesintas and goesoutas in every subroutine. Clearly, Defender ’ s clever programmers never got this lesson. And, in most of the embedded code I read today few of us get it either. We assume the results will be perfect. But they ’ re often not. Ariane 5 ’ s maiden launch in 1996 failed spectacularly, at the cost of half a billion dollars, due to a minor software error: an overfl ow when converting a 64-bit fl oat to a 16-bit integer. The code inexplicably did not do any sort of range checking on a few critical variables.
Every function and object is saddled with baggage, assumptions we make about arguments and the state of the system. Those assumptions range from the ontological nature of computers (the power is on) to legal variable ranges to subtle dependency
64
w w w. n e w n e s p r e s s . c o m
Chapter 3issues (e.g., interrupts off). Violate one of these assumptions and Bad Things will happen.
Why should anything be right? Isn ’ t it possible that through some subtle error propagated through layers of inscrutable computation a negative number gets passed to the square root approximation? If one reuses a function written long ago by some dearly departed developer it ’ s all-too-easy to mistakenly issue the call with an incorrect argument or to make some equally erroneous assumption about the range of values that can be returned. Consider:
float solve_post(float a, float b, float c){ float result;
result = (-b + sqrt(b*b -4*a*c))/2*a; return result;}
… which computes the positive solution of a quadratic equation. I compiled it and a driver under Visual Studio, with the results shown in Figure 3.7 .
The code runs happily even as it computes an impossible result, as is C ’ s wont. The division by zero that results when “a ” is zero creates neither an exception nor a signal to the user that something is seriously, maybe even dangerously, amiss.
This simple routine can fail in other ways, too. Consider the square root: we know that a negative argument isn ’ t allowed. But that ’ s not really true; that ’ s an implicit assumption, which may not be correct. In the complex domain different assumptions apply.
Bertrand Meyer thinks languages should include explicit constructs that make it easy to validate the hidden and obvious assumptions that form a background fabric to our software. His must-read Object-Oriented Software Construction (at 1200 pages a massive
65 The Code
tome which is sometimes pedantic but is brilliantly written) describes Eiffel, which supports Design By Contract (DBC, and a trademark of Eiffel Software). This work is the best extant book about DBC.
In important human affairs, from marriage to divorce to business relationships, we use contracts to clearly specify each party ’ s obligations. The response “ I do ” to “ Do you promise to love and to hold … ” is a contract, and agreement between the parties about mutual expectations. Break a provision of that or any other contract and lawyers will take action to mediate the dispute … or to at least enrich themselves. Meyer believes software components need the same sort of formal and binding specifi cation of relationships. DBC asks us to explicitly specify these contractual relationships. The compiler will generate additional code to check them at run-time. That immediately rules the technique out for small, resource-constrained systems. But today, since a lot of embedded systems run with quite a bit of processor and memory headroom, it ’ s not unreasonable to pay a small penalty to get signifi cant benefi ts. If one is squeezed for resources, DBC is one of the last things to remove. What ’ s the point of getting the wrong answer quickly? And those benefi ts are substantial:
● The code is more reliable since arguments and assumptions are clearly specifi ed in writing.
● They ’ re checked every time the function is called so errors can ’ t creep in. ● It ’ s easier to reuse code since the contracts clearly specify behaviors; one doesn ’ t
have to reverse engineer the code.
● The contracts are a form of documentation that always stays in-sync with the code itself. Any sort of documentation drift between the contracts and the code will immediately cause an error.
● It ’ s easier to write tests since the contracts specify boundary conditions.
● Function designs are clearer, since the contracts state, very clearly, the obligations of the relationship between caller and callee.
● Debugging is easier since any contractual violation immediately tosses an exception, rather than propagating an error through many nesting levels.
66
w w w. n e w n e s p r e s s . c o m
Chapter 3● Maintenance is easier since the developers, who may not be intimately familiar with all of the routines, get a clear view of the limitations of the code.
● Peace of mind. If anyone misuses a routine, he or she will know about it immediately. Software engineering is topsy-turvy. In all other engineering disciplines it ’ s easy to add something to increase operating margins. Beef up a strut to take unanticipated loads or add a weak link to control and safely manage failure. Use a larger resistor to handle more watts or a fuse to keep a surge from destroying the system. But in software a single bit error can cause the system to completely fail. DBC is like adding fuses to the code. If the system is going to crash, it ’ s better to do so early and seed debugging breadcrumbs than fail in a manner that no one can subsequently understand.