The Right Approach to Exceptions
Jonathan M Davis
jmdavisProg at gmx.com
Sun Feb 19 23:38:45 PST 2012
On Monday, February 20, 2012 01:10:39 Andrei Alexandrescu wrote:
> On 2/20/12 12:44 AM, foobar wrote:
> > I just died a little reading this. Are you suggesting that in order
> > to handle IO exceptions I need to: try { ...whatever... } catch
> > (PackageException!"std.io") {...} } catch
> > (PackageException!"tango.io") {...} } catch
> > (PackageException!"otherLib.io") {...} ...
> >
> > What the hell is wrong with just using an IOException?
>
> There's nothing wrong, but there's a possible misunderstanding. If
> tango.io and otherLib.io cooperate with std, then they'd originate
> exceptions in std.io (as opposed to their own). Do note that the issue
> is exactly the same if libraries use IOException - they all must agree
> on using the same nomenclature, whether it's called
> PackageException!"std.io" or IOException.
>
> ModuleException and PackageException have one important thing going for
> them: they automate away a good amount of boilerplate, which makes them
> interesting for me to look at, and worth sharing as long as we're
> brainstorming. The associated issues as clear as the advantages.
> Probably ModuleException is too specific to be interesting, but
> PackageException seems useful.
It saves no boilerplate at the catch point, because you have to know what
you're catching to do anything useful with it. It could be that you choose to
catch a common exception rather than a specific one (e.g. IOException instead
of FileException), but regardless of whether you use templates or mixins or
whatever to generate the exception type's source code, you still need to write
the handling code by hand. Handling code is _not_ the sort of thing that can
be automated.
And as for saving boilerplate in defining exceptions, well some of that could
be done via mixins, but since useful exceptions often have additional member
variables, you're going to have to write many of them by hand anyway. _Some_
exceptions _could_ be done via mixins and the like when it's their type that
matters and that's it, but I question that that's enough boilerplate to be a
big deal - especially since it's not likely we should be adding exception
types all the time.
I think that you're overestimating the amount of boilerplate code involved,
and there are easy ways to reduce it without making exceptions be tied to
modules or packages.
And as has been said before, ultimately the module that an exception comes
from doesn't mean much. It's what went wrong that matters. And ideally, the
standard library would have exception types that user code would throw or
derive its own exception types from, in which case the exception types get
even more divorced from the modules that they're declared in. So, ultimately,
tying exceptions to modules or packages is _not_ a good idea in the general
case. Sometimes it makes sense - particularly if you're talking about making a
base exception type which a project as a whole uses (e.g. a PostgresException
for a postgres library) - but in general, it's a bad approach, and it's one
that we should be moving away from.
I say that we organize Phobos' exceptions into a proper hierarchy and then let
other D projects derive from them or not as they see appropriate. But a
standard set of exceptions should help standardize exceptions in D in general,
even if not all libraries and projects choose to derive their exception types
from the standard library's exception types.
We don't need to do anything elaborate with how exceptions are defined. We just
need to organize them into a hierarchy. And it's not like we even have all
that many exceptions to organize at the moment.
This thread was started due to a legitimate problem - the fact that our
exception types are not always well chosen and definitely aren't always well
organized. But that doesn't mean that we need to do anything new or fancy to
fix the problem either.
- Jonathan M Davis
More information about the Digitalmars-d
mailing list