During the first 17 years of the Java platform considerable confusion, and well-intentioned argument, ensued for how to handle exceptions. For many years the discussion focused on the ill-conceived notion of Checked Exceptions and a hesitancy to abandon this bad idea for exception path processing… the following article is symptomatic of the chaotic state in 2004, almost a decade after Java’s inception:
The above article concludes with the appropriate admonition to “Document, document, document” … a fall-back position when source code lacks understandability. An additional negative side-effect of this period were the endless discussions as each project team resolved how to handle the ambiguity.
I believe the lingering exception handling confusion could be reduced by expressing an effective pattern for using the mechanism. Said another way in the form of a question, when the class NullPointerException ends with the suffix “Exception” is that a mechanism or is that an Implementation Pattern?
If we were to agree that a Checked (Exception) and Unchecked (Runtime) exception are mechanisms… then it would be counter-intuitive to end a class name exposing the mechanism in play… particularly if we use the same word (“Exception”) for both mechanisms:
- java.lang.NullPointerException extends RuntimeException (Unchecked)
- java.sql.SQLException extends Exception (Checked)
In addition, we (the industry) can’t decide if the exception mechanisms are for truly exceptional situations, or for alternative flow processing such as the preference for “exceptions to returning error codes”1, or for both.
My recommendations for code understandability are simple:
- Don’t suffix the class name with the term “Exception”
- Do include the pattern name as a class name suffix
If you buy into this so far, we can now begin the discussion for reasonable patterns expressing exception and alternate path processing, such as:
- Alternate Path Controller (APC)
- Exception Path Controller (EPC)
If you don’t like using acronym suffixes please disregard the parenthetical notation… that is not the point of this post.
But why Controller? The notion cascades from the Single Responsibility Principle (SRP) and that the Controller pattern is suitable for aggregating sub-responsibilities into a single responsibility. For example, exception path processing might require:
- logging the message and stack trace once and only once
- emailing the message and stack trace once and only once
- signalling the error (thrown)
The aggregate single responsibility could be called “notifying”. That is, an Exception Path Controller is responsible for notification whereas an Alternate Path Controller might have the following “informing” sub-responsibilities:
- force compile time (static) checking
- log a brief informational message once and only once
- signalling the error (thrown)
Leveraging the Java checked exception mechanism for alternate flow processing seeks to enhance code expressiveness (understandability). That is, the responsibility for handling alternate path (or ‘flow’ if you prefer) processing is visually apparent in the method header.
And an additional positive side effect… we (code authors) must explicitly clarify anticipated exception path vs. alternate path processing. Here are some typical exception path classes requiring manual (developer) intervention:
- java.lang.NullPointerException
- javax.persistence.PersistenceException
- javax.ws.rs.WebApplicationException
Here are some typical alternate path classes quietly handled by conditional logic:
- javax.persistence.OptimisticLockException
- javax.validation.ValidationException
- javax.faces.convert.ConverterException
Further elaboration at:
_Marvin
Originated: 9/2012
References
- Robert C. Martin, Clean Code, p. 46.