The Right Approach to Exceptions
Andrei Alexandrescu
SeeWebsiteForEmail at erdani.org
Mon Feb 20 07:49:50 PST 2012
On 2/20/12 1:38 AM, Jonathan M Davis wrote:
> On Monday, February 20, 2012 01:10:39 Andrei Alexandrescu wrote:
>> 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.
Absolutely. For catching we're looking for allowing centralization, not
for automation.
> 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.
Again, I think this thread clarified we need the "Variant[string] info;"
member however we define the hierarchy.
Also, I think we can do better than defining the boilerplate constructor
(see e.g. https://github.com/D-Programming-Language/phobos/pull/439).
It's just a function. Consider:
// this goes in the stdlib
void raise(ConcreteException)(string message, Throwable t = null, string
f = __FILE__, size_t l = __LINE__)
{
auto r = new ConcreteException;
r.message = message;
r.file = f;
r.line = l;
r.next = t;
throw r;
}
class AcmeException : Exception {}
Now whenever you want to raise AcmeException, you say
raise!AcmeException("message"). Also, raise may accept additional data
that fills the Variant[string]. That makes exception definitions one-liners.
> 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 tend to agree, particularly because it's easier for people to remember
express names instead of origins encoded by module. Ironically, many of
Phobos' exceptions today follow the exception-to-module correspondence.
Still I think it's worth keeping in mind the possibility of having the
PackageException as a base trail for various exceptions specific to a
package.
Andrei
More information about the Digitalmars-d
mailing list