DIP33: A standard exception hierarchy

Jonathan M Davis jmdavisProg at gmx.com
Tue Apr 2 17:06:51 PDT 2013


On Tuesday, April 02, 2013 22:00:57 Lars T. Kyllingstad wrote:
> On Monday, 1 April 2013 at 23:03:56 UTC, Jonathan M Davis wrote:
> > On Monday, April 01, 2013 13:08:15 Lars T. Kyllingstad wrote:
> >> It's time to clean up this mess.
> >> 
> >> http://wiki.dlang.org/DIP33
> > 
> > Another concern I have is InvalidArgumentError. There _are_
> > cases where it
> > makes sense for invalid arguments to be an error, but there are
> > also plenty of
> > cases where it should be an exception (TimeException is
> > frequently used in
> > that way), so we may or may not want an
> > InvalidArgumentException, but if you
> > do that, you run the risk of making it too easy to confuse the
> > two, thereby
> > causing nasty bugs. And most of the cases where
> > InvalidArgumentError makes
> > sense could simply be an assertion in an in contract, so I
> > don't know that
> > it's really needed or even particularly useful. In general, I
> > think that
> > having a variety of Exception types is valuable, because you
> > catch exceptions
> > based on their type, but with Errors, you're really not
> > supposed to catch
> > them, so having different Error types is of questionable value.
> > That doesn't
> > mean that we shouldn't ever do it, but they need a very good
> > reason to exist
> > given the relative lack of value that they add.
> 
> I definitely don't think we need an IllegalArgumentException.
> IMO, passing illegal arguments is 1) a simple programming error,
> in which case it should be an Error, or 2) something the
> programmer can not avoid, in which case it requires a better
> description of why things went wrong than just "illegal
> argument". "File not found", for example.

If we had IllegalArgumentException, it would likely be the base class for some 
subset of exceptions which were always bad arguments, but it certainly 
wouldn't make sense to use it by itself in most cases. It would just provide a 
convenient way to catch that particular subset of exceptions if you needed to.

In general though, I think that assert covers what IllegalArgumentError is 
trying to do just fine, and where it doesn't, the argument about needing more 
descriptive exceptions applies just as well (e.g. RangeError). So, unless it's 
used as a base class for more descriptive errors, I don't think that there's 
much value in having IllegalArgumentError.

> I didn't really consider contracts when I wrote the DIP, and of
> course there will always be the problem of "should this be a
> contract or a normal input check?" The problem with contracts,
> though, is that they go away in release mode, which is certainly
> not safe if that is your error handling mechanism.

If you're treating Error exclusively as programming errors, then it's really 
no different from AssertError. You're just creating categories for specific 
types rather than using assert for them all. And I would fully expect things 
like RangeError to be compiled out in -release. That's what we've started 
doing in std.range and std.algorithm now that we've got version(assert). So, 
instead of having a function like opIndex assert, it checks and throws a 
RangeError on failure - but it does so in a version(assert) block so that it's 
compiled out. It (nearly) matches the behavior of arrays that way.

So, unless you're arguing that assertions should be left in code, then I don't 
think that it makes any sense to expect that Errors in general will stay in 
production code. Some may, depending on the code and what's being tested, but 
there's no guarantee that they will, and I think that it would be very much 
incorrect to expect them to in the general case - not when they equate 
specifically to programming errors.

- Jonathan M Davis


More information about the Digitalmars-d mailing list