In article <3b7fb52a_1@dnews>
"Kristofer Skaug" <✉skaug.demon.nl> wrote:
> "Barry Kelly" <✉eircom.net> wrote in message
> news:✉4ax.com...
>
> > > It *is* a virtue to survive errors.
> >
> > If they weren't exceptions, and were error codes instead,
> > and you didn't treat them as seriously as you must
> > exceptions, then you wouldn't be surviving errors -
> > you'd be ignoring them.
>
> there are lots of 'ifs' in that statement.
No there aren't. You show me where the reasoning breaks down:
* You can ignore error codes in your code and your code
will continue blithely onwards to the next statement -
this doesn't happen with exceptions.
* If you consider this behaviour to be a downpoint of
exceptions, then you must see virtue in ignoring error
conditions.
* If you see virtue in ignoring error conditions, you
aren't surviving errors - you are ignoring them.
(this point follows directly)
> > [...]
> Stay tuned...! <g>
I'm more convinced than ever! <g>
> > 1) Faulty input - alert the user.
>
> ok, but I don't see input errors as faults;
> failure *due to* input error is a fault
I ask for an integer. The user enters "x".
* Does my StrToInt routine have a fault for not converting it?
or
* Is the input faulty?
I fear we're losing the semantics here; we need to define "failure",
"fault" and responsibility for input and correction more clearly in
order to say what's best for each case.
> (a decent program should be immune to input errors, i.e. not
> fall over because of it).
And raising an exception which subsequently gets shown
to the user isn't falling over.
"'x' isn't a valid integer value" or something to that effect.
> > 2) Faulty programming - a bug; fixing the bug should be more important
> > than a band-aid.
>
> yes, you want to fix the bug.
> but it is too late and may have caused irreparable damage when it happens
> the first time.
> especially if the means of exposing/publicising the error participates in
> aggravating the consequences.
I have an editor. It's called PFE - Programmer's File Editor. It's at
version 1.01.000, and the author says he's not going to update it any
more.
One day, I opened a Pascal file in it for a quick edit and compile on
the command line. It looked fine in the editor. It looked fine when I
edited it. It looked fine when I saved it. It looked fine.
I tried to compile it. I got some gibberish from dcc32 about some syntax
error. So, I opened the file up again.
The file was a mass of binary characters.
Now, you can say what you like, but that editor continuing and surviving
long enough to save its "buffer" to disk was *lethal*. The sooner it
could have crashed and alerted me, the better.
I just don't believe in what you're advocating. Don't mind that it isn't
a good idea; it isn't even ethical.
> > But what about when you finally decide you can't deal with this
> problem,
> > and you must pass it up to your most senior transaction, and say "I
> > can't do this Boss". He might have to say the same to his boss too;
> this
> > is what exceptions are for. They pass the same / extended letter of
> > failure around so that if the whole process ultimately fails, because
> > the workarounds weren't clever enough, there'll be some documentation
> > that can be placed in the lap of some human somewhere sometime.
> >
> > Error codes can make this very messy; other approaches pass logging
> > objects around. I think exceptions are neater than either.
>
> No it's not really that messy. For example, the way I ususally do this
> is:
This code:
* Loses the concept of natural return value (that is, every
function is effectively a procedure since the return value
has been hijacked for another purpose.
* Requires plumbing in *every* procedure, even if it doesn't have to
do any error management itself.
* Is trying to reinvent exceptions, but maybe you don't know that yet.
* Requires now partially redundant try..finally blocks for cleanup.
> function BigBoss():TErrorInfo;
> var MidError:TErrorInfo;
> begin
> MidError:=MiddleManager();
> Result:=f(MidError);
> end;
> [...]
> function JuniorEngineer():TErrorInfo;
> var LowError:TErrorInfo;
> begin
> try
> LowError:= SomelowlevelAPI;
> except
> LowError:=ERR_API_EXCEPTION;
> end;
> Result:=f(LowError);
> end;
>
> Furthermore, at each level the function can signal error info to the user
> interface if deemed necessary.
I wouldn't dream of letting *my* back end near the user interface. <g>
> Also, the error information is abstracted to an appropriate level in each
> step; for example, BigBoss() cannot use any information about
> ERR_API_EXCEPTION, it has no idea what that means. The only language
> BigBoss understands is MiddleManager saying "We have technical
> difficulties, and have taken steps to fix them". BigBoss on his side
> concludes that "we'll have a 2 week project slip and $180,000 lost
> profit". Of course, all JuniorEngineer() is able to say is
> "SomeLowLevelAPI failed with error code -18907.", a message which is of
> absolutely no use to BigBoss.
> So that's why I feel also, that just passing some low level exception on
> to BigBoss has little actual value.
There are at least three solutions to this.
1) Use exceptions that have an error code that does exactly what yours
does, and use your function(s) to throw anew:
procedure BigBoss();
begin
try
MiddleManager();
except
on e: Exception do
raise f(e);
end;
end;
2) Use exceptions that have a data payload that accumulates
information about errors as it unwinds. Rethrow with a new message,
with more general information prepended to detailed information.
Don't display the detailed information by default; have it in
behind a "More..." box or logged someplace.
procedure JuniorEngineer();
begin
try
LowError:= SomelowlevelAPI;
except
on e: Exception do
raise EMyError.Create(e.Message);
end;
end;
// ...
procedure BigBoss();
begin
try
MiddleManager();
except
on e: EMyError do
raise EMyError.CreateChained(e.Stuff);
on e: Exception do
raise EMyError.Create(e.Message);
end;
end;
> > If you're application needs to print, and you don't care whether it
> > prints or not, then the application shouldn't be designed in such a way
> > as to make the stability of the system state dependant on whether or
> not
> > an exception is raised!
>
> True, there should be an exception handler to protect this.
> The point was, that if the TForm.Print method had simply returned an
> error code I could've skipped that part and just left it as "I've done
> what I can, and I'm not going to try harder; if it fails, it's not my
> fault anyway and the user has to figure it out.". (e.g. printer not
> installed, blablabla). It is an error from a printing perspective, but
> due to the spec of my application ("send job to printer", not "guarantee
> it is printed") it is not a fault, so an exception is inappropriate for
> me at that point.
So let the application handle the exception:
try
Print;
except
on e: Exception do
Application.HandleException(e);
end;
or however it goes. At least it lets the user know that something is
wrong and gives them a clue, instead of leaving them wondering if the
printer is plugged in.
-- Barry
--
If you're not part of the solution, you're part of the precipitate.
Team JEDI: http://www.delphi-jedi.org
NNQ - Quoting Style in Newsgroup Postings
http://web.infoave.net/~dcalhoun/nnq/nquote.html