7
votes
\$\begingroup\$

I ran a sonar analysis on my code and it told me the cyclomatic complexity is too high (sonar's limit is ten branches).

Here is my code:

public void myMethod(){
  try{
  // do something
  catch(SomeException e){
    throw new WrappingException("issue when doing something " + e.getMessage(), e);
  }
  catch(AnotherException e){
    throw new WrappingException("issue when doing something " + e.getMessage(), e);
  }
  // lots of other Exceptions
}

Basically, I want to catch a large set of Exceptions, (maybe always processing the same behaviour). I read the question Catching multiple types of exceptions when writing JSON but I don't use Java 7 (with which I could have all Exceptions in one catch statement) and I do not really want to catch ALL Exceptions, since I want my code to fail in a case I did not expect.

Is there any alternative that would involve fewer branches?

NOTE: What I want to achieve here is not to recover from any Exception, but to categorize the Exceptions. An upper layer is in charge of handling Exceptions, but for this purpose, Exceptions need to be properly categorized.

\$\endgroup\$
  • 3
    \$\begingroup\$ If the Exceptions that you are interested in catching share common super classes (but not as far up the ancestor stack as Exception) then you could catch the super class rather than each subclass. If they don't, is your method doing too much? \$\endgroup\$ – JohnMark13 Sep 18 '13 at 13:28
  • \$\begingroup\$ I call a constructor by reflection. That gives me already 6 Exceptions to catch. But I agree, I should maybe split the rest of my method. \$\endgroup\$ – Vince Sep 18 '13 at 13:34
  • 2
    \$\begingroup\$ Shame it is Java 6, as if you look at what they added (fixed, was silly not to have this before) here docs.oracle.com/javase/7/docs/api/java/lang/… that would have cut down your necessary catch blocks! \$\endgroup\$ – JohnMark13 Sep 18 '13 at 13:39
  • \$\begingroup\$ ah indeed it's cool that they decided to use inheritance on Exceptions. Indeed, if we switch to Java 7, I'll update the code. \$\endgroup\$ – Vince Sep 18 '13 at 13:45
  • 1
    \$\begingroup\$ @JohnMark13 I found a way to split my method, it looks nicer now. Thanks, you can actually post your comments as an answer. \$\endgroup\$ – Vince Sep 19 '13 at 8:59
2
votes
\$\begingroup\$

As JohnMark13 stated in the comments above, if the exceptions you want to catch share a common supertype (possibly besides the basic Exception class), then you could catch the supertype instead of all the subtypes. If you have created the SomeException and AnotherException classes yourself, then I strongly suggest that you make them extend a common custom exception type.

Also, I think that since you rethrow the exceptions (or at least most of them), then catching the general Exception is OK. Or, you could first catch all RuntimeExceptions, rethrow them directly, and then check the rest and possibly throw your WrappingException. Consider this:

public void myMethod() {
    try {
        // do something
    }
    catch (RuntimeException e) {
        // We don't need to wrap these, so we just throw the same exception again
        throw e;
    }
    catch (YourCommonSuperException e) {
        throw new WrappingException("issue when doing something " + e.getMessage(), e);
    }
    catch (Exception e) {
        // All other excpetions, such as `IOException` and stuff will be caught and wrapped and throwed here.
        throw new WrappingException("issue when doing something " + e.getMessage(), e);
    }
    // No need for any other Exceptions
}

Perhaps you get some extra cyclomatic complexity from the // do something part. If so, then you could split that part into multiple methods and possibly declaring to throw the exception from the method if needed so that it will get caught in this myMethod() (or catch within the method and throw some kind of YourCommonSuperException.

Depending on the specific // do something part, you might want to overlook which kind of exceptions that are thrown there. If you throw them yourself, it might be possible to change to IllegalArgumentException, IllegalStateException (which both extend RuntimeException) or some exception that extends YourCommonSuperException.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.