Search |
||
Java Exception Handling Patterns (Part 1)Posted by bakksjo on September 19, 2005 at 6:22 AM PDT
In a series of blog entries, I intend to discuss various patterns for exception handling in Java.
Don't use enumerated exceptionsQuite often, you will see code using what I like to call "enumerated exceptions". An enumerated exception typically looks like this:
Problem 1: Over-declaring exceptionsConsider a method which is declared like this:
To someone who does not completely know the internals of
As such, code which calls
This is clearly cumbersome and wasted if However, nobody ever writes such exception handlers, for a number of reasons: Applicability: More often than not, there is no logical or natural way to handle some of these exceptions in the current context, since exceptions A, B and C may be of completely different nature and occur in distinct places. Volume of single catch-handler: Enumerated exceptions often contain hundreds of possible values, which makes it incomprehensible to write a handler for each one after every call of every method which declares that it throws an enumerated exception. Number of handlers to write: In modules which use enumerated exceptions, it is often practice that almost every method in the module declares that it throws the enumerated exception, and usually only this one. As a consequence, almost each method called from client code will possibly have to catch the enumerated exception, so using the principle outlined above would turn the majority of the client code into exception handling. Even worse, most of the exception handling code would, in practice, be produced by copy-and-paste, and often incorrect in the current situation. Nothing would be gained except making the code completely unreadable. Maintainability: Whenever somebody adds For these reasons, catch handlers for enumerated exceptions hardly ever test for all possible error codes; instead, people write their exception handlers to handle a subset of the error codes in ModuleException: the error codes they "know" that the method uses. This brings us over to the next problem: Problem 2: Disabling compiler checking of exception handling completenessA programmer saying that she knows which error codes in an enumerated exception are relevant after a certain method call is like saying that she knows what exceptions a method throws if the Java language did not require you to declare them and the compiler did not check that they were handled. Most Java programmers have experienced the following scenario: You write a new method or modify an existing one. You call methods in various libraries; say, e.g., container-related methods from the java.util package. You read the javadoc for this library to make sure you understand how the methods work, what input parameters they take, what their return values are. You think your modifications are complete, so you compile and test your program - and then you find that the compiler complains to you that you have uncaught exceptions; you need to either handle a certain exception or declare that your method throws it. The exception was written in the documentation, but you missed it and did not write a handler for it anyway. Not until the compiler told you that you needed to do so. Only then you sat down and asked yourself: "What should my program do when that exception is thrown?" Using enumerated exceptions effectively disables compiler checking of the completeness of your exception handling. This is extremely dangerous and nonchalant! Consider the following code:
Here, the programmer of Consider instead:
The compiler will complain to you, since Observe that in the first example, declaring that Problem 3: Polluting the exception-class with non-relevant fields and methodsOften, one will want to add fields or methods to some exception types. With distinct classes for each exception type, this is no problem. With enumerated exceptions, it usually means adding methods and fields which are relevant for some error codes, and have no meaning for others. Quite often these classes end up somewhere in the middle - they try to restrict the level of pollution, so they don't go "all the way" in providing all possible information that could be supplied with single error codes. This causes them to be neither "pure" and general, nor as specific as they should be for a particular case. This should be a clear indication to the programmer that enumerated exceptions are a bad idiom, and one should rather use multiple, separate exception classes. You will see numerous modules using this pattern, such as, for instance, JDBC:
If the exception above was instead a separate class (say, The fact that the pattern is commonly used in "big" libraries/APIs does not make it a
better pattern. All drawbacks listed above apply to all the modules which use
this pattern. In JDBC, for instance, developers typically "forget"
to write code to handle retryable exceptions. The compiler forces
them to catch a By now I should have convinced you not to use enumerated exceptions, right? ;o) So, what should you do then? General rule: Write separate classes for all your exceptional conditions. Declare for each method exactly which of these are thrown. Do not declare to throw some big, fat, one-exception-to-rule-them-all. Stay tuned for part 2: Objections to this rule, adaptations you can make in certain cases where this simple advice may not suffice.»
Related Topics >>
Programming Comments
Comments are listed in date ascending order (oldest first)
|
||
|
|