Pokemon Catch – Generic Exception Handling In Apex

I read a great post about this topic on Stack Overflow: Is it really that bad to catch a general exception?

However, I asked this question on our exchange because I am interested in a more specific discussion of how this topic fits in with a Multitenant Architecture. This discussion is very context specific, and I think it merits a separate discussion specific to what makes sense on the Salesforce platform.


I have a strong preference against catching a generic Exception. One of my former colleagues derisively called this practice a Pokemon Catch, as in “gotta catch em all!”

try
{
    // logic which may throw
}
catch (Exception pokemon)
{
    // handling logic
}

My main problem with catching the generic Exception is that it demonstrates that you do not know the expected behavior or failure paths of your own code. I believe this information is, in general, knowable.

I know that swallowing an Exception silently in the catch block is a much bigger problem, and that’s not what I’m asking about here. I’m also not asking about the tendency to find these blocks wrapping an excessive length of code (sometimes an entire method).

Is it ever acceptable (or even preferable) to catch a generic Exception in Apex? Are there repercussions to watch out for?

Answer

Pros

One of the primary advantages of the Pokemon Catch is that you reduce the complexity of code in many cases. For example, if you’re concerned about a NullPointerException, a CalloutException, a QueryException, and a DmlException, you have two choices:

try {
  ...
} catch(NullPointerException npe) {
  ...
} catch(CalloutException ce) {
  ...
} catch(QueryException qe) {
  ...
} catch(DmlException de) {
  ...
}

… or …

try {
  ...
} catch(Exception e) {
  ...
}

Which is easier to write? Which is easier to get 100% code coverage on? Code coverage alone may be one benefit of catching Exception directly, if you have many scenarios where you have to handle a bunch of Exception types.

However, both of those patterns are actually types of code smell. The former suggests that the developer couldn’t perform many of the usual checks (e.g. a NullPointerException should never occur, because you should be able to simply say if(something != null) ...), while the latter suggests that they have no idea what the API is doing, and so are going to just catch everything and hope for the best.

Cons

The Pokemon Catch usually results in bugs, particularly regression bugs, from going unnoticed until some time after they’re in production, usually right around the time users start asking “wait, why is the system behaving this way?” The more times you use Exception this way, the more risk you’re inherently taking. It’s preferable to have a hard crash with a stack trace than a silently debugged error that may go unnoticed for months.

The Exception

Of course, there are times when you do explicitly want to catch Exception directly. For example, a well-designed Exception-handling framework might wrap each of your methods in a consistent manner that allows solid error reporting, roll-back of partial operations, and so on. For code that advanced, I’d say it’s perfectly acceptable. For the other 99.999% of code out there, it should not be used.

The Unfortunate

Unfortunately, every single line of code in the documentation either uses no error handling, or shows only the use of Exception. This is just plain wrong. While it does make it easy for novice programmers to understand what’s going on, it’d be far more preferable if they used the correct data types and not abstract so much.

The Documentation

One thing that’s notably absent from Apex that was a feature of early Java is the throws keyword. This keyword would force developers calling this method to catch the exception. While I’m glad we don’t have that in Apex Code, because some odd 90% of the API probably throws NullPointerException, it was a nicety in terms of self-documenting code.

The documentation itself doesn’t tell you which methods can throw exceptions, or which types, which means that we end up with most developers going through NPE paranoia phases; we start using try-catch around every method, because we never know what’s going to happen, or (like me), we experiment with null parameters to figure out which methods will break when called with null values.

One thing I’d love to do is to introduce a list of all known methods that throw exceptions, but it would take a lot of work and a lot of maintenance, which I don’t have time for. I think it’d be a pretty cool thing to have on hand, though. Even better, I’d love it if salesforce.com would do this for us. Just put a little icon in the manual next to each method that throws NPE (or some other type).

The Takeaway

Avoid catching Exception at all. Ever. It’s “never” the correct solution. However, sometimes we just don’t have the time to write up all the proper code coverage, or sometimes the code coverage is “impossible” to achieve if we follow best practices. In general, if you can avoid using it, do so, and if it’s unavoidable, I’d recommend documenting why it’s unavoidable so you have something to reference later.

Attribution
Source : Link , Question Author : Adrian Larson , Answer Author : sfdcfox

Leave a Comment