tags:

views:

162

answers:

5

I analyzed the code I am working on using a Java source code analyzer. One of the warnings is "Always declare user defined exceptions as final". There are many other warnings that doesn't make much sense but this one made me a little bit confused.

I am working on a framework and I have one root generic exception (say FrameworkGenericException) and for other exceptions I am simply deriving them from the root exception. So I have a hierarchy of exceptions for the framework. I might extend the hierarchy but this warning I think tells me not to have such hierarchy but define them individually. So what which way should I go, what are your comments?

+2  A: 

I've never hear of this recommendation, nor does it make any sense to me.

Which tool are you using? I tried Googling for that message and got ZERO hits apart from your SO question. Trying other searches in attempt to "exploit the wisdom of the net" gave me nothing obviously relevant either.

Perhaps you should ask the code analyzer tool authors to explain the rationale for this style rule ...

Stephen C
Yeah... Ok if nothing comes up I will do that and let you guys know ;) But we should do some brainstorming before we ask...
erdogany
+2  A: 

Strange. Google shows only one document with such words - your question :)

In my projects this is quite normal to have user-defined ancestor(s) for all exceptions. Few years of development in this style, nothing special so far linked to that.

maxim_ge
+2  A: 

The thing is, a static analysis tool basically scans your code for violations of (what the author of the tool considers to be) "best practises". In this case, it's usually considered a "best practise" to have very shallow exception hierarchies.

The reason is that there's basically two times when you'll catch an exception. The first, is you want to catch the exception because you know how to handle it. For example:

try
{
    return fetchDataFromFile();
}
catch(FileNotFoundException)
{
    return defaultData;
}

In this case, you caught the FileNotFoundException because you want to return "default data" when the file isn't found. In this situation, you typically catch a specific exception class - because that's the only type of exception you know how to handle (for example, if fetchDataFromFile throws some other exception, you don't want it to return default data.

The other time you'll catch exceptions is at the very root of your thread,

try
{
    doStuff();
catch(Exception e)
{
    logException(e);
    notifyUser(e);
}

In this case, you catch the root exception class, because you specifically want all exceptions so that you can log them, or notify the user.

There are very few situations where you need to do anything else.

Now, remember that this is a static analysis tool. It's job is to just flag "potential" problems to you. If you believe your situation is somehow different, then the idea is that you document why you think it's different and specifically disable that warning for that section of code (or that class or whatever).

Dean Harding
@Dean - if that's what they are trying to do, they are going about it the wrong way. Besides, I think that the real issue is you should not be lazy and declare everything as throwing the root exception. IMO, the depth of the hierarchy is immaterial.
Stephen C
@Dean Reason for FrameworkGenericException for example: SQLException (say some specific exception comes from underlying APIs that can not be recoverable). So this specific exception is shielded. Clients of this framework does not need to know about the specific exception but instead they get FrameworkGenericException as an exception nothing to do. But if they get SomethingNotFound extends FrameworkGenericException it becomes meaningful. And BTW exceptions have only two level of derivation.
erdogany
I think that there's nothing wrong with creating a hierarchy of exceptions, this makes the program easier to understand and to work with. See my answer, I've provided an example for this.
Malcolm
@erdogany: In that case, I would have two separate, non-inheriting exceptions. One unchecked exception class (that inherits from `RuntimeException`) for encapsulating `SQLException` (that the client code cannot handle) and one checked exception (that inherits directly from `Exception`) for the `SomethingNotFoundException`. However, this is just my *opinion* for how **I** would do and you're free to do it how you please.
Dean Harding
+4  A: 

This is probably standard practice to them: declare classes as final if they are not supposed to be inherited from, and also they probably think that all of your exceptions won't be extended from.

However, in your case I think that it is a good thing to make one generic exception and extend all others from it. Say, you have:

public void frameworkMethod() throws IllegalDataException, InvalidCommandException;

where these exceptions are sublasses of FrameworkException. Then you could handle exceptions a little bit easier.

try {
    frameworkMethod();
} catch (FrameworkException ex) {
    logger.log(Level.SEVERE, "An exception occured!", ex);

    if (ex instanceof IllegalDataException) {
        // Do something to recover
    } else if (ex instanceof InvalidCommandException) {
        //Inform the user
    } //And so on...
}

So I'd say, you're doing the right thing, the architecture of your program will be easier to work with.

Malcolm
@Malcom This is exactly what I am doing ... And only in few cases there that kind of if/else
erdogany
Yes, I figured that it would be better to illustrate why it may be convenient to have a tree of exceptions and not just one exception per one very special case.
Malcolm
Very common to have a OurDomainException to allow easy classification.
Thorbjørn Ravn Andersen
+2  A: 

I'll bet that message goes away if you make your generic exception abstract. You'll be following another well-respected object-oriented guru, Scott Meyer:

Make non-leaf classes abstract.

Personally, I disagree with a root exception for your whole framework. What extraordinary behavior have you embedded in it that all children will inherit over and above what comes from java.lang.Throwable?

I think having SpecialBusinessException overriding the four constructors from java.lang.RuntimeException is plenty. What's the point of the hierarchy? I'll bet it's flat and wide, with one root class. Why bother?

duffymo
Allowing for the top level catch to clearly identify if this is a vendor exception or not?
Thorbjørn Ravn Andersen
I think the vendor package name should be sufficient. How much more indication do you need?
duffymo