On Jul 8, 10:24 pm, Andrew Tomazos <and...@tomazos.com> wrote:
On Jul 8, 7:16 pm, Stuart Golodetz
That is not necessarily in contradiction with what I said.
Clearly there is a BALANCE between (A) just quickly
hacking away whatever works; and (B) going through
checklists and formal process at every step. Checking
every function for a list of 20 points is too far toward
B, and will slow down development.
The balance depends on the application. If your program
going wrong could potentially kill me (think code to control
an X-ray scanner, or a large, heavy robot arm in a factory,
or...), I'd want you to be far closer to (B) than (A).
Equally, though, I'd want to make sure that your being
closer to (B) would actually have the desired effect of
making my demise less likely. Checklists of *irrelevant*
points could distract you from making your code safer.
I suspect James might doubt that it will be equally robust.
But thinking about it, I suppose there is an issue of how
you quantify the robustness of your code.
I'm all for avoiding onerous processes, except when they're
necessary (which is sometimes the case).
Robustness is quantified by the degree to which software meets
Amongst other things. (Or are you including "implicit
requirements"? I've never seen a requirements specification
which said that the program shouldn't core dump, but of course,
programs which core dump aren't robust.)
What you are missing is that time saved on onerous process can
be spent on runtime testing/debugging.
Whose talking about an "onerous process"? We're talking about a
means of simplifying, and perhaps even mechanising, part of an
Perfect software is practically impossible for a nontrivial
requirement set. You have to look at how much robustness you
get per unit development time. This is true whether or not
the software is mission-critical and/or potentially
life-threatening. That is what I mean when I say that moving
from the balance point toward (B) doesn't get you more
robustness in the same amount of time.
No. It gets you more robustness in less time, because the
errors are found earlier. Finding an error which only shows up
in a test takes significantly more time than finding one where
the error is pointed out to you immediately in the source code.
In general, the further upstream the error is detected, the less
it costs to find and fix it: an error found in code review costs
less to find and fix than one found in unit tests; an error
found in unit tests costs less to find an fix than one found in
integration tests; and an error found in integration tests costs
less than one found in the field.
Using a check list is simply a way of making some aspects of the
code review more efficient (or even automatic).
If a software application could potentially injure people when
it fails to meet its requirements, than it should be treated
in the same way that a new medical drug is treated. After
feature freeze, a crazy amount of runtime testing is conducted
in a safe controlled environment. Any new changes to the code
must be put through full regression (ie the testing process
much be restarted from scratch).
Don't forget that testing can only prove that a program is
incorrect; it can't prove that a program is correct. For life
critical software, it's usual to require some sort of formal
proofs. And that can be expensive. Generally, judging from my
own experience, anything you do getting the error rate down to
about one error per 100KLoc, going into integration, also
reduces total development costs. Beyond that, I'm not sure.
Formal proofs aren't necessary for that level of quality, but
that level of quality probably isn't acceptable for life
critical software. (But the issue isn't cut and dried. For the
example mentionned, one could argue that the system should be
physically designed so that no matter what the software did, it
couldn't generate an overdose of radiation. I know that when I
worked on a locamotive brake system, the emergency brake
position acted physically, in a way that nothing in the rest of
the system could possibly prevent the brakes from being
Let's take a specific example. Suppose there is a function:
void f(int x);
and that f is not exception safe for all values of x. In fact
when f (3) is called, an exception is thrown in an unexpected
place, and the system misbehaves - zapping the patient with a
deadly amount of X-ray radiation.
But suppose that f(3) can never be called at runtime in the
final application. ie There is no calling site of f where x
can possibly be the parameter 3.
If we were to check f for exception safety, we might find this
f(3) problem and fix it. This will however be a waste of
time, and achieves zero improvement on robustness.
Until some modification elsewhere causes f to be called with 3.
Either f's contract allows it to be called with 3, or it
doesn't. If f's contract allows it to be called with 3, then f
must handle 3 correctly. If it doesn't there should be an
assert at the top of the function, so that the system will fail
(and of course, all calling code should be checked that it
respects the contract).
James Kanze (GABI Software) email:firstname.lastname@example.org
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34