Article

From:
To:
Kristofer Skaug
Subject:
Re: Exceptions vs Error codes
Newsgroup:
borland.public.delphi.objectpascal

Re: Exceptions vs Error codes

In article <3b802902_1@dnews>
	"Kristofer Skaug" <✉skaug.demon.nl> wrote:

> "Barry Kelly" <✉eircom.net> wrote in message
> news:✉4ax.com...
> > You show me where the reasoning breaks down:
> > <...>
> > * If you see virtue in ignoring error conditions, you
> >   aren't surviving errors - you are ignoring them.
> >   (this point follows directly)
> >
> > I ask for an integer. The user enters "x".
> >
> > * Does my StrToInt routine have a fault for not converting it?
> 
> No: A fault would be, if StrToInt returned some value without somehow
> indicating that it is invalid.

The only way it can do that is for it to return a Boolean value, which
you must check and either raise your own exception or show your own
message, both of which would be non-standard - they would have to be
localized, would have to be checked for consistency, etc.

Exceptions do this much better, IMO.
> > * 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.
> 
> OK let me take a swipe at that:
> To begin with the easy part: input validation - this isn't software
> errors IMO.

It leads to software errors if it isn't validated, though. So validation
is a good thing; if it raises an exception if invalid, we can rest a bit
easier about it being valid.

> The input is generated by a human operator or another
> application or comes from a data file. If this input is not conformant to
> that expected by the program, the program shall robustly reject that
> input and - if possible - allow other input data to be presented.

Exceptions are a good way of freely wandering down one path until the
faulty input is detected - because of our transaction-style programming,
we can safely recover when the exception is raised and returned to the
user / input loop.

> This
> is, in my view, *not* related to error handling as such but rather a
> normal function of any program which takes input from external sources.
> An 'error' in this context (i.e. from the internal application software
> point of view) would only be if the program failed to trap bad input
> data, or unexpectedly reject valid input data; i.e. the application is
> not fulfilling its 'contract' or specification. If the user types an 'x'
> where '0'-'9' was expected, it is a user error but not an error in the
> application as such (i.e. the application did nothing 'wrong').

However, you can hardly say the user is "faulty". That would imply that they should be "fixed". I don't think we're allowed to do that, even if
we want to!

> Going from there: a 'fault' would be a design (specification) and/or
> implementation error in the application which allows the application to
> accept invalid input and treat it as if it were valid. So: user enters
> 'x' and internal converter reports value=185 with no notion of
> irregularity.
> At this point, we have an *error situation* in the software.

We now have a bug and/or condition we cannot control. Our conversion
routine needs to be either replaced or wrapped up in some sanity
checking.

> The error is
> a symptom of a fault (fault being that converter function doesn't react
> to invalid characters in input). The consequence of the error is failure:
> failure of the converter function and illegal / inconsistent data in your
> application which may quickly lead to invalid results.

And error codes instead of exceptions magically prevent this?

> > [editor corrupting source...]
>
> Sounds like we need a counter-example:
> One of my company's software products supports communication links with
> satellites while on ground,
> i.e. during development and testing. [...] They are pretty 
> vulnerable and helpless [...] A surefire way of taking the
> satellite down is to abandon it for more than 5 minutes. 
> A missing comm link will do that for you [...] After a while, 
> distrusting the satellite's maturity (self-sustainment) level, 
> the engineers have little choice but to hit the "emergency 
> power-off" button.

> If my software incurs an anomaly, e.g. due to an I/O error at file level,
> I am *not* going to panic and take the whole software down in one blow,
> because this doesn't offer the users a chance to tell the satellite to go
> to safe mode first, for example.

Exceptions provide an excellent means of preventing this - because it is
easy to create an exception firewall at the top level.

