cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Berin Loritsch <blorit...@d-haven.org>
Subject [RT] Smarter Use of Exceptions
Date Thu, 29 Sep 2005 14:51:47 GMT
Based on the errors from the Java 1.3 compatability issues I decided to 
check how pervasive the use of generic runtime exceptions was.  I am 
quite surprised at the results.  It seems that instead of having planned 
and known exceptions we opt to throw generic exceptions all over the 
place.  Attached to this is a grep of the current source code searching 
for the phrase "throw.*RuntimeException" to show just how pervasive the 
use of generic exceptions.

Before I dive into more detail here, I am not questioning the use of 
unchecked exceptions.  I am challenging the use of _generic_ 
exceptions.  I am also lumping the CascadingRuntimeException, and 
CascadingException in the generic exception category.  The exception 
type tells you nothing that you didn't already know... that something 
exceptional happened.  We have five hundred and three places where we 
throw generic runtime exceptions.

In general it is good practice to throw a typed exception than a generic 
one.  You have a much better idea of the problem when you see 
ValidatorInitializationException as opposed to RuntimeException.  The 
very name of the exception provides a clue as to what can happen and 
where.  The fact that you have an exception class that you created also 
signifies the fact that the exception was planned and it didn't just 
happen somewhere in the bowels of the JVM.  The same argument goes for 
your generic Exception and CascadingException.  It is better to throw a 
specific exception than it is to throw a generic exception.  The more 
specific you are, the more likely you will be able to narrow down on the 
problem--and the less doubt you will have about the system as a whole.

Creating a new exception class is not difficult, you just have to do 
it.  Using the example comparison in the above paragraph we can create 
our ValidatorInitializationException with just a few lines of code:

public final class ValidatorInitializationException extends RuntimeException
{
    public ValidatorInitializationException(String message)
    {
        super(message);
    }
}

If you want a constructor that wraps another exception and is compatible 
with Java 1.3, then it is also simple to do:

public vinal class ValidatorInitializationException extends 
CascadingRuntimeException
{
    public ValidatorInitializationException(String message)
    {
        super(message);
    }

    public ValidatorInitializationException(String message, Throwable cause)
    {
        super(message, cause);
    }
}

Given the ease of which we can create exceptions with more semantic 
meaning we should start doing that.  Just to drive home the point, 
imagine your significant other's car broke down and they are off the 
beaten path.  The problem is that there is a seven way intersection 
between you and your loved one (and yes there is such a thing as a seven 
way intersection).  If your loved one says that they are by some houses 
down the street, you will have a tough time finding them.  If your loved 
one says that they are by house 315 on Orchard Street, then you stand a 
much better chance of finding them quickly.  That is the difference 
between generic exceptions and typed exceptions.  While there is no 
programatic advantage to writing a new class that does nothing more than 
extend a base class, there is a semantic advantage so that when you see 
your error page you can zoom in much more quickly.

Now, I'm only one guy so me making 305 changes with only a surface 
understanding of why each of those exceptions is thrown doesn't scale 
very well.  It would make much better sense if we all got on board and 
improved the blocks and modules we are working on ourselves.  But as a 
general rule for new development, it should be a problem when the phrase 
"throw new RuntimeException" is encountered in new code.  Why was it 
thrown?  Was there a checked exception that could have been thrown 
instead?  How can we find the cause quickly without getting lost in the 
stack trace?  BTW, the only part of the stack trace that is important is 
the one to the original causal exception.  Are we losing the original 
exception?  Many of these questions can be avoided when we have a known 
exception to throw.  If you want it to be checked or unchecked is up to 
you and your personal beliefs.  However, generic exceptions are evil.  
I've had to try to track down where problems are in several systems and 
the use of the generic exception only made the bug fixing worse.

Mime
View raw message