tags:

views:

749

answers:

8

I read somewhere (can't find it now) that large exception hierarchies are a waste of time. The justification for this statement seemed sound at the time and the idea stuck with me.

In my own code when I have a code base that can have a range of error conditions I use a single exception with an enumeration member to differentiate between them.

If the case arises that I need to catch on one of these errors, I catch it, check the enum and rethrow if it was not what I expected. Ideally, this should be rare.

I was working with exceptions again and the I had a reflective moment where I questioned my exception habits. I am curious what everyone else does and why?

Hierarchy or one exception with data members.

BTW, I am assuming you agree with the idea of exception vs error codes. I don't wish to open that can of worms.

A: 

I like the idea of having a small number of exceptions for different classificatons of errors such as for fatal/non-fatal conditions or for particular layers or modules of an app. The thrower of the exception should then provide codes to include as a payload of the exception. The presentation layer of the application can look up localized human readable error messages corresponding to the codes.

In summary, exception types are useful for the developer and messages corresponding to error codes are useful for the user.

Andrew Kennan
@Andrew: with regards "fatal/non-fatal" classifications of exceptions. Such classification should be determined when an exception is caught, not thrown! Hence it can't relate to the exception type.
Daniel Paull
+8  A: 

I think having just one exception type with an embedded enum is suboptimal:

  1. You are forced to catch the exception more often than necessary (and rethrow it, once you have established that you can't handle it)
  2. The enum itself becomes a change hotspot (all programmers need to modify it on a regular basis)
  3. An enum is not hierarchical, so for example you cannot handle all IO errors with one handler easily
  4. Sometimes you also want to provide the caller with additional information besides the error message text, e.g. the path of the file that has not been found or the error number received from the SQL server. Putting such additional information from all possible error scenarios into the same exception makes handling even more cumbersome.

To answer your question, I'm using a hierarchy of exceptions. It's much broader than it is deep.

Andreas Huber
+2  A: 

In my experience, too many exception classes only become confusing, especially of they are only used for one very specific types of problems. I have seen a system where every error condition had it's own exception, but only the super classes were checked in the catch blocks. The subclasses were a complete waste of time.

On the other hand, having to check for the enum and rethrowing the exception makes the code less intuitive, because you can't identify the exception thrown directly after the catch. Perhaps only a minor drawback, but if used often it can have an impact on readability. It could also pose a performance problem when used in code that needs to be very fast.

I would not use the enum solution but a few exception types that have a broad enough spectrum to be useful. Like a DatabaseException instead of several exceptions like TableNotFoundException, ColumnNotFoundexception, etc. In my experience, that works best for most developers. You can always add a field with some error code that you display to the user to make communication between user and support easier.

Sebastian Dietz
+1  A: 

You don't solve the problem of too many exception classes by replacing them with one exception type and enum subtypes. In fact, you only make it worse!

Example: Say you had Exception types Ex1..Ex99, with e.g. E14..E18 are childs of E1, etc. You now decide to replace them by one exception Ex and subtypes ST1..ST99. What have you solved? Nothing - people still have to deal with all possibilities. What have you made worse? You can't ignore ST14-ST18 and treat them as occurances of ST1. You now must deal will all 99 possibilities, as you enum subtypes do not have a natural, flexible hierarchy.

MSalters
+3  A: 

I think you are having the worst of two worlds. A large exception hierarchy is useless because clients are known to be lazy and will end up checking only for the top nodes (maybe only for the hierarchy root). Your enum system does not solve this problem and makes for a more cumbersome exception catching system.

If you really know that lots of different exceptions are needed and catchers will really want the different exceptions (know, not vaguely think), go ahead with the large hierarchy and forget the enums. Otherwise, stick to the small exception hierarchy and offer only the exception classes that will really be interesting for catchers.

Gorpik
+2  A: 

Don't confuse errors with exceptions.
Errors happen, solve them as close to the problem as possible.
Exceptions are rare and usually not solvable without more contextual information.

If something goes wrong and can be corrected locally then you should probably use error codes and handle it there and then.

Exceptions should be used to propagate the problem up the call stack to a context that has enough information to solve the problem.

Saying that: Enums are not the way to go as they bypass the whole try catch mechanism that the compiler will generate automatically for you.

Martin York
+8  A: 

Simple rule of thumb:

  • If you end up rethrowing exceptions after examining them, then you need a more finegrained exception hierarchy (Except for the rare case where the examination entails considerable logic).
  • If you have Exception classes that are never caught (only their supertypes are), then you need a less finegrained exception hierarchy.
Michael Borgwardt
+5  A: 

You should not be dogmatic about this. Use whatever is the best fit for the problem in hand. My rule of thumb for this is as follows:

  • Create new Exception classes only when you need an exception that requires different behaviour.
  • Instead, add content (enums, errorcodes, whatever) to exception classes when you simply want extra information included with the exception
  • Don't create new classes unless you really need them. and remember, YAGNI...
Roddy