And exceptions still prevent you from continuing in the case of faulty input; describing input as all things external to our control and that enter our program through "outside" means (i.e. aren't compiled in).
> So what I am saying is: *of course* you should *never produce incorrect
> results*. Allowing a source code file to corrupt like you described is a
> prime example of that. But if your software is built out of carefully
> self contained modules then an error in one part of the software should
> stay confined to that part and still allow the rest of the software to
> continue operations until the *user* has determined that he's as ready as
> he can get to quit the application.

I don't really see what this has to do with exceptions vs error codes;
you can get this behaviour with either, and I reckon exceptions
normalize it better. Especially with object-oriented features.

> Now, the follow-on, if you have followed me so far, is this: when you are
> trying to dam up against error propagation (by this I mean a chain
> reaction of more failures following upon a single failure - not the
> passing of information about errors) the exception mechanism, with its
> propensity for automatic self-propagation (and potential disruption of
> state in all layers of software which it transverses) is actually not the
> kind of behaviour you want.

I disagree - because of the transactional nature of most operations, if
a small part fails we must either try harder or fail the larger
transaction. Exceptions provide an excellent means of doing this, and
what's more - they prevent execution from continuing if we don't get a
successful resolution to the problem blocking our path.

Error *recovery* isn't easy; I don't envy the kind of situations you describe. I still think it's easier with exceptions, though.
And you've also got to take note that most people don't need to be so concerned with error recovery - merely rolling back to a previous state will do.
I still don't see a benefit from error codes in this situation, though.
> Sure, if properly dealt with you need not
> incur any new problems, but there is IMO a latent *risk* associated with
> this propagation behaviour which you do *not* see with error codes.

Propagation is *good*, because it prevents the bigger transaction
struggling on in error conditions when the smaller transaction fails.

You must propagate this behaviour even when not using exceptions.
Why not use exceptions to do this?
> Combine this with the fact that many exceptions, especially the low-level
> ones from third-party libraries and components which you have no control
> or visibility upon, are often not justified or based on different error
> handling schemes than your own, and the risk to your application's
> reliability increases.

Embrace exceptions, and these components *fall into line* naturally,
they can *integrate* into your exception handling *beautifully*.

Struggle against the tide if you really want, but don't be surprised if it's hard going.
> I am afraid you close-read me too much here.

Sorry about that.

> Also, I guess more often than not, the
> error info is returned as a var parameter (my favorite parameter list
> closure phrase is 'var isOK:boolean);' - I even have a keyboard macro for
> this one! <g>).

I'm glad I don't have to maintain any of your code.

No offence or anything, but I would just be writing:
  Blah(isOk);   if not isOk then     raise ENotOkError.Create('Blah failed. I don't know why, ' +       'because it didn''t raise an exception.'
Which is a damn site more ugly and less useful than Blah raising an exception of its own.
> > I wouldn't dream of letting *my* back end near the user interface. <g>
>
> ??? you lost me there, I must be getting too serious about this <g>
> What I meant was that, at least in all operational/control classes, I
> always have a messaging event which passes text information to the owner
> of that object, which in turn has its own event for exporting these
> messages again... eventually this upward chain of message passing results
> in a line of log text displayed in the user interface.

Ah, so you have yet another thing doing exactly what exceptions can do
automatically!

<g>
That's a joke. I understand you; a separate log for all your activities.
> I was trying to demonstrate that there are "errors"
> (leading to *exceptions*) which an application might not actually care
> about. [...] we are *not* incurring bad states, no, we 
> simply call some bleeping API
> somewhere, cross our fingers and don't care if it blows up, as long as it
> doesn't blow *us* up. Printing was one example. Trying to locate a
> default e-mail client or web browser is another example. If it's not
> there it's not there. Too bad.
> In these situations it's nice to have error codes, because you can do
> what you want with them.
> Exceptions, you *got to* catch them, or they'll wallop you. So, this puts
> extra constraints on your code.

What about all the people who need to print, and who need to do this
stuff? Should they be forced to rely on return codes just because you
can't be bothered with them?

***
Kristofer, we might have to agree to disagree!
-- 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
FYI: Phrase searches are enclosed in either single or double quotes
 
 
Originally created by
Tamarack Associates
Wed, 09 Oct 2024 16:05:36 UTC
Copyright © 2009-2024
HREF Tools Corp.