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.
System.LimitException
being a notable example. – martin Aug 16 '16 at 5:33UnexpectedException
andAssertException
are also uncatchable. – Alan Morey Aug 16 '16 at 18:26