Internal and External Exceptions
Perhaps the continuing confusion over the difference between checked and runtime exceptions in Java is because we haven’t named them properly. Mosts texts and teachers, including myself, have traditionally focused on how and when you handle the exceptions (compile time or runtime) rather than on what causes each. I propose a modification, not in code, but in terminology and teaching. Specifically I think we should should start calling checked exceptions “external exceptions” and runtime exceptions “internal exceptions”.
The idea is this: a checked exception is a response to some external event the program does not have control over. Examples include:
- File not found (
FileNotFoundException
) - Network socket closed midstream (
SocketException
) - Port already in use (
BindException
) - Malformed XML document (
SAXParseException
) - Database refuses request (
SQLException
) - Bad request or response from a different program (
RMIException
,JMSException
, etc.)
Any exception caused by occurrences outside the program itself should be a checked exception.
By contrast, a runtime exception is caused by a mistake inside the program. Examples include:
- Precondition violations (
IllegalArgumentException
) - Dereferencing null (
NullPointerException
) - Objects of the wrong type (
ClassCastException
) - Accessing outside an array (
IndexOutOfBoundsException
) - Inserting an object in a read-only collection (
UnsupportedOperationException
)
These should all be runtime exceptions.
When choosing between checked and runtime exceptions, simply ask yourself where the bug lies. Is the problem that causes the exception inside the program or outside it? If it’s inside, use a runtime exception. If it’s outside, use a checked exception. Simple, easy to understand, and easy to teach. And a lot clearer than complicated verbiage like
checked exceptions are for unpredictable environmental conditions such as I/O errors and XML well-formedness violations while unchecked exceptions are for program failures that should be caught during testing, such as array index out of bounds or null pointers. A checked exception usually cannot be avoided by changing your code while an unchecked exception usually can be. That is, an unchecked exception normally indicates a bug in your program, and a checked exception doesn’t.
This is especially true when you’re teaching undergrads who don’t do any testing at all, and thus for whom the distinction between bugs caught in testing and bugs caught at compile time is non-existent. I’m hopeful that it will be easier to teach them the difference between internal and external causes than the difference between bugs caught at compile time and bugs caught at runtime.
There are some borderline cases. The classic one is a user entering a string which is then converted to an int
. For example,
int getNumberFromUser(TextField tf) { String s = tf.getText(); return Integer.parseInt(s); }
If the user enters a non-numeric value, getNumberFromUser
throws a NumberFormatException
, a runtime exception. How do we account for this?
I think we can do that by breaking this into two parts. From the perspective of the Integer.parseInt()
method, a runtime exception is appropriate. The bad string is a precondition violation. An argument was passed that is not according to spec. This argument came from another part of the same program. Integer.parseInt()
does not accept input from the user. Therefore, NumberFormatException
is rightly a runtime exception.
The mistake here really is in the code that invokes Integer.parseInt()
. It should have checked that the value was a correct numeric string before passing it to a different method. It failed to verify the user input. This program is buggy, irrespective of user input. The uncaught runtime exception indicates that.
Now for practical purposes and convenience, we may well wish to allow Integer.parseInt()
to do the necessary check anyway. There’s no need to duplicate the code. However, a non-buggy invoking method should catch the runtime exception and convert it to a checked exception. For example,
int getNumberFromUser(TextField tf) throws UserInputException { String s = tf.getText(); try { return Integer.parseInt(s); } catch (NumberFormatException ex) { throw new UserInputException(s + " is not a number"); } } ... public class UserInputException extends Exception { public UserInputException(String message) { super(message); } }
That is, we really need two methods: one that reads a string from the user and returns an integer, and one that reads a a string from another part of the program and returns an integer. The first may call the second, but these are not the same methods, and they do not throw the same exception.
It doesn’t help that a lot of APIs, even some in the core JDK, get this wrong. For example, CloneNotSupportedException
always indicates an internal program bug. It really should be a runtime exception (and if it were Cloneable
would be quite a bit simpler and easier to implement). In fact, I suspect the JDK might well be improved if we went through all its exception classes and recategorized them according to this scheme. But overall I do think that exceptions are neatly sorted into those caused by internal mistakes and those caused by external data. When you find a checked exception caused by internal bugs or a runtime exception caused by external conditions, chances are very good this indicates a design flaw that should be corrected.
To sum up, here’s the rule:
If the exception is caused by problems internal to the program, it’s a runtime exception. If it’s caused by problems external to the program, it’s a checked exception.
Short, simple, to the point. Are there any exceptions to this rule? Are there any cases where an internal program bug legitimately should be signaled by a checked exception or a problem in the external environment should be signaled by a runtime exception? I can’t think of any. What do you think?
July 21st, 2007 at 4:02 pm
[…] http://cafe.elharo.com/java/internal-and-external-exceptions/ Perhaps the continuing confusion over the difference between checked and runtime exceptions in Java […]
July 21st, 2007 at 5:01 pm
I don’t think it’s important whether the problem was internal or external. The choice has to be with what you can do about it!
If you can’t deal with it than throw a runtime exceptions. There is no point in bubbling it up and write all the boilerplate code. Likelyhood is that only the outermost layer needs to know to tell the user. In these cases make the app stop what it was doing and let the outer layer tell the user.
If the calling code can and should deal with the exception than throw a checked exception and force the code calling your method to do so. Personally I actually introduced a compromise exception, the Expected Runtime Exception for exceptions I can handle but not in the calling code but inside the outermost code.
July 21st, 2007 at 6:57 pm
Sorry, no. The decision is most definitely not based on what you can do about it. What you can do about a problem has two consequences:
Error
, not anException
.However this has no effect on the choice of whether to throw a checked or a runtime exception.
It is rarely if ever acceptable for an exception to simply shut down an application and alert the user. (I am assuming we’re discussing production applications here, not student homework.)
An uncaught runtime exception always indicates a bug in a program. An uncaught checked exception is harder to produce, but still indicates a bug in a program when it does occur. A program that lets an exception bubble up to the VM and the user is buggy.
July 22nd, 2007 at 3:47 am
There will always be cases we can’t deal with! Database down – external resource not available …
I do not say bubble up to the VM or let the user see a stack trace etc.
I say do not bother all the code in between the exception location and the outer layer who can make a sensible decision on how to deal with such instances – which might include telling the user that a fatal exception occurred and to inform the administrator.
The outer layer will always need to deal with Runtime exceptions, whether they are thrown by our code or by other code we invoked.
Truth of the matter is that only very rarely the exception should/can be handled in the code who called the code throwing it. Then a checked exception is correct.
My ExpectedRunttimeException is for the outer layer to decide whether he can give a meaningful response to the client, for example tell him that his record was updated by someone else, or whether it’s something we did not anticipate at all and hence have no meaningful answer waiting for.
Development of applications, apart from student homework, is about making it work not about getting any academic ideas about Error vs Exception and Checked vs Unchecked right. Making developers place multiple catch clauses in the code in areas where they can’t do anything about it is the reason for the (still inexcusable) habit of people catching Exception and placing empty catch clauses into the code.
July 22nd, 2007 at 6:04 am
A similar classification: Contingency vs. Fault
http://dev2dev.bea.com/lpt/a/541
July 22nd, 2007 at 8:02 am
Ah. I see. You’ve forgotten that the code that invokes a method that may throw a checked exception does not have to catch the checked exception. The invoking method is always free to simply declare that it itself throws the same exception. This allows the exception to bubble up as many levels as necessary to find the method that can and should handle the problem. Overuse of
catch
and underuse ofthrows
is a common antipattern in Java code. The wrong solution to this problem is changing the checked exception to a runtime exception. The right solution is adding athrows
clause.July 22nd, 2007 at 8:56 am
Admittedly less verbose than the catch (especially for multiple exceptions) but still leaving the issue that the code in the middle has to deal with issues it can’t do anything about.
If I work with existing code that changed to use a method that throws a checked exception, I will now have to change all methods upstream to throw this exception as well. Lastly it still leaves the issue that developers will (I agree wrongly) just deal with it by catching Exception or even far worse swallowing it.
July 23rd, 2007 at 2:28 am
Good article. Have to mostly agree with Ingo, bsimply adding throws clauses is not always enough either. If your code uses an abstraction then it is not good practice to expose the exceptions that can be thrown from the concrete implementations. For example, if I use an interface Cache that can be implemented with a database or a file-based solution. My interface should not throw IOExceptions and SQLExceptions, and every time I add a new implementation I have to extend the throws clause. So that forces my implementing classes to catch the lower level checked exceptions and convert them into a custom exception at a suitable level of abstraction e.g. CacheException. This quickly gets tedious and results in a large amount of boilerplate code.
I would, however, refine the idea that the type of exception depends on what you can do with it. When writing a library, or a layer in a large project, it’s very important that you specify the exceptions that can be thrown, so that whoever uses your code doesn’t get nasty surprises. If I work in a smallish team responsible for a complete app, from front to back, then it’s generally much easier to use runtime exceptions.
July 23rd, 2007 at 3:30 am
Your idea begs the question: What exactly is external and what is internal?
IMHO it depends on the context. In a modularized software system, the definition of external and internal cannot be made at compile-time. What if, in the context that a method is used, the declared exception is actually not a problem at all, but expected behavior? An empty
catch
clause always leaves a bitter taste, to say the least. And in the opposite case, that it cannot be sensibly handled, you’d say, add athrows
clause, right? But, if we keep addingthrows
clauses to all the higher layered methods, our software will eventually be littered with checked exceptions that make no sense from a more abstract point of view.The problem with checked exceptions is still, that they force the user of a method (a developer that uses an API) to deal with problems that are not necessarily part of the problem domain at hand. What if I am absolutely content to handle an unparsable number as
null
? Sadly, I am still stuck withNumberFormatExceptions
, wrapped and unwrapped.July 23rd, 2007 at 4:54 am
Checked exceptions do not force the user of a method (a developer that uses an API) to deal with problems that are not necessarily part of the problem domain at hand. They force the developer to acknowledge that problems may arise, whether they want them to or not. Changing a checked exception to a runtime exception would not change the fact that an exception is thrown.
If indeed null is an acceptable response, then a method is free to return null instead of throwing an exception. That’s a call the designer of the method has to make. A method that invokes a method that throws an exception can catch an exception an itself return null, if that makes sense. You are not stuck with anything.
As we’ve seen time and time again, most recently in this thread, developers like to shift the blame when something goes wrong in their code. They like to blame “user error” because their code can’t handle a typo. They blame hardware failure if the disk fills up while they’re writing. Anything to avoid having to do include necessary error handlers in the code. Exceptions prevent this blame shifting and force developers to write more robust code. This is a good thing.
July 23rd, 2007 at 5:13 am
Wow, did you read my blog entry: http://www.jroller.com/jaha/entry/the_horror_of_the_checked? :-), I have not always agreed with you, but when we do we realy do! Think we pretty much arrived at the same rule for when go checked and unchecked! I think an important point to remember are:
The handling if an checked exception (cx) are often litle more than: Preserve valid state and stay alive; its not us that are in error, and maybe it goes away or at least allow human (end user, server administrators) to decide further actions (stay up, terminate as normal as possible).
But as I said in my blog, I feel the biggest problem with cx are that they in some cases has become sleeping pillows for developers: When throwing unchecked exceptions there must be means for users of that API to avoid making that programming error, easier then to throw cx! See my blog for my SQLException example.
July 23rd, 2007 at 5:18 am
[…] post from Elliotte Harold, proposing a new nomenclature for exceptions, whereby checked exceptions are referred to as “external” and runtime exceptions as […]
July 23rd, 2007 at 5:45 am
It’s not about shifting the blame. It’s about handling the issue at the point we can!
If you can handle a full disk – then do. You will however want to deal with it once. The point you where you are able to do so is generally at the root of the call (what I would call the service layer – e.g. the entry-method of the particular call).
Here you will have to deal with runtime exceptions anyway – even if you do not throw any, other pieces of code will.
Same as with checked Exceptions you can extend Runtime exception and create yourself a structure that will allow this layer to deal with specific issues specifically.
What I say is that I do not want to bother all the code in between with these exceptions – checked exceptions force me too!
July 23rd, 2007 at 7:14 am
Thanks Ingo, I wholeheartedly agree. This is not at all about shifting the blame. Eliotte, you did not answer the question: How can you define external and internal at compile-time or even design-time? I do not think you can, without proper a context. Sure, I do see the virtue of transparent code, say, when a method signals potential problems, but this expressiveness results in cumbersome rethrows (or, worse, empty catch clauses). That’s an annoyance at best, a design flaw of Java at worst — in fact, the way that checked exceptions are actually used in real-world applications have resulted in harder-to-debug, less robust(!) code. Do you honestly think that complex systems written in C# are less robust than Java systems? The anti-patterns are rooted within the abilities of the respective development team, not within the language.
July 23rd, 2007 at 8:36 am
Again and again… Why is it do difficult?! “Checked” exception is something to BE ALWAYS checked (Either by catching or by including it into the method declaration). “Unchecked” (Runtime) excepion can be not checked (one is allowed not catching it or including it to the method declaration). Is it not simple? Now the quetsion is which type of exceptions to use in each particular case. There can not be a definitive answer to that! In one case I may decide to report all “external” to my code problems by means of “checked” exceptions. I do that because I hope that the guy calling my code knows better what to do. Or I am pesimistic (or realistic) and I do not believe that anyone can handle those problems (since they are even more far away from the root cause) so I give up and throw runtime exceptions.
July 23rd, 2007 at 9:44 am
From the articles on Checked Exceptions published at this site, I understand (probably inaccurately) Elliotte to be saying the following:
1. Checked Exceptions in Java are wonderful.
2. If you truly understand Checked Exceptions, they have no problems whatsoever.
3. If you are having problems using Checked Exceptions then:
(a) You do not understand the concept of Checked Exceptions or when to use them; or
(b) You do not realize that a Checked Exception can be included in the throws clause of a method signature, making everything simple according to ERH; or
(c) You are a lazy developer who likes to pass the buck; or
(d) You do not like to write “robust” code; or
(e) All of the above.
Since ER Harold seems to believe the above very strongly, what is to be gained by any further discussion?
Let us agree to disagree since I do not think either party can convince the other of the merits of its arguments.
July 23rd, 2007 at 10:06 am
Once again I see advice from ERH to simply add the throws clause for any troublesome checked exception. As I asked repeatedly in the predecessor thread: Is it really so that I am recommended to add, say, SQLException, to any and all methods in an interface that is in, say, the domain model layer?
Sure, you may of course have only one implementation of the domain model interfaces – ever – and yes, they are implemented on top of a database then. But then, ERH is a teacher, and he will probably, rightly, give you sage advice not to expose implementation details needlessly. But, how is re-declaration of SQLException not exposing implementation details? How does it not nudge us towards a monolithic application by introducing dependencies? And how does it not follow that other exceptions deserve the same treatment as SQLException, so that they should get to feature in my interface as well?
FileNotFoundException? Someone deletes a file in error.
SocketException? A switch or VPN process dies.
BindException? Someone starts your program twice.
SAXParseException? Some external web service bugs out.
All of these are external. The domain model layer can’t handle them. Should we re-declare them in Account or Person interfaces? Bubble them all up as far as needed to reach the outer exception handling logic, predictably accumulating to mammoth throws lists in “upper” methods, tying their host interfaces to any and all implementation details “below”?
I suspect not, yet read your advice as “yes”. What’s the deeper insight here? Other than that, at least I can agree that overuse of “catch” is a bad smell 🙂 Just don’t ask me about “throws”!
July 23rd, 2007 at 12:26 pm
Elliotte nails the definition very well! The book “Effective Java” has a more complete definition, but Elliotte’s definition is a perfect “in a nutshell” explanation of what is going on.
Most APIs out there are written by people who don’t understand the concept of checked vs unchecked exception which is why the rest of the masses whine and moan about how awful checked exceptions are. If more API developers respected Elliotte’s simple rule we wouldn’t be in this mess 😉
July 23rd, 2007 at 4:22 pm
As someone whose mind can be changed by new data (hopefully we all consider ourselves in that category to some degree), I’m struggling with the following question:
Don’t I need to catch-wrap-throw things like SQLExceptions to insulate my callers from my implementation regardless of whether the exceptions are checked or unchecked? If so, then the ugliness of the catch-wrap-throw idiom is a problem with both approaches. Maybe something that both camps can use is some syntactic sugar to reduce the idiom’s intrusiveness.
July 23rd, 2007 at 6:14 pm
Kjetil,
You do not need to rethrow a
SQLException
from your domain model classes if it’s not appropriate. You may instead choose to catchSQLException
and rethrow a more appropriate exception. For example,In rare cases you might even convert a checked exception to a runtime exception in this fashion (but that’s really only appropriate if you can guarantee from the code that the checked exception will not in fact be thrown. Thus the runtime exception is more like an assert.)
However what is never appropriate is to simply ignore the problem. If there can be a
SQLException
, then you will need to deal with it somehow, somewhere. You can’t just sweep it under the rug.July 23rd, 2007 at 6:35 pm
Gili,
Bloch’s guidelines in “Effective Java” are actually much closer to Ingo’s. Item 40 states “Use checked exceptions for recoverable conditions and run-time exceptions for programming errors”. He then expounds on this in item 41 where he states “The burden (of checked exceptions) is justified if the exceptional condition cannot be prevented by proper use of the API and the programmer using the API can take some useful action once confronted with the exception.
Elliotte:
A few years ago (when I was still in academia land) I would have agreed with you. However, after several years of working on real-life software applications (or corrupted by real-life software applications, if you prefer 🙂 ), I have to disagree. Throwing checked exceptions when you can’t expect the calling method to do anything about it violates the principle of encapsulation, as you are forcing the calling method to deal with something it frankly doesn’t care about. And as far as adding throws clauses goes, that doesn’t end up working very well either as your throws clauses will grow exponentially. If you write a method which calls two other methods that throw checked exceptions, it will be forced to throw them both (assuming it cannot do anything about them). And then if that method’s parent calls both it and a sister method that also throws two checked exceptions, it will be forced to throw 4. Then if that method’s caller calls both it another method that throws 4 exceptions, well you get the picture. And add to all that, your top level method has now become tightly coupled to all the underlying methods that have thrown something it is now catching.
Yeah, with unchecked exceptions the top level code will have to catch a base Exception and post some generic error message (and log the details), but thats usually all the user will need. It sure beats having the top level code deal with every single error condition the underlying code could possibly hit individually.
July 23rd, 2007 at 8:29 pm
>The right solution is adding a throws clause.
I agree 100% Adding a throws clause is very elegant & easy – be lazy!. I prefer a throws clause to try/catch blocks. Try/catch blocks are very often uneccesary and ugly.
>doesn’t end up working very well either as your throws clauses grows exponentially.
>…Then if that method’s caller calls both it another method that throws 4 exceptions, well you get the picture.
Yes a picture that looks a little like a straw man. Wrap those exceptions silly.
July 23rd, 2007 at 9:03 pm
StrawMan,
Wrapping exceptions requires handling the exceptions, which is precisely what he was trying to avoid when he suggested adding throws clauses. So no strawman, just a demonstration of the flaw in the given suggestion. And furthermore, wrapping exceptions have problems in that you often lose the original exception that caused the problem in the first place. You know, the interesting one.
Again, throwing checked exceptions that the calling method cannot be expected to handle is an unfortunately common antipattern in software development. Remember, you are always free to declare or catch an unchecked exception. You are never free to ignore a checked exception.
July 24th, 2007 at 2:15 am
Elliot, on the academic side you are most probably right in respect to checked vs unchecked (I’m not so sure regarding internal vs external). When checked exceptions where introduced into Java the idea was to force people to use and to handle these to make sure people did not ignore them. Reality however showed that people who do not care about good exception handling will find ways around it – shortcuts that made it worse, not better. If you look into real code you’ll find empty catches and areas catching or throwing just exception.
Throwing unchecked exceptions doesn’t make it worse nor better. You are still free to cheat and avoid dealing with them and you are still free to handle and deal with them.
You do however make it easier to deal with them collectively in one area and avoid having to deal (if only to re-throw or wrap) with them in multiple areas – each one an area where someone can deal with them wrongly.
At the end it comes back to the question of what’s more important – academic correctness or pragmatism.
Personally I believe the later to be more important, which is the main theme of my blog (Golden Toolbox. Sorry for the shameless plug – however there are a couple of posts where you now have the chance to critique me :-).
July 24th, 2007 at 6:04 am
I do not agree that throwing checked exceptions that the calling method cannot be expected to handle is an antipattern. The throwing method in general knows nothing about what the calling method can or cannot handle. Some methods that call it may be able to handle the exception. Others may not, and have to rethrow it. Regardless, the throwing method never expects that the calling method can handle the exception and the throwing method never expects that the calling method can’t handle the exception. Its job is to notify the calling method of the exception, not to worry about how the calling method will or will not handle it.
I’ll have to reread Bloch, but I think what he meant was not whether the calling method could be expected to handle it, but whether any method in the call chain could (and if he didn’t mean that, he should have). There are cases such as
OutOfMemoryError
that really can’t be handled properly 90% of the time. These are represented by errors, not exceptions (either checked or runtime) and they’re very uncommon.July 24th, 2007 at 7:21 am
Elliotte,
I did not say the throwing method has to be 100% sure that the calling method will be able to handle it, but there does need to be a reasonable expectation that it will be able to do something useful. The reason I took the more extreme view that it should be the calling method that should be expected to handle it as opposed to someone else up the chain (and note that I did not say Bloch said that, though his wording was “the programmer using the API” which is fairly close) is that if the exception is unchecked, the calling method gets to decide how to handle it. They are free to catch it or document that it is thrown if they like, or ignore it as something that it cannot do a damn thing about and leave it for some top level method. You are right, the throwing method doesn’t usually know what the calling method can or cannot do, so in those cases leave the decision to the calling method.
And of course throwing an unchecked exception doesn’t mean don’t document it anywhere. If your method might throw an unchecked exception, you need to let the calling method know through the javadoc so it will be able to make that decision.
Forcing methods to deal with exceptions they cannot handle will result in one of three things: empty or nearly empty catch blocks as described by Igno (and in my experience, that happens a lot), throws clauses that grow exponentially as more and more methods get called like I described in my first post, or wrapped exceptions that just results in the obfuscation of the original, useful exception. When something happens like a resource is missing, often the only thing they can do is have a top level method (the container or shell or GUI or whatever) log the exception and print out an error message.
Also, it may be nitpicking, but I disagree regarding when Errors should be thrown instead of Exceptions. If you can handle it 10% of the time it should probably be an unchecked exception, as Errors are (almost) never handled. Something like an OutOfMemoryError cannot be handled even 10% of the time; if the system ran out of memory, then your app is pretty much hosed. The only Error I can think of offhand that can be properly handled is a StackOverflowError since they are often thrown by recursion gone bad.
July 24th, 2007 at 10:20 am
Elliotte, I know that is the other option. I’ve been through this. I also know that you should and must wrap the original exception, or you will lose valuable failure information. If you don’t, you will just send the reader of your stacktrace (usually yourself) out on a time-consuming debug session. You probably know this too, so I’m assuming your example was a bit rushed.
But it does bring me onto the next objection I have about checked exceptions. The following is a re-hash of my postings in your previous thread on exceptions, but the gist of it is, that you will eventually end up with ALL methods declaring that they throws DomainModelException. This is nice from a design point of view, in that each layer will have its own exception (super)class, dutifully declared in every method.
However, I find that this practice doesn’t provide THAT much more information than NOT having that throws in every method. What it does provide though, is the need for duplicating that particular try/catch/throw construct in most (if not all) method calls going down-layer, in all layers. This is a high cost, and the information gain is low.
And when you look at what comes out, in the end, when something fails and assuming one follows your practice of using e.getMessage() for the message – what information does it contain? It has exactly the same information as an unchecked exception thrown at the original cause would have had, it just has a lot more noise. And yes, it should be handled, no rugsweeping here, no sir – but just because it’s important doesn’t mean it warrants superfluous effort.
I am trying to put this simply. I know I should give up and get on with the coding 🙂
July 24th, 2007 at 3:50 pm
I wrote a bit about error handling here, which covered checked and unchecked exceptions:
http://www.artima.com/forums/flat.jsp?forum=270&thread=207358#269379
In brief, a checked exception is part of the status information (success/fail, diagnostics) passed from a routine to the calling code, and so it’s legitimate to have to declare it. If not an exception, it would be an extra status parameter or return value, which would also need to be declared. Think of an exception as an “invisible return parameter”.
Unchecked exceptions a very much like gotos – untraceable execution/data paths. I find it odd that they have so many defenders.
July 26th, 2007 at 7:50 pm
This was an interesting read and I mostly agree with the outlined suggestions. Particularly, I often encapsulate checked exceptions as checked domain exceptions so that I do not expose implementation detail exception to the outer layers that don’t need to.
One thing that should NEVER be done in production code (quite frankly, not even in test code or whatever code – I see that sadly all too often and has caused a lot of grieve) is given by the example in Elliotte’s code snippet that illustrates how to encapsulate domain specific exceptions:
try {
someDatabaseAccessingMethod();
} catch (SQLExcepiton ex) {
throw new DomainModelException(ex.getMessage());
}
ex
has to be passed along as an exception cause insideDomainModelException
.The code snippet needs to read as follows:
try {
someDatabaseAccessingMethod();
} catch (SQLExcepiton ex) {
throw new DomainModelException(ex);
}
I would put the former code snippet as an example of antipattern number 1 in the list of Java antipatterns.
July 28th, 2007 at 4:46 am
Thomas, I was pointing to the exact same thing. Not wrapping the cause generally forces you to open the debugger and re-run, hoping to find out what it is – and that is assuming it is reproducible and relatively easy to pick out. (Think of code that runs on thousands of elements – one of which provokes the error!) In lucky cases, someone has logged the cause somewhere just before (also an anti-pattern), or you have the code and can find a likely culprit. But not knowing what failed is NOT encapsulation, it’s more like subterfuge.
For further payoffs, provide an additional message in the new exception, containing some contextual information relevant to the situation. Keep in mind that more information exists at runtime, and all too often I see static exception message strings thrown from, say, lookup-foo-by-name type methods, simply: “Unknown foo”. What a senseless waste of human life! How many man-hours could not have been saved, if the author instead had given us the string “Unknown foo ” + name?
The runtime perspective is a good thing, and helps me produce transparent code that can tell me about errors and help me find its right shape. I fear the static perspective – including trying to predict errors with exception checking – is confusing and may suggest, e.g. to people learning Java, that this practice is somehow “illegal” design-wise. I have been met with the argument, particularly from recovering C++ victims – that wrapping the lower-level exception will “reveal” the implementation.
July 28th, 2007 at 3:36 pm
@Thomas Pollinger
It would be nice if Java automatically chained Exceptions according to the Exception specified by the method. Manual wrapping as in:
is tedious and unnecessary.
July 29th, 2007 at 4:37 am
Roland,
It is tedious to HAVE TO do it.
It CAN BE useful to wrap and contribute some contextual, runtime information to the stacktrace.
It IS unnecessary because you can use unchecked exceptions instead.
July 11th, 2008 at 8:19 am
[…] Source: The Cafes […]
April 20th, 2010 at 5:59 am
[…] Java programs throw Errors, not checked exceptions, not even runtime exceptions. Checked exceptions signal environmental problems that programmers cannot prevent or predict, should test for, and most decidedly can handle. To choose the most extreme example, if a […]
November 7th, 2010 at 6:27 pm
[…] approaches to deciding on checked vs unchecked exceptions. First, let’s turn our attention to this Elliote Rusty Harold’s article. He suggests that we should start calling checked exceptions “external exceptions” and runtime […]