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.
rteclasses.log.gz
Description: GNU Zip compressed data
