The Right Approach to Exceptions

Jonathan M Davis jmdavisProg at gmx.com
Thu Feb 23 16:06:02 PST 2012


On Thursday, February 23, 2012 15:18:27 H. S. Teoh wrote:
> On Thu, Feb 23, 2012 at 12:07:40PM -0800, Jonathan M Davis wrote:
> In my book, a linked library shares equal status with the "main
> program", therefore the definition of "user input" still sits at the
> internal-to-program and external boundary.

Yes, "in your book." Some people will agree with you and some won't. It really 
depends on what the code is doing though IMHO. In some cases, one is better 
and in some cases, the other is better. But it _is_ important to remember that 
there's a big difference between linking against a library over which you have 
control and a 3rd party library.

And there are times when it just plain makes more sense to have a function 
which throws an exception on bad input regardless of whether it's an 
"internal" function or not. For instance, if you want to convert a string to 
something else (e.g. with SysTime's fromISOExtString or even just with 
std.conv.to), you need to actually verify that the string has a value which 
can be correctly converted. It's actually cheaper to have the function doing 
the conversion do the checking rather than have another function do a check 
first, and then have the converting function not check (save perhaps for an 
assertion outside of release mode), because then you'll be processing the 
string _twice_.

This is _not_ a cut-and-dried issue. Sometimes DbC makes more sense, and 
sometimes defensive programming does. You pick the one that works best for a 
given situation.

The whole thing is a gray area, and you're not going to get a consensus that a 
library should always use DbC on its functions or that it should always use 
defensive programming.

> > Arguably, the best thing would be if there was a way for the caller to
> > indicate whether it wanted the callee to have DbC enable and possibly
> > even indicate whether it wanted the callee to use DbC or defensive
> > programming. But there's no way to do that in D, and I'm not sure that
> > it could even be done with the C linking model - at least, there's no
> > way to it without templatizing everything and giving an argument to
> > the template indicating what you want, which obviously isn't a good
> > solution (and won't work at all in the case of virtual functions,
> > since they can't be templatized).

> No need to templatize anything, just ship two versions of the library,
> one with DbC compiled in, one without. Let the user decide which one to
> link in.

There _is_ a need to do that if the caller wants to control whether an 
assertion or an exception is used. There's also a need if you want to enable 
it in some places and not in others. However, the reality of the matter is 
that using a debug version of a library is as close as you're likely to get. 
And I'm certainly not arguing that templatizing functions in this manner would 
be a good idea. I'm just pointing aut that there are issues with how DbC is 
currently implemented.

And the primary problem with how DbC is implemented is the fact that its 
assertions test the caller, not the callee, but the assertions end up in the 
callee. So, the assertions are separated from the code that they're actually 
testing. It's the best that we can do at this point, but it does result in a 
weird situation where you end up using assertions to test _other_ people's 
code rather than your own.

- Jonathan M Davis


More information about the Digitalmars-d mailing list