Discussions

News: James Gosling Chimes In on Checked Exceptions

  1. James Gosling Chimes In on Checked Exceptions (113 messages)

    Checked Exceptions have been attacked by many. Bruce Eckel wrote an early piece questioning their value. Recently, Anders Hejlsberg told us why he didn't go that route with C#. Now James got his chance to explain that he still DOES think Checked Exceptions are important, and discusses industry practices, and issues with the way students write code.

    When you are in class, you just write code to complete the project at hand, and don't care about exception cases. In the real world this isn't the case!

    He also has a few words on where/how to decide what to throw in your code.

    Read James Gosling: Failure and Exceptions

    More info

    Anders Hejlsberg's comments on checked exceptions:
    The Trouble with Checked Exceptions

    Bruce Eckel questioning the value of checked exceptions:
    Does Java Need Checked Exceptions?

    Threaded Messages (113)

  2. Have to agree with James on this one. I look at the throws clause as a reminder to developers that something can go wrong and that at some point "this" particular error should be handled. Without that, nobody would ever catch anything except the global default try{}catch(Exception e){e.printStackTrace;}. Love this: "In Java you can't escape the creepy feeling."

    I agree with Anders Hejlsberg that there should be a much higher number of try-finally than try-catch in a well written application. But James has a point, that this depends on the domain.

    I also agree with James' idea of using heirarchies and wrapped exceptions (cause), especially when layering software. Standard exceptions should be defined as part of the interface for each layer [or component] and all other [checked] exceptions wrapped within those layered exceptions (or within the layer exception hierarchy). It's just too bad that it took them until JDK 1.4 to include standard API for wrapped exceptions!

    Finally, I also agree with Bruce Eckel in his book: Effective Java. I agree with using checked exceptions for recoverable errors (e.g. FileNotFoundException) and using unchecked exceptions for programming errors (e.g. NullPointerException).

    My $0.02

    Cheers,
    Clinton
  3. I like Checked Exceptions in Java and miss them a lot in VB.NET/C#. As a programmer I find coding so difficult without Checked Exceptions.
    Anil
  4. I'd say of all the Exceptions handlers I've ever written, I've say about 50% of them have actually saved my bacon. That's a whole lotta errors which might have otherwise have caused me pain and heartache and made my bosses extremely unhappy.

    Checked Exceptions might be a pain to write but man they've saved my butt.
  5. Just for the record, Effective Java is by Joshua Bloch
  6. WHOOPS!! I'm sorry Mr. Bloch. Looking on my bookshelf I totally looked at the wrong book! Doh.

    I guess I need practice reading sideways.

    Cheers.
  7. I was disappointed with how Gosling sidestepped the question about exceptions being dependent on implementation.

    For instance, suppose I had an Addable that could add two integers. One implementation would add them locally. Another would pass them off to a web service to perform the addition. So should Addable really declare an exception, just because the web service might have a network failure?

    And no... simply wrapping the exception as an AdditionException doesn't overcome the core fallacy with this strategy.

    -Tim.
  8. might?[ Go to top ]

    If you think a remote "Addable" is the same beastie as a local one, then you haven't worked too heavily with distributed systems. If a remote call is part of the possibility space, you have to specifically handle comms errors in all but the most simplistic situations.

    In other words, a local Addable is NOT the same type as a remote Addable.
  9. might?[ Go to top ]

    Um, that is *exactly* my point. They are totally differnet beasties *in implementation*. And yet, they have the same interface. So how can I treat my exceptions as an interface decision, when the are so tightly coupled to the implementation?

    With unchecked exceptions, I can delegate the choice of what exception to throw to the implementation. But how do you handle this problem elegantly with a checked exception?

    -Tim.
  10. What point? :)[ Go to top ]

    Um, that is *exactly* my point. They are totally differnet beasties *in implementation*. And yet, they have the same interface. So how can I treat my exceptions as an interface decision, when the are so tightly coupled to the implementation?

    >
    > With unchecked exceptions, I can delegate the choice of what exception to throw to the implementation. But how do you handle this problem elegantly with a checked exception?
    >


    Put another way: do you mean that throwing a runtime exception for a comm. error is elegant? ;)

    Gaah, Imagine sitting there with your calculator and suddenly while trying to calculate the answer to Life, the Universe, and Everything getting only a crashed program and some obscure stack-trace as an answer?

    > -Tim.

    /Anders
  11. distributed != local[ Go to top ]

    Um, that is *exactly* my point. They are totally differnet beasties *in implementation*. And yet, they have the same interface. So how can I treat my exceptions as an interface decision, when the are so tightly coupled to the implementation?


    You really had to pick the worst illustration of what Gosling is evading, did you...

    Contracts of local and remote components must differ or you must subscribe to some of "The Eight Fallacies of Distributed Computing" (http://java.sun.com/people/jag/Fallacies.html).

    Contract of the local implementation is something like this: "I will return the sum or crash so badly (hardware error, software bug) that there is no possibilty to recover". Contract of the remote implementation is: "I will return the sum, but don't count on it. The the network might be down, or the remote component might be off-line, or middleware might screw up, or ...".

    Anyway, read http://research.sun.com/techrep/1994/abstract-29.html.

    > With unchecked exceptions, I can delegate the choice of what exception to throw to the implementation. But how do you handle this problem elegantly with a checked exception?
    java.rmi.RemoteException and then chain the implementation exception?
    You MUST plan for failure in distributed computing. Get off the "one true path".
  12. distributed != local[ Go to top ]

    wow, i sure opened up a s**tstorm with this one, eh?

    i'll respond to you, bostjan... since you seem to encompass the numerous criticisms raised of my position.


    > You really had to pick the worst illustration of what Gosling is evading
    > did you...

    ok, i'll give you that. :)

    my off-the-cuff example was to illustrate something where the one implementation would never produce an error condition, where another produces a whole host of error conditions.

    my original point-- which i'll make again for emphasis-- is that checked exceptions can force an unnecessary coupling between the interface and the implementation.

    and in that light, while an emotional topic, i still stand by my original example.


    > Contracts of local and remote components must differ or you must subscribe
    > to some of "The Eight Fallacies of Distributed Computing"
    > (http://java.sun.com/people/jag/Fallacies.html).

    again, this is an issue of implementation, not interface. is a network class loader not a class loader, because the network may fail?

    and the defense, "these two objects can't have a common interface, because one can throw a lot more errors" doesn't work for me. if that's true, then that just simply illustrates a flaw in the current exception scheme rather than proves its a good design practice.


    >> But how do you handle this problem elegantly with a checked exception?
    > java.rmi.RemoteException and then chain the implementation exception

    well, i'm not going to buy that... that should be obvious by now :) a remote exception forces the interface to advertise the implementation, and that's my whole point.

    in some cases, it may be perfectly reasonable to have an exception that is in the domain of the problem... and *that* exception could wrap the implementation exception. but what about when there is no common domain exception, because you are doing something trivial like adding two numbers?


    > You MUST plan for failure in distributed computing. Get off the "one true
    > path".

    this has nothing to do with planning for failure... or with distributed computing for that matter. it has to do with exception handling.

    with an unchecked exception, my options for failure are limitless. i can throw whatever unchecked exception i want. with checked exceptions, the interface dictates whats throwable. so if i want to throw a remote exception or whatnot, i force my interface to reveal details about the implemention.

    further, this has nothing to do with robustness... the code that catches the exception, checked or unchecked, dicates how robust your code is. rather, its a design question. i think its an important question... and i wish gosling didn't dismiss it so lightly in the interview.

    *whew*

    -tim
  13. distributed != local[ Go to top ]

    \Tim Dwelle\
    this has nothing to do with planning for failure... or with distributed computing for that matter. it has to do with exception handling.

    with an unchecked exception, my options for failure are limitless. i can throw whatever unchecked exception i want. with checked exceptions, the interface dictates whats throwable. so if i want to throw a remote exception or whatnot, i force my interface to reveal details about the implemention.

    further, this has nothing to do with robustness... the code that catches the exception, checked or unchecked, dicates how robust your code is. rather, its a design question. i think its an important question... and i wish gosling didn't dismiss it so lightly in the interview.
    \Tim Dwelle\

    I think I hear where you're coming from, but I think you're missing a piece. When accessing a subsystem or opaque component, understanding the contract between the component and callers is crucial to using it correctly. In my mind, a correctly designed checked-exception hierarchy is a critical part of that contract, because it conveys very important _runtime_ semantics beyond the method and class signatures of your API. It's not just about writing correct code, it's also about API designers signalling to users "Hey, you! You really, really should understand that this thing can fail in this way when you start using it".

       -Mike
  14. distributed != local[ Go to top ]

    It's not just about writing correct code, it's also about API designers

    > signalling to users "Hey, you! You really, really should understand that
    > this thing can fail in this way when you start using it".

    Yep, that's the advantage of the checked exception, Mike. Well articulated.

    And I'm not necessarily saying that unchecked exceptions are a better option. Only that unchecked exceptions avoid the muddying of interface with implementation that can happen with checked exceptions.

    You may decide that this muddying is perfectly acceptable, given the benefit of the checked exception. Fine by me. But there is a tradeoff in each approach.

    And that's why, if you're James Gosling and you're pressed on this issue in an interview, you gotta say more than "That's a place where exception translation can be a good thing." That's simply a cop out.

    Wrapping the exception *may* be a perfectly valid way to avoid revealing implementation details. But what about when (1) the interface does not declare an exception that it throws, or (2) the domain exception is not appropriate for the underlying exception? And what about all the exception semantics that get "lost in translation"?

    Like I said in my original post, I wish Gosling didn't sidestep the question.

    -Tim.
  15. might?[ Go to top ]

    I think the point Ross was making is that a "Remote" Addable is a different type all together than a local "Addable". In other words, they do NOT have the same interface.

    There are many good reasons why they should be treated differently:

    http://java.sun.com/people/jag/Fallacies.html
  16. might?[ Go to top ]

    Um, that is *exactly* my point. They are totally differnet beasties *in implementation*. And yet, they have the same interface. So how can I treat my exceptions as an interface decision, when the are so tightly coupled to the implementation?


    Er no. The key distinction, which is independent of implementation, is related to the possibility of partial failure. The remote operation can fail without the caller failing (consider a JVM being killed, power being removed, or a network connector being removed, or a firewall going down or, ...).


    > With unchecked exceptions, I can delegate the choice of what exception to throw to the implementation. But how do you handle this problem elegantly with a checked exception?

    Which is a separate point which is not well illustrated by your example.
  17. They don't have the same Interface[ Go to top ]

    Surely the remote calculator must have a different interface to the local one as it has to handle network exceptions.
  18. Hejlsberg: programmers don't bother to check for exceptions, so there is little point in adding language features that force them to think about exception processing. And if we did they would just deal with them incorrectly by having empty catch clauses.

    Gosling: programmers ought to deal with failure modes (as embodied in exceptions), so we'll prevent them forgetting about it. Responsible programmers won't be satisfied by bad strategies (such as empty catch clauses), and bad code will be visible and caught during code review.
  19. That is why Thinking In C and Thinking In Java are very popular book. Clearly,
    they should think differently. Ha, I had to smile when a chief designer
    complains about a versioning Issue. In C world, exception may be a bandage that
    is attached on every wound without fore-thinking. Exceptions are the part of
    whole design issues which should be as important as API itself. Nobody
    in Java just throws as they want. If exception is changed, client code
    should be modified not because ONLY exception changes, but because it means API
    has gone though subtantial design changes. In that case, I guarantee 100% that
    some part of API has changed. I want to recommend him to "THINK IN JAVA".
    Maybe checked exceptions are not appropriate in C-blah world.
  20. The example Gosling gives off opening a file and not knowing it isn't there would be solved perfectly adequately in most cases with an unchecked exception.

    If checked exceptions encourage unwarranted exception swallowing - which in practice often seems to be the case - then a checked exception makes the adverse consequences he describes more likely not less.
  21. Bull[ Go to top ]

    The example Gosling gives off opening a file and not knowing it isn't there would be solved perfectly adequately in most cases with an unchecked exception.


    How so? Is the universal error handler going to ask the user for another file name and somehow pass it back to the code that needs it or just barf?

    > If checked exceptions encourage unwarranted exception swallowing - which in practice often seems to be the case - then a checked exception makes the adverse consequences he describes more likely not less.

    I totally disagree with you that this is the most common case. If I ever find anyone on my team writing empty catch blocks without a comment explaining why it's neccesary (something that is easily found using one of many analysis tools) I'm going to disembowel them and everyone knows it. It's all about accountability. If you squash a checked exception in a real, for sale, program, you are stupid. If you forget to catch an unchecked exception when you should have, you've just made a mistake anyone could make.
  22. Checked exceptions are most useful when they provide enough context that an intelligent reaction can be formed. An IOException provides context, and subclasses provide even more context. You can choose to simply catch IOException rather than FileNotFoundException if you think missing files are not a semi-regular happening. GetMessage() ought to provide enough information to at least allow a human user to figure out what went wrong if you choose to punt the exception to an outer handling loop.

    The problem with CHECKED exceptions is when you get an API that is really a wrapper around some other, possibly remote system, like EJB. The problem is that these wrapper exceptions destroy the hierarchy of context that existed in the system that is wrapped. Even if a nested exception is included, there is no way the calling class can understand the context of the exception. Nor should the calling class be expected to understand the context, as the whole point of the wrapper API is to hide the complexity of remote comms, db's, etc.

    For systems that are essentially wrappers, for example EJB and JDO, the right design is to throw unchecked exceptions from the API. The unchecked exception hierarchy should recreate context in terms that make sense to the user of the API.

    CHECKED exceptions are the right design for core classes, like File, where the caller has intimate knowledge of what he is calling, and knows how to react to specific exceptions.

    -geoff
  23. \Geoff Hendrey\
    For systems that are essentially wrappers, for example EJB and JDO, the right design is to throw unchecked exceptions from the API. The unchecked exception hierarchy should recreate context in terms that make sense to the user of the API.

    CHECKED exceptions are the right design for core classes, like File, where the caller has intimate knowledge of what he is calling, and knows how to react to specific exceptions.
    \Geoff Hendrey\

    I disagree completely. What you're saying, to use EJB conceptually as an example (conceptually, not necessarily the current implemenation) is that if an EJB fails, the calling application has no true options. I disagree - the user of the API needs to be aware that they are calling a potentially remote resource, and that resource can fail for several reasons. The right action is almost certainly _not_ to allow an EJB exception to propogate out of your API, but it may be to wrap the underlying exception and throw a checked exception that makes sense in your domain. It's important to hide your implementation details - like exceptions from low-level libraries. But it's a _very_ idea to hide your semantics, and this is IMHO what you're advocating. If part of your API's contract is that it's accessing a resource that can fail, then that fact should be part of your API as a checked exception. You don't want things like MalformedURLException() or RemoteException to propogate out to callers, but you may very well want to throw your own ResourceUnavailableException or the like.

        -Mike
  24. I don't see how ResourceUnavailableException gives you
    enough information to make a reasonable decision on
    how to react. It matters deeply why a resource became
    unavailable if your reaction is going to be appropriate.
    If you don't expect a reaction then it doesn't really
    matter either way.
  25. \thoff thoff\
    I don't see how ResourceUnavailableException gives you
    enough information to make a reasonable decision on
    how to react. It matters deeply why a resource became
    unavailable if your reaction is going to be appropriate.
    If you don't expect a reaction then it doesn't really
    matter either way.
    \thoff thoff\

    There are two seperate things here. Most importantly - you know that this API uses a resource that may become unavailable. It's explicitly pointed out by the contract. This is more important than many people realize.

    Second - The mythical "ResourceUnavailableException" example is a placeholder in this discussion for a meaningful Exception hierarchy. I agree that such hierarchies can be difficult to create properly, but if done so they can be priceless. For just one example - ResourceUnavailableException may have an indicator in it called "isRetriable()" - if true, it's legal to retry the operation again.

        -Mike
  26. I agree with Mike (Spille in case there's another one posting in this thread).

    For any non-trivial application, designing an exception hierarchy is important. Furthermore it is also important to design the hierarchy, so that the exceptions have semantic relevance within the code that tries to catch them.

    Meaning that if an exception is too generic to have semantic value within a segment of code, the code throwing that exception should convert it to an exception that makes more sense in that context.

    In fact, I ususally refer to this as "semantic exception evolution". All that means is that an exception arising in one of the lower layers in the application will evolve through the exception hierarchy, at each stage becoming semantically more relevant to the layer that it is caught in.

    Note that I use the term "layer" pretty loosely here. A transition from one "layer" to another (as I use it here) denotes a transition across a psuedo-boundary in the call stack, that effectively corresponds to a shift in domain, say from an WebDAV component to an ECM component, or a utility component to a business logic component, and so on.

    I use the NestableException class from the Jakarta Commons library, and find that it's convenient to derive most of my exceptions from it, so as to achieve the above effect without much ado.

    Of course I also use runtime exceptions in cases where the "potential error" information is not something that I want included in the contract of the API.

    Sandeep.
  27. Exceptions are part of the contract[ Go to top ]

    Checked exceptions, as has been pointed out in this thread, are an essential part of the method contract.

    If I have an method in an API set that encapsulates some functionality, and whose behavior is controlled by the parameters passed on to it, then IMHO, it is important that a list of the things that could go wrong in that call be documented as part of the method signature as well.

    That said, there is another school of thought, which I do not subscibe to, that suggests that just as pre and post conditions are not officially checked by Java as part of the contract between caller and callee of a method, exceptions shouldn't be either. These folks may or may not have a point. In any case, it is undeniable that checked exceptions make the Java world more predictable.

    Sandeep.
  28. I think you misunderstood me, or I needed to be clearer. When I said "right design is to throw unchecked exceptions from the API", the API I was refering to was the API of the component (the EJB, JDO, whatever).

    What I'm advocating is that an API, like JDO, does it right when it includes its own hierarchy of meaningful unchecked exceptions that provide context relative to JDO.

    Since an API like JDO or EJB is supposed to abstract the details of database connectivity, it goes against the grain to expect the calling program to know how to handle nested exceptions, like a SQL or RMI exception.

    The implementation of the API like JDO (or EJB for that matter) does the right thing to take the SQL exception, for example, and translate it into a JDODataStoreException. That way the the calling program can be written with generalized exception handlers.
  29. CanRetryException vs. FatalException[ Go to top ]

    I also like that JDO provides exceptions that all fall under either JDOCanRetryException or JDOFatalException. That provides some very useful hints on how to handle the exceptions. You might decide to catch a number of specific JDOCanRetryExceptions, to give the user retry options, whereas all JDOFatalExceptions might be logged in a single catch block, and the user pointed to a generic system unavailable message. Or you might have a totally different handling strategy, but the choice is there.
  30. \Geoff Hendry\
    Since an API like JDO or EJB is supposed to abstract the details of database connectivity, it goes against the grain to expect the calling program to know how to handle nested exceptions, like a SQL or RMI exception.
    \Geoff Hendry\

    Yes, I agree there - if you're abstracting a resource, you should throw higher level exceptions. But still keep the SQL Exception around 'cuz it _may_ be useful.

    \Geoff Hendrey\
    Since an API like JDO or EJB is supposed to abstract the details of database connectivity, it goes against the grain to expect the calling program to know how to handle nested exceptions, like a SQL or RMI exception.

    The implementation of the API like JDO (or EJB for that matter) does the right thing to take the SQL exception, for example, and translate it into a JDODataStoreException. That way the the calling program can be written with generalized exception handlers.
    \Geoff Hendrey\

    Sounds good, except for the unchecked part.

       -Mike
  31. I've always wished that Throwable had a property called "cause" (or similar) that contained another Throwable (or list of Throwable).

    That would allow you to wrap without losing data, to be able to shoe-horn in behind existing interfaces for example, hiding but not losing the details of root exceptional conditions.

    BTW - IIRC C#/.NET has this in its implementation.

    Peace,

    Cameron Purdy
    Tangosol, Inc.
    Coherence: Easily share live data across a cluster!
  32. Throwable[ Go to top ]

    "I've always wished that Throwable had a property called "cause" (or similar) that contained another Throwable (or list of Throwable)."


    Your wish has come true:
    " private Throwable cause = this;"
    http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Throwable.html#Throwable(java.lang.Throwable)

    >BTW - IIRC C#/.NET has this in its implementation.

    What an inovation. ;)
  33. More chiming in on the chiming in[ Go to top ]

    I especially like this exchange from the interview:

    Venners: "I find that catch clauses usually have a natural home—the method that has enough contextual knowledge to know how to deal with the exception."

    Gosling: "[Yes], the knowledge of the situation is always fairly localized...Having one big catch clause on the outside really only works if your exception handling philosophy is simply to die."

    I consider the lack of checked exceptions to be one of the major "whoa, they seriously flubbed that" moments in C# ("virtual" is the other). Thanks to Gosling for taking it on.

    And yes, Bloch's section on exceptions in Effective Java is good stuff.
  34. What Andesr said[ Go to top ]

    I think the quote is misstatement of what Anders said. He's not saying that all of your exception handling is global - there are obviously lots of good cases where you use very local exception handling.

    He's saying that for exceptions that aren't handled locally, there's little reason to handle them specifically in a global handler. If you don't handle a file not found exception near where it happens, your global handler probably can't do anything *specific* based on that exception.

    I think that's clearer if you read the original interview, and I don't think Bill pulled out a very good quote.

    On the virtual case, you might be interested in this:

    http://www.artima.com/intv/nonvirtual.html
  35. On the non-Virtual side[ Go to top ]

    \Eric Gunnerson\
    On the virtual case, you might be interested in this:

    http://www.artima.com/intv/nonvirtual.html
    \Eric Gunnerson\

    I read the entire interview, and frankly the case for a non-virtual default for methods seemed like a lot of double-talk to me. Given that we are talking about Microsoft, I'd be willing to bet that performance was the number one reason for defaulting to final methods. In fact the entire C# language seems to make it as hard as possible to use virtual methods....

        -Mike
  36. On the non-Virtual side[ Go to top ]

    Mike:
    I read the entire interview, and frankly the case for a non-virtual default for methods seemed like a lot of double-talk to me.


    Agreed. I think the unsaid reason is that of cross-languages. I weblogged about it.

    --
    Cedric
  37. On the non-Virtual side[ Go to top ]

    Cedric, you make a good case. I wouldn't be surprised if it was both for cross-language (read: C++) and performance issues combined. I also wouldn't be surprised if this wasn't a mandate passed down from on high, and he's possibly shy about discussing it.

    Oh, and thanks for the nod in the Blog, but don't make a habit of it - the JBoss people will point to it as proof positive that I'm in bed with Weblogic. ;-)

        -Mike
  38. On the non-Virtual side[ Go to top ]

    Mime:
    Oh, and thanks for the nod in the Blog, but don't make a habit of it - the JBoss people will point to it as proof positive that I'm in bed with Weblogic. ;-)


    But... you are, right? Otherwise I'll remove the praise in my blog :-)

    --
    Ced
  39. On the non-Virtual side[ Go to top ]

    \Cedric\
    But... you are, right? Otherwise I'll remove the praise in my blog :-)
    \Cedric\

    Actually, it's rather embarrassing to admit, and it will probably get me in trouble with the Secret Inner Circle of Masquerading Weblogicers, but in my current job I'm (oh the shame!) interfacing with a group using another app server - one with a decided bluish tinge to it. But please, tell the circle I never exhaled!!!

        -Mike
  40. J# ?[ Go to top ]

    <Cedric Beust>
    Agreed. I think the unsaid reason is that of cross-languages. I weblogged about it.
    </Cedric Beust>

    J# supports checked exceptions.. doesnt it?
  41. There are two kinds of Exceptions:

    - Those that can be caught and corrected locally
    - Those that cannot be caught and corrected locally

    In my experience, 95% of all exceptions fall into the second category. If a method can't possibly recover from an exception it shouldn't trap it; instead, should bubble it up (i.e. throws Exception).

    This leads me to my next point: Exception handling was designed to centralize error handling. Instead of having tons of return code checks all throughout your code for "database failure" an object would be "thrown" onto the stack and propagated up for a generalized handler to log and properly recover. Recovery here might mean halting the application. However, the responsibility for "checking" this condition is largely removed from the application. Going back to the first category, Java does not support resumeable exceptions (nor does .NET, to be fair). This greatly reduces their efficacy in these situations, usually requiring ugly loops and breaks.

    In my opinion, Anders made the right call. He recognized these two categories and said, "If a programmer can trap and correct, let them; otherwise, it gets bubbled up". One certainly doesn't loose anything not having to explicitly declare exceptions in the interface. Rather, I'd say one gains quite a lot in flexibility and sanity.
  42. This leads me to my next point: Exception handling was designed to centralize error handling.


    I disagree strongly. Exceptions are useful for that, but that's not why they're a language feature.

    I think they're a replacement for return codes, which make it too easy to ignore failure and continue. Even unchecked exceptions prevent a failure from being swallowed by default; checked exceptions are simply useful for the cases where there's a potential for either (1) recovery or (2) meaningful reclassification of the error.

    The question over whether the language should include checked exceptions boils down to whether it's ever reasonable to force the client of an API to think about (1) and (2). I think it is. The question of whether a particular exception should be checked revolves around whether (1) and/or (2) are the excepected cases for that particular exception.
  43. \Jeffrey Panici\
    - Those that can be caught and corrected locally
    - Those that cannot be caught and corrected locally

    In my experience, 95% of all exceptions fall into the second category. If a method can't possibly recover from an exception it shouldn't trap it; instead, should bubble it up (i.e. throws Exception).
    \Jeffrey Panici\

    In a well-designed application using well-defined APIs, the situation is largely reversed from what you describe, particularly if you're talking about any kind of distributed system, or any kind of system which deals with external resources. There are many types of errors in those situations where the developer can do something meaningful beyond just printing a message or aborting.

    The problem, though, is two-fold:

       a) Many base J2EE APIs started out with pretty lousy Exception hierarchies, many still have them. This makes it tough to figure out the real underlying semantics of the error.

       b) Many programmers took a) above as a cue, and just decided "the hell with it".

    However, I have seen applications where people went the extra mile and wrapped the J2EE/J2SE exceptions with meaningful stuff (after _much_ grunt work), and also have their own intelligent exception hierarchies. These are a joy to use.

    \Jeffrey Panici\
    This leads me to my next point: Exception handling was designed to centralize error handling. Instead of having tons of return code checks all throughout your code for "database failure" an object would be "thrown" onto the stack and propagated up for a generalized handler to log and properly recover. Recovery here might mean halting the application. However, the responsibility for "checking" this condition is largely removed from the application.
    \Jeffrey Panici\

    This is completely false. Exception handling was introduced because error return codes are too often ignored, and when they're not they clutter up the mainline code something horribly. Exceptions fixed this, but they were from the getco designed to be caught at the earliest moment something meaningful could be done about them. This is very different from the idea of a "generalized handler". If such a handler is invoke, that usually means that either a) something unbelievably bad happened, or b) the underlying code is letting too much bubble up.

    \Jeffrey Panici\
     Going back to the first category, Java does not support resumeable exceptions (nor does .NET, to be fair). This greatly reduces their efficacy in these situations, usually requiring ugly loops and breaks.
    \Jeffrey Panici\

    There's a very good reason why resumeable exceptions aren't implemented in either language - they lots of extra complexity in the VM, they induce a significant performance hit, and it confuses the hell out of programmers. The language designers (wisely I believe) left it up to application developers to decided if they needed restartability, and if so to provide it themselves.

    \Jeffrey Panici\
    In my opinion, Anders made the right call. He recognized these two categories and said, "If a programmer can trap and correct, let them; otherwise, it gets bubbled up". One certainly doesn't loose anything not having to explicitly declare exceptions in the interface. Rather, I'd say one gains quite a lot in flexibility and sanity.
    \Jeffrey Panici\

    I think you lose a lot - you lose a piece of your API contract that says "this code can fail in meaningful ways, and as an API writer I insist you at least consider it".

       -Mike
  44. why "insist"[ Go to top ]

    I think Mike stated it perfectly that checked exceptions indicate "this code can fail in meaningful ways, and as an API writer I insist you at least consider it". The problem with this is that it assumes that "meaningful" is the same to everyone. If you are doing a quick prototype or working on a seldom used susbsystem, recovery from obscure errors is less desirable. The difference is that you can always catch an unchecked exception, but you can never ignore a checked exception.
  45. Checked Exceptions and Once and Only Once[ Go to top ]

    I think you lose a lot - you lose a piece of your API contract that says "this code can fail in meaningful ways, and as an API writer I insist you at least consider it".


    Mike, I hear what you are saying. But how can an API writer know whether the failure of one of it's methods is meaningful for the caller? Doesn't that depend on the caller?

    For example, why am I forced to handle FileNotFoundException if I have already checked that the file exists?
  46. Checked Exceptions and Once and Only Once[ Go to top ]

    \Pato Loco\

    /Mike/
     I think you lose a lot - you lose a piece of your API contract that says "this code can fail in meaningful ways, and as an API writer I insist you at least consider it".
    /Mike/

    Mike, I hear what you are saying. But how can an API writer know whether the failure of one of it's methods is meaningful for the caller? Doesn't that depend on the caller?

    For example, why am I forced to handle FileNotFoundException if I have already checked that the file exists?
    \Pato Loco\

    My point of view is pretty well captured in my phraseology above - and you meanly went and altered it :-)

    As I said, this time with some emphasis - "this code _can_ fail in meaningful ways, and as an API writer I insist you _at least consider it_". The API writer can't divine the intent of all users, but the API writer _can_ do her best to convey meaningful and easy to use semantics to users. Some (or all) of this may be used, tweaked, thrown away, refactored, abused, or worked around, but these facts don't change the responsibility of the original API writer. It's when the API writer gives up in despair of all the possible uses (and forgets her own original intent) that you end up with a, shall we say, crappy API.

         -Mike
  47. PLEASE DONT "throws Exception"[ Go to top ]

    |
    |There are two kinds of Exceptions:
    |
    |- Those that can be caught and corrected locally
    |- Those that cannot be caught and corrected locally
    |
    |In my experience, 95% of all exceptions fall into the second category. If a
    |method can't possibly recover from an exception it shouldn't trap it; instead,
    |should bubble it up (i.e. throws Exception).

    AAGGHHHH! NoooOO!

    Well, you were going fine until you said "throws Exception" ;-)

    "throws Exception" highlights perfectly the problem with Checked Exceptions. The programmer. (My apolagies if I have taken *your* particular example out of context - but this is a common antipattern)

    Throws Exception is the worst of both worlds. You are now forcing the hapless caller of your code to catch _all_ exceptions! Even the ones they can do nothing about. Even the RuntimeExceptions! And to add insult to injury, you have given this hapless user absolutely no clue as to what might come out.

    I know *why* this is often done - it means you can ignore all the checked exceptions that come out of the runtime library classes.

    Bottom line:
    Checked exceptions are good. (wait until you dont have them - c#/c++)
    Catching and wrapping exceptions is good encapsulation. (something that unchecked exceptions dont encourage)
    But they are not the only show in town (use runtime exceptions when they make sense)
    And for gods sake, know the difference between the two when you go to an interview!

    The whinge that I have is why, oh, why did RuntimeException extend Exception?
    I think that in hindsight, there should have been a clearer distintion between AppException and SystemException a la CLR...

    -Nick
  48. <Golsing>
    Lots of newbie's coming in from the C world complain about exceptions and the fact that they have to put exception handling all over the place—they want to just write their code. But that's stupid: most C code never checks return codes and so it tends to be very fragile. If you want to build something really robust, you need to pay attention to things that can go wrong, and most folks don't in the C world because it's just too damn hard.
    </Gosling>

    I quit long ago trying to convince someone that checked exceptions is actually one of the most fundamental features of Java… Most of the detail-code-examples discussions lead to nowhere due to simple basic misunderstanding of the core concepts behind exception handling in general (although I appreciate Mike Spille dedication to prove his point with usual stamina).

    Anyways, it’s helpful to have someone with certain weight in Java community to stand up for this point.

    Regards,
    Nikita.
    Fitech Labs.
  49. "Never stop, never stop fighting till the fight is done."

    It applies even moreso for me, 'cuz I don't even have a badge. :-)

        -Mike
  50. It is evident that the use for checked exceptions become most apparent when you don't have them ;-)

    Peace,

    Cameron Purdy
    Tangosol, Inc.
    Coherence: Easily share live data across a cluster!
  51. Troubling[ Go to top ]

    "Adding a new exception to a throws clause in a new version breaks client code. "


    Adding a new exception to a throws clause doe NOT break client code(does not
    break binary compatibility).Its embarrassing that the interviewers/tech editors
    did not catch this.


    >"You don't want a program where in 100 different places you handle exceptions and pop up error dialogs...The exception handling should be centralized,"

    Refactorings/Design patterns can be used centralize exception handling. See:
    http://www.refactoring.com/catalog/extractMethod.html

    >"I'm a strong believer that if you don't have anything right to say, or anything that moves the art forward, then you'd better just be completely silent"

    Does C# move art forward?
  52. Bruce vs Gosling[ Go to top ]

    I agree w/ Bruce Eckel that static typing MIGHT be overhyped. There are many languajes that do without and they are simpler and more elegant.

    However, I LOVE CHECKED EXCEPTIONS!! Back in the C++ days I came to the conclusion that comercial programmers need to start any module thinking of how to handle errors. Doing it right can mean the diff between hours of debugging and error-free code.

    I love Java's solution because it helps me quickly ensure that I handle all errors appropriately.

    Of course it is important to follow the guidelines to make this effective (ex: joshua block in Eff Java). There is no use in writing "throws Exception". But as many have pointed out.. Java makes these obvious lapses of programmer judgement obvious since we can easily detect these code smells and take appropriate action.. the same goes for empty catch() blocks.

    When I program in PHP.. I am very troubled by its lack of serious and standardized error checking. It is the main reason I use PHP less than Java. Java is for production quality. Don't like it.. go back to C++. ::)
  53. Anders should read Joshua Bloch[ Go to top ]

    "Anders Hejlsberg: Let's start with versioning, because the issues are pretty easy to see there. Let's say I create a method foo that declares it throws exceptions A, B, and C. In version two of foo, I want to add a bunch of features, and now foo might throw exception D. It is a breaking change for me to add D to the throws clause of that method, because existing caller of that method will almost certainly not handle that exception. "

    Joshua Bloch: Item 43 - Throw exceptions appropriate to the abstraction. If you do this you can add a new type of exception that inherits from the original.


    "Anders Hejlsberg: The scalability issue is somewhat related to the versionability issue. In the small, checked exceptions are very enticing. With a little example, you can show that you've actually checked that you caught the FileNotFoundException, and isn't that great? Well, that's fine when you're just calling one API. The trouble begins when you start building big systems where you're talking to four or five different subsystems. Each subsystem throws four to ten exceptions. Now, each time you walk up the ladder of aggregation, you have this exponential hierarchy below you of exceptions you have to deal with. You end up having to declare 40 exceptions that you might throw. And once you aggregate that with another subsystem you've got 80 exceptions in your throws clause. It just balloons out of control. "

    Joshua Bloch: Item 43 - Throw exceptions appropriate to the abstraction. Avoids the problem entirely. APIs should hide inner details, including the exceptions. If you use the cause stuff you can still get to the original cause if you need to.

    ME: I usually avoid declaring more than one exception thrown. If I have a method.. depositMoney() I declare a checked exception DepositException (I have a script in my editor that does it automatically). If another exception is necesary I consider it just another form of DepositException. There is a subtle difference between this and "throws Exception" because DepositException is related to depositing... not SQL not IO, not Servlets, etc.. If I were to add SQLException to depositMoney() (for example), I consider that an Encapsulation violation because I am revealing that depositMoney() uses JDBC (what if it is XML based? or file based? or none?).

    Anders should read Joshua Bloch.

    (He is right tho that Exceptions are a new experiment for a lot of us.. only now are the best practices slowly coming to light..)
  54. We need checked exceptions[ Go to top ]

    This discussion reminds me of "old times" when I tried to convince a Fortran programmer of using Pascal. He said "OK, I'll try a simple program over the weekend". When I saw him again on Monday, he said that Pascal is inefficient (actually he used some less friendly words) because it takes him much too long to declare all the labels that he needs for his gotos.

    If you think of checked exceptions as an annoyance that make it more diffcult to program the way you are used to, then, of course, you end up declaring "throws Exception" on every method or write "catch (Exception e) {}" and you claim that checked exceptions are very inefficient. You have to change your point of view (like it took the Fortran programmer some time to value the existence of loop constructs that reduced the number of labels he needed to declare).

    We have found in our projects that checked exceptions raise the quality of your software tremendously. The average programmer is often fully occupied with following the main track of the program. He may be aware that a file open may fail (though you shouldn't rely on it!), but he almost certainly fails to be aware of the exceptional conditions that can arise in a distributed system. Checked exceptions make him aware of what can go wrong, and, OK then it is a cultural issue not to allow "catch (Exception e) {}" (btw. we prohibit this by using the checkstyle tool).

    The exception handling stategies may be different depending on the environment. We accept limit "throws Exception" declaration (though we prefer "throws ApplicationException") e.g. in a GUI environment if the exception is caused by a temporary failure (you can then display a "try again later" and everything is OK). But this is not a useful strategy for programs running as servers with no user interaction. With this kind of programs it is, however, especially important to cover all possible error cases at compile time, because there simply is nobody that can handle them at runtime.

    We all tend to be lazy. Checked exceptions shake you up. You have to think about something and explicitly state your opinion instead of silently ignoring the problem or thinking "maybe the guy who does the modul that invokes my methods thinks about the exceptions". You have to develop, teach and establish exception handling strategies. But once you have done this, the quality of your code increases significantly.

        Michael Lipp
  55. If the semantics of the program demand that an exception be taken into account and treated, the programmer will treat it, checked or unchecked. Don't tell me that the programmer needs to be reminded by the compiler that the network can go down or something.
    However, let's say we have a series of n methods from m classes that are called to achieve one logical goal, and that most of those methods do intensive file handling. The semantics of the program demand transactional behavior, it's all or nothing. It only makes sense to catch one IOException in one place (the root of the execution tree of the n methods) and abandon the whole process if the exception is thrown. However, with checked exception the programmer has to write a significant number of throws IOException. That's not too bad, but it's not helping.
    The bottom line, programmers will treat only the exceptions the have a role in the semantics of the application. If a file is missing, you don't look for it somewhere else ! If the network is down, you don't call the police ! That's just a 'Internal Error' dialog.
  56. \Edward Vrajmasu\
    The bottom line, programmers will treat only the exceptions the have a role in the semantics of the application. If a file is missing, you don't look for it somewhere else ! If the network is down, you don't call the police ! That's just a 'Internal Error' dialog.
    \Edward Vrajmasu\

    This is a style that says "any error means my thread must fail". It's valid approach, but many people take another, more sophisticated approach where exceptions can be acted on in a meaningful way. But, as I mentioned, the key is to have a meaningful exception hierarchy, and often to have more information inside your exception than just a String message.

        -Mike

  57. > This is a style that says "any error means my thread must fail". It's valid approach, but many people take another, more sophisticated approach where exceptions can be acted on in a meaningful way. But, as I mentioned, the key is to have a meaningful exception hierarchy, and often to have more information inside your exception than just a String message.
    >
    > -Mike

    I see what you mean. What i said was that many exceptions represent the absence of critical resources (or their failure) and it's good practice to fail. If we don't fail, we accept an inconsistent state and that's not good.
    Any domain model should clearly define when a failure is critical and when it is not. I think most IO failures are critical. The db is down, the net is down, how can I do my stuff?

    In the case of the rare ultra resilient system that you are talking about, being a rare case, the more we don't need checked exceptions because it's a specialized thing and the programmers will have that in mind. Again, most applications have well defined external/collateral requirements for sane execution. If those fail, you should fail too.
  58. James Gosling Chimes In on Checked Exceptions[ Go to top ]

    If the semantics of the program demand that an exception be taken into account and treated, the programmer will treat it, checked or unchecked. Don't tell me that the programmer needs to be reminded by the compiler that the network can go down or something.


    Actually I have worked with quite a few programmers over the years who needed exactly this kind of reminder. Years ago when I was working on a C++ client-server application I used to get really annoyed because time and again I would be testing other people's code only to find that they had given no thought whatsoever to what they should do if the client couldn't connect to the server. Absolutely basic requirement for a client-server app, but there was this blind assumption that the server was always going to be up and running, the app would always be configured correctly, and the network was never going to fail. People simply didn't think about it. So to me, it's a good thing to force the programmer to sit down and think "What should I do if the network goes down?" because my experience suggests that they don't think of these things unless somebody or something reminds them to think about it.

    > If a file is missing, you don't look for it somewhere else.

    Surely this is a perfectly valid response for some applications? If the application tries to open a file and the file's not there, pop up a window and ask the user where it is, then continue. The decision as to whether or not to continue is taken in the context of where the "open file" instruction has been called. In the particular case that you describe it may not make sense to locate the file and try again but in other applications it does. The important point is that the person writing the component that opens the file doesn't know which kind of application is going to invoke it.

    If I am writing a reusable component which will be called from a number of different clients (including some which I don't know about when I write the component), I need to give some thought as to how I will notify these clients that an error has occurred in my component. How the client handles these errors is not my business, but I do need to make sure that the client is aware of the error so that it can respond appropriately. If I throw a checked exception, I am saying up front during the development process to the person programming the client, "Look, this error condition may occur. You really need to think about what you're going to do here. What you do is up to you, but at least be aware that this can happen." On the other hand, if I throw an unchecked exception, then I'm leaving it until runtime to tell him, "Look, this error condition has just occurred, and you may or may not have thought about it before hand. What happens next is up to you."
  59. No doubt about it - when you first start working with Java checked exceptions are a real pain. I hated them. Then I found my code was staying up and running for a long time and revised my opinion somewhat.

    You could argue (half seriously) that Microsoft has always taken a somewhat lackadaisical approach to error handling which is why Microsoft products:
    a) Crash a lot and
    b) Contain error messages like “An error occurred. Error. Error. There is no message for this is error. Error” (insert cunning error message here).

    Of course, neither COM nor the Windows API’s support exceptions in any form so those of us who develop with Microsoft products are pretty grateful for anything (makes a change from an error resume next anyway!)
  60. I recently wrote some encryption code. I had to deal with 6 different possible exceptions being thrown from 1 method that I wrote which did the encryption. That is crazy. It makes fast development, propotyping etc. a real pain. What happens a lot of time is developers instead catch Exception and bury the exception.
  61. There's no doubt that some Java programmers are to anal about creating pointless Exception subclasses non-recoverable situations but having already seen a C# application fail after deployment because someone didn't handle an exception at the right tier - I am 100% in favour of checked exceptions.
  62. There's no doubt that some Java programmers are to anal about creating pointless Exception subclasses non-recoverable situations but having already seen a C# application fail after deployment because someone didn't handle an exception at the right tier - I am 100% in favour of checked exceptions.


    What is your definition of failure? For me, an application fails if it doesn't meet its requirements. Now, in the failure case you mention above, was there an actual requirement that was not met? If there was no such requirement, how can it be a failure? If there was, how come the requirement wasn't tested before deployment?

    People in favour of checked exceptions often say that it makes an application more reliable. But if you want a reliable application then there's really no substitute for testing. Even if you use checked exceptions to handle certain failure cases, you still need to test them. And since you are going to test your failure cases anyway then, in my point of view, it doesn't really matter whether you use checked or unchecked exceptions as far as the reliability of your application is concerned.
  63. Pato Loco - it's not a question of absolutes, which is how you've framed your response. It's a question of making your application 100% bulletproof. It's a question of "what techniques are likely to _increase_ your robustness?". There's a difference between trying to increase your impact somewhere and actually achieving it 100%.

    Checked exceptions are a tool that's designed to increase the likelihood that something will be handled correctly. It's not a substitute for anything - instead, it's one more piece of the puzzle that can help you make your code better.

    And as I said in another post, you can pay the man now or pay more later. In the long haul, I've found checked exceptions decrease the overall development and maintenance times for large projects - I pay the hit up front to get corrections right, to communicate them forcibly through Checked exceptions, and having to deal with a compiler complaining about my mistakes. That hit is small in comparison to paying for it later, or trying to do manually what checked exceptions does automatically.

        -Mike
  64. Pato Loco - it's not a question of absolutes, which is how you've framed your response. It's a question of making your application 100% bulletproof. It's a question of "what techniques are likely to _increase_ your robustness?". There's a difference between trying to increase your impact somewhere and actually achieving it 100%.

    > Checked exceptions are a tool that's designed to increase the likelihood that something will be handled correctly. It's not a substitute for anything - instead, it's one more piece of the puzzle that can help you make your code better.
    >
    > And as I said in another post, you can pay the man now or pay more later. In the long haul, I've found checked exceptions decrease the overall development and maintenance times for large projects - I pay the hit up front to get corrections right, to communicate them forcibly through Checked exceptions, and having to deal with a compiler complaining about my mistakes. That hit is small in comparison to paying for it later, or trying to do manually what checked exceptions does automatically.

    Mike, I'm actually trying to decide whether I should make the exceptions thrown by my API checked or unchecked, so thanks for taking the time to discuss this matter.

    What I'm struggling with is that I hear people advocating the use of checked exceptions for robustness sake, but I haven't seen any concrete evidence that this is the case. It would be nice if someone could show me some practical code where the use of checked exceptions has increased the robustness of an application.

    What I do know, though, is that checked exceptions are irritating in many cases. For example,

    File f = new File(...);
    if (f.exists()) {
        FileInputStream fis = new FileInputStream(f);
    } else {
        ....
    }

    This code forces met to handle FileNotFoundException although I know this will never happen.

    Another example:

    byte[] bytes = ...;
    String s = new String(bytes, "UTF-8");

    This code forces me to handle an UnsupportedEncodingException although I know this will never happen.

    One more (and then I'll stop):

    Class cls = Class.forName("java.lang.String");

    This code forces me to handle ClassNotFoundException although I know this will never happen.

    So I find checked exceptions annoying in practice. I would really like to see some concrete application code where checked exceptions are helping to increase the reliability of the application.
  65. You're using trivial examples where your decision happens to be "I've considered what the API is telling me can fail, and will ignore it". More often, especially in complex software, the mental thinking is more along the lines of "Huh, this can be a ClassNotFoundException - I better make sure I deal with that".

    For example, consider this code that reads serialized objects over the wire, you may write the following, with "in" an ObjectInputStream:

          if (format == -1) {
            format = in.readInt ();
          }
          switch (format)
          {
          case 0xdeadbeef:
            if (channel == null) {
              channel = in.readUTF();
            }
            if (len < 0) {
              len = in.readInt();
            }
            if (len >= rawBytes.length) {
              rawBytes = new byte[len + 500];
            }
            if (numRead == -1) {
              numRead = 0;
            }
            while (len > numRead) {
              int readNow = in.read (rawBytes, numRead, len-numRead);
              numRead += readNow;
            }
            ObjectInputStream ois = new ObjectInputStream (new ByteArrayInputStream (rawBytes));
            Object newObject = ois.readObject();
            ois.close();
            result = new Packet (channel, newObject);
            format = -1;
            channel = null;
            numRead = -1;
            len = -1;
            break;
         default:
            throw new ProtocolMismatchException ("ERROR: bad magic number on protocol");

          }

    The above is the bulk of an reader method that sucks serialized objects off a stream. Obviously, since we're talking network stuff you know that IOExceptions may be involved (ProtocolMismatchException is a subclass of that). However - due to some strange shadow in my brain I often forget that this sort of code can throw a ClassNotFoundException, because the client has this class but the server does not. Using checked exceptions here (in this case in ObjectInputStream) reminds me that _this_ sort of stream can not only have IOException problems, but also ClassNotFound problems.

    So my method here is tagged with IOException and ClassNotFoundException, and a
    a higher-level handler deals with ProtocolMismatchException, ClassNotFoundException, and IOExceptions differently (the former two send a message back down the wire saying either "you're using a bad protocol!" or "I don't know about the class of the object you've sent me", the latter results in a closed stream and an audit message being closed about the error).

    For developers serious about robustness and correctness, and who also may happen to be harried and dealing with complex issues to begin with, Checked Exceptions remind them what the important robustness issues are. If I were using an API designed like Spring, my little spot-blindness on an issue like this (constantly forgetting about ClassNotFoundException) would repeatedly bite me in the ass, most likely in production, all because the designer felt that Exception handling should be advisory and optional, and not something that should be intrusive.

        -Mike

    * Note: the above code is only a fragment, not complete, and has been slightly altered to protect the guilty. Enough of the real code has been retained to show the flavor and seasoning of the original.
  66. <Mike>
    If I were using an API designed like Spring, my little spot-blindness on an issue like this (constantly forgetting about ClassNotFoundException) would repeatedly bite me in the ass, most likely in production, all because the designer felt that Exception handling should be advisory and optional, and not something that should be intrusive.
    </Mike>

    I strongly agree with this statement, Mike. Paraphrasing Gosling, every time I see a framework like Spring, that wraps checked exceptions into unchecked -"it gives me creeps".

    Regards,
    Dmitriy Setrakyan
    xNova™ - Reusable System Services for Java and .NET

  67. If I were using an API designed like Spring, my little spot-blindness on an issue like this (constantly forgetting about ClassNotFoundException) would repeatedly bite me in the ass, most likely in production, all because the designer felt that Exception handling should be advisory and optional, and not something that should be intrusive.

    Please explain how this would bite you only in production if you'd done any testing. Spring won't swallow the exception if you don't catch it, so any tests for that code will fail. If you trust the compiler to help you safely forget the implications of what you're doing, you'll get caught out sooner or later, not just with exception handling.


    every time I see a framework like Spring, that wraps checked exceptions into unchecked -"it gives me creeps"

    We know that from every other thread on checked exceptions on TSS. I'm not sure that it makes us much wiser. Btw, many frameworks and applications do this--it's not just Spring. However, no one is forcing you to use them.

    I was disappointed with James Gosling's interview--not because I disagreed with what he said, but because I didn't think it was a particularly profound discussion. I don't think that interview or this thread is getting us any farther along than every other thread on exceptions here. It's always the same people posting and they (we) just reiterate the same opinions on each side. (Hence the reason I hadn't posted to this thread until Dmitriy's comment on Spring.) And for some reason the opinions are always very emotive on this issue, especially from the checked exception folk.

    We're all entitled to our opinions. I think we should agree to disagree on this one. Having done large projects successfully with both exclusively checked and substantial use of unchecked exceptions my experience is that it's not as simple as "only one way works." So neither side is going to win a decisive victory.

    Btw I actually like the fact that Java has checked exceptions. I use them to enforce callers to react to recoverable conditions. I think I would miss that in C#. It's just that I see an important role for unchecked exceptions as well.

    Regards,
    Rod
  68. <Rod>
    I don't think that interview or this thread is getting us any farther along than every other thread on exceptions here. It's always the same people posting and they (we) just reiterate the same opinions on each side.
    </Rod>

    Hold on Rod. I hope this thread is going to be different in that we are going to see some real code that proves that checked exceptions are essential for developing reliable applications and that the same reliability can not be achieved by using unchecked exceptions with top-level try/catch blocks.

    Let's stop throwing opinions at each other, let's discuss some real code.
  69. Hold on Rod. I hope this thread is going to be different in that we are going to see some real code that proves that checked exceptions are essential for developing reliable applications and that the same reliability can not be achieved by using unchecked exceptions with top-level try/catch blocks. Let's stop throwing opinions at each other, let's discuss some real code.
    I agree that we need evidence rather than opinions. Obviously you are sincere in wanting to explore this, rather than just repeat a position.

    However, I don't think that code snippets in a discussion forum are adequate to explore this. For example, one of Anders Hejlsberg's points, which I tend to agree with, is that exclusive use of checked exceptions looks great in small examples but doesn't scale so well to large code bases.

    Unchecked exceptions don't necessarily mean top-level catch blocks. It is possible to catch them.

    My experience is that it definitely is possible to build reliable applications making substantial use of unchecked exceptions. As with checked exceptions, it depends on coding standards, and a host of other things besides exceptions, such as testing.

    Regards,
    Rod
  70. two cents[ Go to top ]

    I think people take side on this issue based on their “managerial preferences”. The guys who prefer “checked exception for ever thing” prefer their subordinates to report to them every problem they come across. They want to give it a try even when they are not capable of doing so. The guys who prefer Unchecked exception trust more their subordinates and they assume if the subordinates fail drastically may be nothing can be done about it unless they are _really_ interested in doing it by themselves.

    The “Checked” guys being autocratic are more emotive as you pointed out I guess.
  71. Hi Rod,

    Before addressing your comment, I'd just like to point out that you and I agree on the general idea that "There is room for both checked and unchecked exceptions in quality software". The difference is that I tend to design with checked exceptions by default and I will consider making the exception unchecked on a case-per-case basis.

    Rod:
    My experience is that it definitely is possible to build reliable applications making substantial use of unchecked exceptions.


    Obviously. You say that you were able to build reliable software based on unchecked exceptions. I have no problem believing that, but you need to keep in mind you (probably) achieved this using Spring, your own framework.

    In other words, you knew what methods were throwing unchecked exceptions, because you wrote that code.

    I wonder if someone who can only rely on the Spring documentation would have been able to do as well (I am not saying the Spring documentation is bad, it's actually pretty good, but just pointing out that documentation falls out of synch with code, it's just a fact of life).

    Checked exceptions force you to consider the error code as soon as you write the code, regardless of whether the documentation is accurate or whether you have the source of the API you are using. There is no cheating. I think this is a very healthy thought process.

    And if you are not sure what to do with the checked exception, you declare it in your throws clause and defer the decision higher in the call stack, where it will eventually make sense to catch it.

    --
    Cedric
    http://beust.com/weblog
  72. Hi Cedric.

    You say that you were able to build reliable software based on unchecked exceptions. I have no problem believing that, but you need to keep in mind you (probably) achieved this using Spring, your own framework.

    In other words, you knew what methods were throwing unchecked exceptions, because you wrote that code. I wonder if someone who can only rely on the Spring documentation would have been able to do as well (I am not saying the Spring documentation is bad, it's actually pretty good, but just pointing out that documentation falls out of synch with code, it's just a fact of life).

    Your point about documentation is fair. But in this case, Spring provides a simple and stable exception hierarchy. All data access operations can result in DataAccessException or subclasses. This hierarchy hasn't changed since I first wrote the code, despite lots of enhancements to the JDBC implementation. Note that there's no problem adding leaf classes, as they won't break existing code that catches superclasses.

    So I think having a well-defined hierarchy is important. Throwing unchecked exceptions around randomly is certainly a recipe for problems.

    This issue applies with checked exceptions, as well. If I published a framework, and then decided to add a bunch of new checked exceptions to the APIs in a revision, it would break all code using it and cause big problems for users.

    I know of quite a few Spring applications in production, and their developers seem happy with their ability to do error handling.

    Regards,
    Rod
  73. Nowhere?[ Go to top ]

    Hi Rod

    Rod: "If I published a framework, and then decided to add a bunch of new checked exceptions to the APIs in a revision, it would break all code using it and cause big problems for users."

    Adding checked exceptions to APIs will *NOT* break code using it. Your catch alls
    will work as bad as they did before.

    Hejlsberg:"Adding a new exception to a throws clause in a new version breaks client code."

    You should not repeat things from M.S. infomercials.

    Dave
  74. Nowhere?[ Go to top ]

    Adding checked exceptions to APIs will *NOT* break code using it. Your catch alls will work as bad as they did before.
    So a particularly bad exception handling strategy will still work. Brilliant. If you have "catch alls" checked exceptions are made almost meaningless--ie your code will compile if you delete all the catch(MeaningfulException e) blocks.

    You should not repeat things from M.S. infomercials.
    I've made this particular point in previous threads and publications before that interview. I find your assertion insulting. My ideas on this issue are my own. It just happens that a lot of people agree.

    In any case, why is James Gosling talking about Java not an infomercial, while the designer of C# talking about C# is?
  75. Nowhere?[ Go to top ]

    DH:Adding checked exceptions to APIs will *NOT* break code using it.

    Rod Johnson:
    "If you have "catch alls" checked exceptions are made almost meaningless--ie your code will compile if you delete all the catch(MeaningfulException e) blocks. "

    I dont think you understand. Nobody is talking about compiling:
    "it would break all code using it and cause big problems for users. "
    "Adding a new exception to a throws clause in a new version breaks client code."

    The client binaries should keep humming (running).
    But if one was to ever re-compile client code the compiler should do its job.
    This is what makes checked exceptions so wonderful.

    >It just happens that a lot of people agree.

    A quick read of these 'nowhere threads' suggests you are in a vocal minority.

    Dave
  76. It's all about style[ Go to top ]

    <David Hunter>A quick read of these 'nowhere threads' suggests you are in a vocal minority.</David Hunter>
    Minority/Majority does not make a case for an argument being correct. As far as being vocal, many who support unchecked exceptions simply aren't spending a lot of time arguing about it anymore since it's been beaten to death so often before. (I will also suggest that many supporting checked exceptions are keeping silent as well for the same reasons). I've remained silent for a while because it's a waste of time, I don't believe there is a "right answer", theres only an answer that is right for a particular programmer, team, or project.

    I think many are missing a major point, and that is that those who support using unchecked exceptions are NOT (for the most part) saying they don't use/like checked exceptions. They are simply saying that they prefer using them in a different way or on a different scale. We are also saying that a meaningful exception hierarchy is far more important than the whole checked/unchecked decision.

    Cedric appears to support checked, and Rod is a big supporter of unchecked (as am I). But note the following:

    <Cedric Beust>
    Obviously. You say that you were able to build reliable software based on unchecked exceptions. I have no problem believing that, but you need to keep in mind you (probably) achieved this using Spring, your own framework.

    In other words, you knew what methods were throwing unchecked exceptions, because you wrote that code.
    </Cedric Beust>

    I believe there must be a trust relationship with any underlying api you use. Even if the api uses checked exceptions, there is no guarentee that they are making all the exceptions you might want to catch checked. You must trust that they are using checked exceptions correctly and in every place you expect them. If they don't, you simply can't trust the compiler errors to tell you about checked exceptions that aren't being thrown. So assuming you are making that trust, why would you trust the code to declare a checked exception and not the documentation? I realize documentation is not always kept up to date, but by the same token someone could add a new exception and leave it unchecked because they don't want to do the extra work to change code if they make it checked. Trust or intimate knowledge of the underlying code is key regardless of which strategy you use. With a checked strategy you trust they will declare them. With unchecked you trust they will document them.

    With this in mind, it primarily comes down to personal style and application requirements. If you prefer checked use them, and if you preferred unchecked use those. Either way you need to use them properly, appropriately, and with care.
  77. It's all about style[ Go to top ]

    Trevor, you make good points. But let me point out the following, from the perspective of an API writer (or writer of any class or package which may be used by others): everytime you add in a checked exception to an API, you can be confident that users _know_ about it. Everytime you add in an unchecked exception, many people (myself included) get a slightly queasy feeling.

    From the perspective of a user of an API, everytime I see an API that relies exclusively on unchecked exceptions, my response is "oh, shit!". This interjection is forced from me because now I know I have to comb through the docs, and manually figure out which unchecked exceptions can reasonably happen, and which are indicators of programmer error/constraints violations, and when I'm all done with this I have no idea if I've missed anything.

    When I get an update of the library I have this same interjection forced from me for the same reason.

    The problem here is that using unchecked exclusively imparts _no_ useful information for users about exceptions. You can attempt to document the hell out of it, but people are invariably untrusting of documentation. And, when it comes down to it, I'm trusting the API developer's conventions and hoping he's presenting critical exceptions vs. true Runtime-like exceptions properly in his docs.

    As you point out, you can never _know_ if a libray might throw an unchecked exception. But this is a case not of absolutes, but of _levels_ of trust, and _levels_ of comfort. If someone shows me a decent checked handling hierarchy in her API, it gives me a relatively decent level of comfort, and some trust will ensue from that over time. If someone, on the other hand, shows me a relatively decent unchecked exception hierarchy in their API, my comfort level is going to decrease, because I know that I'm now relying on their coding conventions and discipline not to screw me up. It requires _considerable_ trust in this instance that the other guy is going to do the right thing, and communicate the right thing through extra-language means.

    Me, I'd prefer to trust the compiler over human good intentions and discipline.

        -Mike
  78. It's all about style[ Go to top ]

    Trevor:
    We are also saying that a meaningful exception hierarchy is far more important than the whole checked/unchecked decision.


    I think it's a dangerous way of proceeding. Choosing a hierarchy and picking the type (checked/unchecked) of the exceptions are two orthogonal decisions that should both be made after a careful analysis.

    Thinking "Alright, I have nice exception hierarchy, now I'll just pick a type by tossing a coin" is a recipe for disaster...


    I believe there must be a trust relationship with any underlying api you use.


    True, but in the case of checked exceptions, the compiler will make sure that nobody cheats on the contract.

    Personally, I love it when errors can be caught before I even get to run my code.


    Trust or intimate knowledge of the underlying code is key regardless of which strategy you use.


    I think this is a bit exaggerated: there is obviously a lot of reliable software making use of API's without any knowledge of the underlying code (WLS being a pretty obvious example :-)).

    Knowing the underlying code can certainly help you debug and diagnose problems and code faster in general, but it's by no means a sine qua non condition to produce reliable code.

    With a checked strategy you trust they will declare them. With unchecked you trust they will document them.


    I would phrase it differently:

    With checked exceptions, you trust they will
    - Declare them

    With unchecked exceptions, you trust they will
    - Declare them
    - Document them


    Either way you need to use them properly, appropriately, and with care.


    Definitely.

    --
    Cedric
  79. It's all about style[ Go to top ]

    <trevor>
    Trust or intimate knowledge of the underlying code is key regardless of which strategy you use.
    </trevor>
    <cedric>There is obviously a lot of reliable software making use of API's without any knowledge of the underlying code (WLS being a pretty obvious example :-)). </cedric>
    Trevor said trust or intimate knowledge of the code. In the case of WLS it's trust, that WLS implements the APIs and service contracts specified in the J2EE specs.

    Regards,
    Rod
  80. It's all about style[ Go to top ]

    |
    |In the case of WLS it's trust, that WLS implements the APIs and service
    |contracts specified in the J2EE specs.
    |

    But why "trust"?

    Do you think its possible to get burnt by some unexpected (non J2EE) Checked exception coming out of Weblogic?

    -Nick
  81. It's all about style[ Go to top ]

    <Cedric Beust>
    Thinking "Alright, I have nice exception hierarchy, now I'll just pick a type by tossing a coin" is a recipe for disaster...
    </Cedric Beust>

    I totally agree with this, and I hope my comments indicate that a well-thought out design is important. However, catching checked exceptions that CAN be recovered from in certain situations, but which are NOT recoverable in the context I'm working clutter my code. Inside my code/layer I mostly use checked exceptions, but I prefer not to have to deal with exceptions from other layers which are unrecoverable in the current context (or which will never occur outside of development - for example a static sql statement).

    <Cedric Beust>
    True, but in the case of checked exceptions, the compiler will make sure that nobody cheats on the contract.
    </Cedric Beust>

    I believe this misses one thing and that is that the compiler cannot make sure they don't cheat UNLESS they specify the checked exception. If somebody uses a checked exception strategy normally, but does not apply it across the board (or misses a specific spot), the compiler simply cannot assist you. This is the trust I'm referring to, not the compiler catching everything marked as checked (which it will) but the programmer declaring things checked which should be under a checked strategy.

    <Cedric Beust>
    With checked exceptions, you trust they will
    - Declare them

    With unchecked exceptions, you trust they will
    - Declare them
    - Document them
    </Cedric Beust>

    I also believe that documentation needs to be done properly in a checked strategy. If an exception isn't documented, how do you know what it means, what additional information it encapsulates, and under what conditions it will be thrown? I don't think you can ever get away from either trusting OR understanding the code AND documentation.
  82. It's all about style[ Go to top ]

    Some comments:

      - Some clutter is inevitable in code. I don't think it's a good yard stick for one approach vs. another, and in particular too many people go the unchecked route as a clutter-avoidance mechanism (when really what they're doing is avoiding exceptions!). I'm not saying you do this, but it's more common than it should be.

      - Most of programming isn't about absolutes, it's about techniques that bring you closer to your goals. Using checked exceptions in my own code, I find, makes it clearer to myself and others, and the compiler does catch a number of unintentional screwups.

      - I've observed that the more unchecked exceptions there are in an overall code base, the more likely it is that one or more exceptions are handled badly or not at all. The reason has nothing to do with design or knowing the code or anything like that, it has to do with human frailty. Being human, I'm going to miss some unchecked exceptions, and that's a fact. I may mishandle checked exceptions, but I can't miss them unless I code it that way.

      - Conclusion: the more unchecked exceptions I see in code, the queasier the feeling I get :-/

        -Mike
  83. One ques[ Go to top ]

    Mike

    small ques:

    <Mike>
    Conclusion: the more unchecked exceptions I see in code, the queasier the feeling I get
    </Mike>

    Are you suggesting unchecked exceptions have no place in professional coding?. If No at what situations you would recommend unchecked exceptions?
  84. One ques[ Go to top ]

    Well, as I said my own take isn't about absolutes, it's about getting closer to goals. In that vein I can't say that unchecked exceptions have no place in professional coding.

    Certainly, they make sense enforce the basic coding contract between an API and its users. If truly bad data is sent in, or an illegal pattern of method calls is made, it makes sense to throw an IllegalArgumentException or something similar which is unchecked. It doesn't make sense to make it a Checked exception, because it only happens on buggy code. To a large extent this is similar to assertions, at least conceptually. I'm also very grateful for language Runtime exceptions, such as the NullPointerException, because it's a pretty user friendly way to report a bug in your code, and certainly much easier to deal with then a core dump or GPF. But I don't like unchecked exceptions being used for resource failures or similar situations.

        -Mike
  85. Thanks[ Go to top ]

    Yes. Thanks :-).
  86. It's all about style[ Go to top ]

    Using checked exceptions in my own code, I find, makes it clearer to myself and others, and the compiler does catch a number of unintentional screwups.


    I agree that in 80% cases checked exceptions are great... the problem is with the remaining 20%. This is still a lot. Only searching google for "throws Exception" gives 100,000 results :-)

    http://www.google.com/search?hl=en&ie=UTF-8&oe=UTF-8&q=%22throws+Exception%22&btnG=Google+Search
  87. Nowhere?[ Go to top ]

    The client binaries should keep humming (running). But if one was to ever re-compile client code the compiler should do its job. This is what makes checked exceptions so wonderful.
    I know that. But it's not much good being unable to recompile my app, is it?

    A quick read of these 'nowhere threads' suggests you are in a vocal minority.
    A minority of posts, perhaps, but I don't think a minority of posters. Count the number of posts by each of the very vocal checked exception zealots.

    Regards,
    Rod
  88. <Mike>
    So my method here is tagged with IOException and ClassNotFoundException, and a
    a higher-level handler deals with ProtocolMismatchException, ClassNotFoundException, and IOExceptions differently (the former two send a message back down the wire saying either "you're using a bad protocol!" or "I don't know about the class of the object you've sent me", the latter results in a closed stream and an audit message being closed about the error).
    </Mike>

    Ok, let me now try to describe how this could work without checked exceptions. Without checked exceptions you would simply forget about handling ClassNotFoundExceptions and IOExceptions. Instead, at the place where you now handle these kinds of exceptions explicitly, you have something like this:

    try {
        mikesMethod()
    } catch (Exception e) {
        log exception and alert administrator
        send "Internal system error" message back to client
        close connection
    }

    Is this code more unreliable than your solution because it doesn't use checked exceptions?
  89. <quote>

    Ok, let me now try to describe how this could work without checked exceptions. Without checked exceptions you would simply forget about handling ClassNotFoundExceptions and IOExceptions. Instead, at the place where you now handle these kinds of exceptions explicitly, you have something like this:

    try {
        mikesMethod()
    } catch (Exception e) {
        log exception and alert administrator
        send "Internal system error" message back to client
        close connection
    }

    Is this code more unreliable than your solution because it doesn't use checked exceptions?

    </quote>

    Just as a matter of interest, what advantage do you see here using unchecked over checked exceptions. The code is identical whether the exceptions thrown by mikesMethod are checked or unchecked. So if you were writing mikesMethod, what would cause you to make the exceptions unchecked rather than checked in this particular example? I fail to see how your example given here can be taken as an argument either for or against unchecked exceptions. The one thing you do lose by the particular example you give is that the message returned to the client is a generic "something went wrong" message but that's not a result of the exceptions being checked or unchecked, it's simply because you don't distinguish between sub-types of Exception here.
  90. <David>
    Just as a matter of interest, what advantage do you see here using unchecked over checked exceptions. The code is identical whether the exceptions thrown by mikesMethod are checked or unchecked. So if you were writing mikesMethod, what would cause you to make the exceptions unchecked rather than checked in this particular example? I fail to see how your example given here can be taken as an argument either for or against unchecked exceptions.
    </David>

    People seem to agree that checked exceptions have drawbacks, if only that it forces you to write more code. Now, unless you don't agree with this, I think the discussion should be what benefits checked exceptions have over unchecked exceptions, not what benefits unchecked exceptions have over checked ones.

    That's why I have asked people in favour of checked exceptions to show me what advantage checked exceptions have over unchecked exceptions that justifies living with these drawbacks. I think that my code is as reliable as Mike's code except that I don't use checked exceptions. So, why would I use checked exceptions?

    <David>
    The one thing you do lose by the particular example you give is that the message returned to the client is a generic "something went wrong" message but that's not a result of the exceptions being checked or unchecked, it's simply because you don't distinguish between sub-types of Exception here.
    </David>

    Exactly. Thanks for pre-empting this one for me.
  91. <Quote>

    That's why I have asked people in favour of checked exceptions to show me what advantage checked exceptions have over unchecked exceptions that justifies living with these drawbacks. I think that my code is as reliable as Mike's code except that I don't use checked exceptions. So, why would I use checked exceptions?

    </Quote>

    I agree with you absolutely that you can write good code using unchecked exceptions, and you can write bad code using checked exceptions. At the end of the day it's the quality of the programmer that makes the difference.

    The examples you have given are all from the point of view of "I am writing some code using a class that throws an exception" and that is a valid point of view. But the other point of view is "I am writing some code that will be used by somebody else". The question is, what can I do when writing a class to help the unknown programmer who will be using my code in future?

    I guess I would argue that checked versus unchecked is a question of documentation, in a way. Whether the exceptions are checked or unchecked, people can still write what is IMHO rather doubtful code and just catch Exception without thinking about what kinds of exception might be thrown and whether the code should respond differently for different exceptions. But if the programmer is going to think about how to handle different types of exception, he needs to know what different kinds of exception are being thrown. Now, with unchecked exceptions, the programmer only has one way to find that out: he can read the documentation and hope that it's up to date and I have documented all the unchecked exceptions that might be thrown. And chances are that there will be some programmers who don't read the documentation but just use the Ctrl-space feature in their IDE to drop down a list of methods and say "I'll have that one". But if the exception is checked then whether the programmer reads the documentation or not, the compiler will pull him up and say, "This may throw such-and-such an exception, you need to do something about it". The programmer may choose to ignore it but that's his choice. At least when I wrote my code I gave him a heads-up to let him know in advance this error may be coming his way.
  92. <David>
    Just as a matter of interest, what advantage do you see here using unchecked over checked exceptions. The code is identical whether the exceptions thrown by mikesMethod are checked or unchecked. So if you were writing mikesMethod, what would cause you to make the exceptions unchecked rather than checked in this particular example? I fail to see how your example given here can be taken as an argument either for or against unchecked exceptions.
    </David>

    People seem to agree that checked exceptions have drawbacks, if only that it forces you to write more code. Now, unless you don't agree with this, I think the discussion should be what benefits checked exceptions have over unchecked exceptions, not what benefits unchecked exceptions have over checked ones.

    That's why I have asked people in favour of checked exceptions to show me what advantage checked exceptions have over unchecked exceptions that justifies living with these drawbacks. I think that my code is as reliable as Mike's code except that I don't use checked exceptions. So, why would I use checked exceptions?

    <David>
    The one thing you do lose by the particular example you give is that the message returned to the client is a generic "something went wrong" message but that's not a result of the exceptions being checked or unchecked, it's simply because you don't distinguish between sub-types of Exception here.
    </David>

    Exactly. Thanks for pre-empting this one for me.
  93. That's why I have asked people in favour of checked exceptions to show me what advantage checked exceptions have over unchecked exceptions that justifies living with these drawbacks. I think that my code is as reliable as Mike's code except that I don't use checked exceptions. So, why would I use checked exceptions?


    You definitely CAN write reliable code using only unchecked exceptions. As Mike stated, it's just harder to achieve the same level of reliability with such approach. Checked exceptions are just a reminder in the method contract that the risk of method call "blowing up" is significant and that the user must seriously think about how to handle such a case.
  94. <quote>
    You definitely CAN write reliable code using only unchecked exceptions. As Mike stated, it's just harder to achieve the same level of reliability with such approach.
    </quote>

    Is it? I have shown one way to code Mike's example code without using checked exceptions and I'm yet to be convinced that the unchecked version is less reliable than the checked version. No-one has commented on that particular code fragment sofar saying it is less reliable for this or that reason.
  95. \Pato Loco\
    Ok, let me now try to describe how this could work without checked exceptions. Without checked exceptions you would simply forget about handling ClassNotFoundExceptions and IOExceptions. Instead, at the place where you now handle these kinds of exceptions explicitly, you have something like this:

    try {
        mikesMethod()
    } catch (Exception e) {
        log exception and alert administrator
        send "Internal system error" message back to client
        close connection
    }

    Is this code more unreliable than your solution because it doesn't use checked exceptions?
    \Pato Loco\

    Yes - there are several problems with your counter example.

    First - how did you know to wrap mikesMethod() in a try...catch() block?

    Second - you're catching Exception (shudder). This means that all failures look the same to you.

    Third - you're missing the semantics here. A ClassNotFoundException should not result in a closed stream, just an error sent back down the stream. Some actions are log/close, others are not.

    Fourth - consider a case where a harried developer adds some code to another method - let's say it involves a JNDI lookup, and such look ups use unchecked exceptions in some alternate universe. He carefully goes around and changes all callers to do the right thing with possible JNDI exceptions - but misses one.
    Now you have a ticking time bomb in your source, because someone thought they were better than a compiler at tracking exceptions.

        -Mike
  96. \Pato Loco\

    > Ok, let me now try to describe how this could work without checked exceptions. Without checked exceptions you would simply forget about handling ClassNotFoundExceptions and IOExceptions. Instead, at the place where you now handle these kinds of exceptions explicitly, you have something like this:
    >
    > try {
    >     mikesMethod()
    > } catch (Exception e) {
    >     log exception and alert administrator
    >     send "Internal system error" message back to client
    >     close connection
    > }
    >
    > Is this code more unreliable than your solution because it doesn't use checked exceptions?
    > \Pato Loco\
    >
    > Yes - there are several problems with your counter example.
    >
    > First - how did you know to wrap mikesMethod() in a try...catch() block?

    OK, I wasn't clear enough. This try/catch block is what Anders Hejlsberg calls a bottom level exception handler. In the case of your application, I would put one of these bottom level exception handlers at the code that handles your network I/O. It would look something like this:

    Socket s = serverSocket.accept();
    try {
        InputStream is = s.getInputStream();
        OutputStream os = s.getOutputStream();
        try {
            processRequests(is, os);
        } catch (Exception e) {
            log exception
        }
    } finally {
        s.close();
    }

    In this example, processRequests() calls mikesMethod() somewhere which may throw ClassNotFoundException. But I don't care about that. I simply handle all exceptions so that my application gracefully recovers from any exception that may occur (i.e., there is no impact on parts of the application that were not involved with the activity that caused the exception).

    > Second - you're catching Exception (shudder). This means that all failures look the same to you.

    Yep, for a bottom level exception handler, all exceptions that reach it are internal server errors by definition.

    > Third - you're missing the semantics here. A ClassNotFoundException should not result in a closed stream, just an error sent back down the stream. Some actions are log/close, others are not.

    Yes, but this is just another requirement. There are probably 10s or 100s of other requirements that are not so lucky to get any support from the Java compiler. And the only way to check these is to test them.

    My point is that forgetting to check an exception does not need to affect the fundamental reliability of your application if you use bottom level exception handlers in the right places. I do agree that having checked exceptions can positively impact the reliability of your application somewhat if you do not thoroughly test your application.

    > Fourth - consider a case where a harried developer adds some code to another method - let's say it involves a JNDI lookup, and such look ups use unchecked exceptions in some alternate universe. He carefully goes around and changes all callers to do the right thing with possible JNDI exceptions - but misses one.

    No problem, the bottom level exception handler catches it and logs it. But if you don't mind, I would like to keep the discussion limited to the original code that you have shown. It is very hard to discuss this subject without concrete code samples.

    > Now you have a ticking time bomb in your source, because someone thought they were better than a compiler at tracking exceptions.

    A ticking time bomb? What's the worse thing that can happen? If you use bottom level exception handlers in the right places then maybe your GUI application will show you an error message, your transactional application will rollback the transaction, or the client's network connection gets closed. No other part of the application is affected. And all this happens only if something that shouldn't have happened occured.
  97. I won't critique your response in detail, because it's just worlds apart different from how I approach exceptions - it's so different it would take a small book to explain the differences. What you're doing is technically avoiding exceptions from propogating upwards to the top of the call stack. That's it - zero intelligence in actually responding to exceptions. In the sorts of applications I write, your approach would leave all sorts of things in inconsistent states.

        -Mike
  98. Checked exceptions are useful[ Go to top ]

    Checked exceptions are valuable to help enforce good programming practice in error checking. There is a good example in the Java API where an unchecked runtime exception can cause problems in web applications. When parsing a ServletRequest parameter which should be a number, there is nothing to stop the programmer from ignoring a NumberFormatException, which is an unchecked exception. A lot of websites fail to handle this, and it allows awkward error messages to arise in accessing webpages, such as "Internal Error". Similar problems can arise with text input to Java GUIs as well.
  99. <Mike>
    I won't critique your response in detail, because it's just worlds apart different from how I approach exceptions - it's so different it would take a small book to explain the differences. What you're doing is technically avoiding exceptions from propogating upwards to the top of the call stack. That's it - zero intelligence in actually responding to exceptions. In the sorts of applications I write, your approach would leave all sorts of things in inconsistent states.
    </Mike>

    Mike, I think you are completely misunderstanding what I am doing. Maybe the words bottom and top are confusing here. In my terminology, a call stack is a stack where you add and remove things from the top. Using this terminology, an exception does not propagate upwards on the call stack, but downwards. Hence the name 'bottom level exception handler'.

    It is true that I am avoiding exceptions from propagating all the way to the bottom (top in your terminology) of the call stack because that would crash my application. Instead, I am looking for places in my code a little higher in the call stack where I can put bottom level exception handlers so the exceptions occurring above it are contained within the context in which they occur and do not affect other, unrelated parts of my application. These bottom level exception handlers act kind of like firewalls. I indicated some typical places where to put them in my previous message.

    It is also true that I try not too worry too much about handling exceptions anyware above these bottom level exception handlers as they will be caught and handled by these bottom level exception handlers anyway. I just treat exceptions for what they are: things that should not happen. I try not to put a lot of effort in trying to recover from exceptions unless there is a clear requirement to do so.

    Leaving things in an inconsistent state has nothing to do with this approach. Unlike you, I use try/finally's everywhere. For example, I would never write something like this:

    ObjectInputStream ois = new ObjectInputStream(...);
    Object newObject = ois.readObject();
    ois.close();

    I would write this as:

    ObjectInputStream ois = new ObjectInputStream(...);
    try {
        Object newObject = ois.readObject();
    } finally {
        ois.close();
    }

    In fact, this is such an obvious and proven pattern for managing resources in the face of exceptions that I'm really surprised that you do not use it (at least not consistently).

    That is not the only code smell in your example code, BTW. This one also smells quite bad:

    while (len > numRead) {
        int readNow = in.read (rawBytes, numRead, len-numRead);
        numRead += readNow;
    }

    What happens if the message length sent by the client is wrong? What if the in.read() method reaches the end of file and returns -1 before the complete message is read? If I write network code, I diligently check all things that could go wrong and throw (unchecked) exceptions when they happen.

    I understand that you stripped some code from the example but if this is actual production code then I advise you to spend less effort on handling checked exceptions and more on writing actual robust code.
  100. \Pato Loco\
    Mike, I think you are completely misunderstanding what I am doing. Maybe the words bottom and top are confusing here. In my terminology, a call stack is a stack where you add and remove things from the top. Using this terminology, an exception does not propagate upwards on the call stack, but downwards. Hence the name 'bottom level exception handler'.
    \Pato Loco\

    That does confuse things - standard terminology is the reverse. Given a thread with a deep call stack, the "top" is traditional the Thread's run() method, the bottom is where you are in the call chain. The verbal description of top/bottom is the exact opposite of the Java stack backtrace.

    \Pato Loco\
    It is true that I am avoiding exceptions from propagating all the way to the bottom (top in your terminology) of the call stack because that would crash my application. Instead, I am looking for places in my code a little higher in the call stack where I can put bottom level exception handlers so the exceptions occurring above it are contained within the context in which they occur and do not affect other, unrelated parts of my application. These bottom level exception handlers act kind of like firewalls. I indicated some typical places where to put them in my previous message.
    \Pato Loco\

    I've found that where you put the handler is critical to getting the right handling mechanisms, and we probably agree on that. But your terminology is still driving me a bit nuts - you're saying "I am looking for places in my code a little higher in the call stack [meaning 'lower' in my sense] where I can put my bottom level exception handlers [meaning 'top' in my sense]". I'm sorry, but I'm confused - using your terminology, you're putting something termed "bottom level" higher up.

    \Pato Loco\
    It is also true that I try not too worry too much about handling exceptions anyware above these bottom level exception handlers as they will be caught and handled by these bottom level exception handlers anyway. I just treat exceptions for what they are: things that should not happen. I try not to put a lot of effort in trying to recover from exceptions unless there is a clear requirement to do so.
    \Pato Loco\

    I have a very different view of exceptions than you do. Exceptions are not things "that should not happen". Exceptions are rare, negative occurences that can happen, and which interrupt normal program flow. Having a disk write fail isn't something that "should not happen", it's something can happen (but hopefully rarely!) and which has a number of negative consequences - consequences which I have to deal with.

    Leaving things in an inconsistent state has nothing to do with this approach. Unlike you, I use try/finally's everywhere. For example, I would never write something like this:

    \Pato Loco\
    ObjectInputStream ois = new ObjectInputStream(...);
    Object newObject = ois.readObject();
    ois.close();

    I would write this as:

    ObjectInputStream ois = new ObjectInputStream(...);
    try {
        Object newObject = ois.readObject();
    } finally {
        ois.close();
    }
    \Pato Loco\

    The difference is programming-in-the-large vs. programming-in-the-small. I do not have every low-level piece of code have a finally block that deals with resource release. Instead, I have higher levels of code which do this on behalf of the lower levels (and the need to do so is communicated by exceptions). Further, I don't use exceptions to communicate all failures - for example, often I will catch a fatal exception on a connection, close it out at a higher level than the error, and then propogate a Disconnection event to interested parties.

    On a different level, you misread or misunderstood my code in the example you took. The original was:

            ObjectInputStream ois = new ObjectInputStream (new ByteArrayInputStream (rawBytes));
            Object newObject = ois.readObject();
            ois.close();

    Note that the ObjectIntputStream is reading from a ByteArrayInputStream, not a real stream connected to an external resource. The close() is actually superfluous since I chuck the whole thing away.

    \Pato Loco\
    In fact, this is such an obvious and proven pattern for managing resources in the face of exceptions that I'm really surprised that you do not use it (at least not consistently).
    \Pato Loco\

    It is not the responsibility of the code snippet I showed you to manage its resources. Its only responsibility is to encapsulate the protocol, get a message and turn it into an Object for return to the higher level. Resource management is taken care of at a higher (in my terminology), centralized level in the call chain.

    \Pato Loco\
    That is not the only code smell in your example code, BTW. This one also smells quite bad:

    while (len > numRead) {
        int readNow = in.read (rawBytes, numRead, len-numRead);
        numRead += readNow;
    }

    What happens if the message length sent by the client is wrong?
    \Pato Loco\

    Then the ObjectInputStream.readObject call will fail with an exception, or extra junk data will be written. In either case - how do you propose I validate a length?

    \Pato Loco\
     What if the in.read() method reaches the end of file and returns -1 before the complete message is read? If I write network code, I diligently check all things that could go wrong and throw (unchecked) exceptions when they happen.
    \Pato Loco\

    The actual code checks for this condition.

    \Pato Loco\
    I understand that you stripped some code from the example but if this is actual production code then I advise you to spend less effort on handling checked exceptions and more on writing actual robust code.
    \Pato Loco\

    It's not the actual production code, I pruned quite a bit primarily to make a point on exception handling. I actually find it amusing that you're pointing out "code smells" on a partial code snippet.

    Anyway, as I said in a previous message, it's obvious that we are worlds apart in many ways, and I don't have the energy to write a small book on the differences. It's obvious my own attempt at explaing my POV is being completely misunderstood by you (possibly it's my bad explanation, possibly because we really are that far apart in outlooks).

        -Mike
  101. <Mike>
    > \Pato Loco\
    > Mike, I think you are completely misunderstanding what I am doing. Maybe the words bottom and top are confusing here. In my terminology, a call stack is a stack where you add and remove things from the top. Using this terminology, an exception does not propagate upwards on the call stack, but downwards. Hence the name 'bottom level exception handler'.
    > \Pato Loco\
    >
    > That does confuse things - standard terminology is the reverse. Given a thread with a deep call stack, the "top" is traditional the Thread's run() method, the bottom is where you are in the call chain. The verbal description of top/bottom is the exact opposite of the Java stack backtrace.
    </Mike>

    Yes, I realized that and I apologize for the confusion. I copied the phrase 'bottom level exception handler' from the Anders Hejlsberg interview without realizing that this is called a 'top level exception handler' in Java. But now I come to think about it, 'top level exception handler' is also incorrect because my exception handlers are not at the absolute top of the call stack but a little bit lower. But OK, let's call them top level exception handlers.

    Anyway, my exception handling strategy is fundamentally the same as the one that Anders Hejlsberg describes in his interview.

    <interview>
    "[Bill Venners] .... isn't their code broken just by the fact that they didn't expect that exception when they wrote the code?

    [Anders Hejlsberg] No, because in a lot of cases, people don't care. They're not going to handle any of these exceptions. There's a bottom (top in Java, ed.) level exception handler around their message loop. That handler is just going to bring up a dialog that says what went wrong and continue. The programmers protect their code by writing try finally's everywhere, so they'll back out correctly if an exception occurs, but they're not actually interested in handling the exceptions."

    "[Bill Venners] So you think the more common case is that callers don't explicitly handle exceptions in deference to a general catch clause further up the call stack? (notice 'up' here, ed.)

    [Anders Hejlsberg] It is funny how people think that the important thing about exceptions is handling them. That is not the important thing about exceptions. In a well-written application there's a ratio of ten to one, in my opinion, of try finally to try catch. Or in C#, using statements, which are like try finally."
    </interview>

    If your exception handling/resource management strategy is fundamentally different than this one then maybe you should write a book about it, really.

    Anyway, the reason why I started this discussion is because proponents of checked exceptions are saying that my exception handling strategy leads to unreliable applications. I'm not convinced this is the case. If you put top level exception handlers in the right places then you have a fundamentally reliable application (as far as exception handling is concerned anyway).

    So what is a right place for a top level exception handler? Well, that depends on your application, but the general rule is that you put them there where you can confine the effect of the exception to the context within which it occurred.

    - If you are writing a GUI application, you can confine the effect of an exception to the event in which the exception occurred by putting a top level exception handler in you event loop. Other events are not affected.

    - If you are writing a transactional application, you can confine the effect of an exception to the transaction in which the exception occurred by putting a top level exception handler in the code that starts and commits/rolls back the transaction. Other transactions are not affected.

    - If you write a network server, you can confine the effect of an exception to the connection in which the exception occurred by putting a top level exception handler in the code that manages the connection (as I tried to show for your particular application). Other connections are not affected.

    <Mike>
    I've found that where you put the handler is critical to getting the right handling mechanisms, and we probably agree on that. But your terminology is still driving me a bit nuts - you're saying "I am looking for places in my code a little higher in the call stack [meaning 'lower' in my sense] where I can put my bottom level exception handlers [meaning 'top' in my sense]". I'm sorry, but I'm confused - using your terminology, you're putting something termed "bottom level" higher up.
    </Mike>

    Yes, we agree. I hope the above clears up the confusion.

    <Mike>
    I have a very different view of exceptions than you do. Exceptions are not things "that should not happen". Exceptions are rare, negative occurences that can happen, and which interrupt normal program flow. Having a disk write fail isn't something that "should not happen", it's something can happen (but hopefully rarely!) and which has a number of negative consequences - consequences which I have to deal with.
    </Mike>

    I agree completely. But how does this relate to checked exceptions vs. unchecked exceptions? My argument is that my exception handling strategy is fundamentally reliable even though I am not using checked exceptions. I catch exceptions, log them for the administrator, confine them to the context in which they occurred and use try/finally's to guarantee consistency.

    People in favour of checked exceptions say that my code is fundamentally unreliable because it doesn't use checked exceptions. You yourself were talking about time bombs. Where are the time bombs? As I said before, the worst thing that can happen is that my GUI application pops up a dialog, my transaction rolls back or that the client's network connection breaks.

    You say that your application has to handle disk write failure. How do you do that? What more can you do than log the fact that the disk write failed to notify the administrator, just like my generic, top level exception handler does?

    <Mike>
    > Leaving things in an inconsistent state has nothing to do with this approach. Unlike you, I use try/finally's everywhere. For example, I would never write something like this:
    >
    > \Pato Loco\
    > ObjectInputStream ois = new ObjectInputStream(...);
    > Object newObject = ois.readObject();
    > ois.close();
    >
    > I would write this as:
    >
    > ObjectInputStream ois = new ObjectInputStream(...);
    > try {
    >     Object newObject = ois.readObject();
    > } finally {
    >     ois.close();
    > }
    > \Pato Loco\
    > The difference is programming-in-the-large vs. programming-in-the-small. I do not have every low-level piece of code have a finally block that deals with resource release. Instead, I have higher levels of code which do this on behalf of the lower levels (and the need to do so is communicated by exceptions). Further, I don't use exceptions to communicate all failures - for example, often I will catch a fatal exception on a connection, close it out at a higher level than the error, and then propogate a Disconnection event to interested parties.
    </Mike>

    I cannot really comment on what you are doing put I think that the pattern:

    Resource r = acquireResource(...);
    try {
        use resource
    } finally {
        r.close();
    }

    is universally accepted in the Java world as an excellent way to manage resources, regardless of whether you are programming-in-the-large or programming-in-the-small.

    <Mike>
    > On a different level, you misread or misunderstood my code in the example you took. The original was:
    >
    >         ObjectInputStream ois = new ObjectInputStream (new ByteArrayInputStream (rawBytes));
    >         Object newObject = ois.readObject();
    >         ois.close();
    >
    > Note that the ObjectIntputStream is reading from a ByteArrayInputStream, not a real stream connected to an external resource. The close() is actually superfluous since I chuck the whole thing away.
    </Mike>

    Yep, I saw that. But I would still recommend to use try/finally or get rid of the close(), if only not to confuse the people who have to maintain your code.

    <Mike>
    > \Pato Loco\
    > In fact, this is such an obvious and proven pattern for managing resources in the face of exceptions that I'm really surprised that you do not use it (at least not consistently).
    > \Pato Loco\
    >
    > It is not the responsibility of the code snippet I showed you to manage its resources. Its only responsibility is to encapsulate the protocol, get a message and turn it into an Object for return to the higher level. Resource management is taken care of at a higher (in my terminology), centralized level in the call chain.
    </Mike>

    Again, it surprises me a a bit that you apparently do not the try/finally construct for this purpose, but that's OK.

    <Mike>
    > \Pato Loco\
    > That is not the only code smell in your example code, BTW. This one also smells quite bad:
    >
    > while (len > numRead) {
    >     int readNow = in.read (rawBytes, numRead, len-numRead);
    >     numRead += readNow;
    > }
    >
    > What happens if the message length sent by the client is wrong?
    > \Pato Loco\
    >
    > Then the ObjectInputStream.readObject call will fail with an exception, or extra junk data will be written. In either case - how do you propose I validate a length?
    </Mike>

    You can't. But the least you can do is to prevent your thread from waiting forever for data that is never going to arrive.

    <Mike>
    > \Pato Loco\
    >  What if the in.read() method reaches the end of file and returns -1 before the complete message is read? If I write network code, I diligently check all things that could go wrong and throw (unchecked) exceptions when they happen.
    > \Pato Loco\
    >
    > The actual code checks for this condition.
    </Mike>

    Good.

    <Mike>
    > \Pato Loco\
    > I understand that you stripped some code from the example but if this is actual production code then I advise you to spend less effort on handling checked exceptions and more on writing actual robust code.
    > \Pato Loco\
    >
    > It's not the actual production code, I pruned quite a bit primarily to make a point on exception handling. I actually find it amusing that you're pointing out "code smells" on a partial code snippet.
    </Mike>

    I apologize. The only defense for my remarks is that I asked to see a code fragment that showed where the use of checked exceptions was essential for the reliability of an application. In this context, I got presented a code fragment that was inherently unreliable and that person had just told me that I am a bad programmer ("the sorts of applications I write, your approach would leave all sorts of things in inconsistent states"), without any further explanation.
    I should have been a bit more diplomatic and not touch this subject at all. I apologize.

    <Mike>
    > Anyway, as I said in a previous message, it's obvious that we are worlds apart in many ways, and I don't have the energy to write a small book on the differences. It's obvious my own attempt at explaing my POV is being completely misunderstood by you (possibly it's my bad explanation, possibly because we really are that far apart in outlooks).
    </Mike>

    I don't know. All I know is that my exception handling strategy is a pretty common one and all I wanted to know is why people think that it is inherently unreliable because it doesn't use checked exceptions. Unfortunately, this thread has not produced a convincing answer.
  102. I don't know. All I know is that my exception handling strategy is a pretty common one and all I wanted to know is why people think that it is inherently unreliable because it doesn't use checked exceptions. Unfortunately, this thread has not produced a convincing answer.


    I think Mike produced a few convincing arguments, but you didn't really take them on board.

    Simply performing a blanket catch of Exception is almost never a good thing. It sounds to me like you just put this right at the very top, letting it catch everything you throw at it. This means that you cannot do anything meaningful with your exceptions - all exceptions to you are fatal errors, which should alert the administrator.

    Lets say I write a section of code to perform, say, login as a simple example. So I have an object, with a method

    login(String username, String password)

    Unbeknownst to you, this method throws three exceptions - UnknownUserException, InvalidPasswordException and AccountLockedException. All of these extend RuntimeException.

    None of these are fatal error conditions. All of them require specific handling. You may or may not want to obscure the first two conditions from the user (to hide the fact that someone trying to gain access has hit upon a correct username, but just hasn't got the password right yet). You may want to use a helpful method I've provided on InvalidPasswordException which indicates the number of retries before the account becomes locked. You *will* want to route the user to a separate part of the application if their account becomes locked, and probably notify the sysadmin.

    This *cannot* work with your strategy. You won't even know they're going to be thrown without looking at the documentation - and that's relying on me having kept it up to date (big mistake).

    If only I had made them checked exceptions... then within a couple of minutes you could have elegantly dealt with all of the possible exceptional (NOT error, NOT fatal) conditions within my login method.

    You will only find out all of the exceptions that can be thrown when you exhaust all of my possible failure conditions. What if the amount of retries I've specified before an account gets locked is undocumented? What if its 10? What if its 50? Did you anticipate any of that when you were writing your test cases? If not then my runtime exceptions will come back to bite you further down the line. Then you will have to redesign your application to take into account a condition you hadn't anticipated and I hadn't documented.

    I am all for top-level exception handlers by the way - but managed properly and dealing with specific cases meaningfully. I also use RuntimeExceptions extensively (I use the Spring Framework, and agree with a lot of what Rod Johnson has to say) but not exclusively. I think that they both have a very important place, and ignoring either of them is pretty much shooting yourself in the foot.
  103. I don't know. All I know is that my exception handling strategy is a pretty common one and all I wanted to know is why people think that it is inherently unreliable because it doesn't use checked exceptions. Unfortunately, this thread has not produced a convincing answer.

    >
    > I think Mike produced a few convincing arguments, but you didn't really take them on board.

    Well, keep in mind that I'm only focusing on the reliability argument made by people advocating checked exceptions. As I have stated numerous times now, my problem is with people that say that using an unchecked-exception only approach leads to inherently unreliable application code and I am not convinced by this.

    > Simply performing a blanket catch of Exception is almost never a good thing. It sounds to me like you just put this right at the very top, letting it catch everything you throw at it. This means that you cannot do anything meaningful with your exceptions - all exceptions to you are fatal errors, which should alert the administrator.

    I stated two times where I would put these top-level exception handlers and in neither of these two times did I say I would put them at the very top.

    These top level exception handlers do, indeed, nothing meaningful with the exception, except that they are treated as things that should not have occurred and alert the administrator. There's nothing fatal about these exceptions. As I have said before, they are confined to the context in which they occur and no other part of the application is affected.

    > Lets say I write a section of code to perform, say, login as a simple example. So I have an object, with a method
    >
    > login(String username, String password)
    >
    > Unbeknownst to you, this method throws three exceptions - UnknownUserException, InvalidPasswordException and AccountLockedException. All of these extend RuntimeException.
    > None of these are fatal error conditions. All of them require specific handling. You may or may not want to obscure the first two conditions from the user (to hide the fact that someone trying to gain access has hit upon a correct username, but just hasn't got the password right yet). You may want to use a helpful method I've provided on InvalidPasswordException which indicates the number of retries before the account becomes locked. You *will* want to route the user to a separate part of the application if their account becomes locked, and probably notify the sysadmin.
    >
    > This *cannot* work with your strategy. You won't even know they're going to be thrown without looking at the documentation - and that's relying on me having kept it up to date (big mistake).

    That's funny. In my world, an API is as good as it's documentation. You are really contradicting yourself here. First you say that I might "want to use a helpful method that you've provided on InvalidPasswordException which indicates the number of retries before the account becomes locked". Now how would I know about this method and what it does other than to read your documentation? And then you say it is a big bistake for me to rely on your documentation to be up to date?

    I also completely fail to see how I can write a reliable application using a poorly documented API.

    > If only I had made them checked exceptions... then within a couple of minutes you could have elegantly dealt with all of the possible exceptional (NOT error, NOT fatal) conditions within my login method.

    Oh, I completely agree. I would probably define them as checked exceptions as well. But I'm not convinced that this makes such a big difference in the fundamental reliability of my application (as was my original point).

    > You will only find out all of the exceptions that can be thrown when you exhaust all of my possible failure conditions. What if the amount of retries I've specified before an account gets locked is undocumented? What if its 10? What if its 50? Did you anticipate any of that when you were writing your test cases? If not then my runtime exceptions will come back to bite you further down the line. Then you will have to redesign your application to take into account a condition you hadn't anticipated and I hadn't documented.

    That's funny as well. What you are saying is that because AccountLockedException is a checked exception, a programmer gets reminded to write some code to handle the AccountLockedException, which is all well and good. But then you say that it is very likely that this exception handler will not get tested before it goes into production anyway so how does this add to the reliability of my application?

    > I am all for top-level exception handlers by the way - but managed properly and dealing with specific cases meaningfully. I also use RuntimeExceptions extensively (I use the Spring Framework, and agree with a lot of what Rod Johnson has to say) but not exclusively. I think that they both have a very important place, and ignoring either of them is pretty much shooting yourself in the foot.

    You know what? I completely agree with you and Rod Johnson. On the one side, I think that checked exceptions are overused in Java (IOException, RemoteException, SQLException, etc.), but on the other side I think there is a good use for checked exceptions in some cases (such as the one you described).

    What I don't agree with is the argument that checked exceptions are vital for writing reliable applications. What is much more important for writing reliable applications is:

    1. You only use quality APIs and a poorly documented API is not a quality API.

    2. You don't assume that something is working unless it has been tested.

    In fact, if the usage of checked exceptions causes APIs to get poorly documented or application code not to get tested then checked exceptions do more harm than good. I'm not saying this is the case, but the more I hear arguments such as yours, the more I start to worry.
  104. Well, keep in mind that I'm only focusing on the reliability argument made by people advocating checked exceptions. As I have stated numerous times now, my problem is with people that say that using an unchecked-exception only approach leads to inherently unreliable application code and I am not convinced by this.


    A well-designed exception heirarchy *can* work perfectly well whether the exceptions are checked or unchecked, particularily in high-level application code. If you are developing an API that will be reused by other components, you should make its boundary as clear as possible to prevent errors and poor usage. Anything that reduces the likelihood of errors *must* be making your application more robust. And this is my argument - by declaring checked exceptions appropriately, you force calling code to acknowledge that they exist and to deal with them appropriately. In my opinion (and this is only my opinion) this makes that interface clearer in that I *have* to consider these exceptional conditions as valid code paths.

    > That's funny. In my world, an API is as good as it's documentation.

    That's a blanket statement. There are plenty of API's that are elegant, well designed, robust, and yet don't have a verbose comment on every single method. But, we're not discussing documentation or coding standards here - we're discussing checked and unchecked exceptions.

    > You are really contradicting yourself here. First you say that I might "want to use a helpful method that you've provided on InvalidPasswordException which indicates the number of retries before the account becomes locked". Now how would I know about this method and what it does other than to read your documentation? And then you say it is a big bistake for me to rely on your documentation to be up to date?
    >

    Not at all.

    Firstly, you don't need javadocs to see that a method exists.

    Secondly, you don't need even well written javadocs to tell you that a method exists. Even basic javadocs, with no comments will tell you that.

    Thirdly, I am human, and as such I make mistakes. It is entirely possible that my login method is on the face of it well documented. I could describe, in detail, the intricacies of the login procedure. I could even helpfully mention the UnknownUserException and InvalidPasswordException that are thrown within the body of the method. However, even after all of this, I could neglect to mention the UnknownUserException (Perhaps it is thrown by another API I am using). In fact this is worse - you would be convinced by my extensive documentation that everything was covered, when it was not.

    But again, documentation is a separate concern from exception handling - I am merely pointing out that a reliance on complete documentation is fundamentally less safe than a reliance on compile-time checking. Exceptions are part of the contract between an API and the code which is calling it. There is *no* contract between the calling code and the API's documentation. If my API can, in the general run of things, throw an exception that is not necessarily fatal and requires calling code to at least judge whether or not its worth dealing with, then I will make that exception checked. Not doing so makes my interface less explicit, and therefore more error prone.

    > That's funny as well. What you are saying is that because AccountLockedException is a checked exception, a programmer gets reminded to write some code to handle the AccountLockedException,

    Throwing AccountLockedException is a perfectly valid, and probably common, codepath for my API, and its a path that you need to consider when designing your application.

    > which is all well and good. But then you say that it is very likely that this exception handler will not get tested before it goes into production anyway so how does this add to the reliability of my application?
    >

    I say nothing of the sort - to what are you referring? I do point out that the fact that since I indicate up front a possible exceptional condition as part of my API contract, its easier to write a test case for it. Its harder to write a test case for a situation you have not considered and don't even know exists. That is one way it improves the reliability of your code - by ensuring that you fully consider the exceptional cases that are a part of that API's contract.


    > You know what? I completely agree with you and Rod Johnson. On the one side, I think that checked exceptions are overused in Java (IOException, RemoteException, SQLException, etc.), but on the other side I think there is a good use for checked exceptions in some cases (such as the one you described).
    >
    > What I don't agree with is the argument that checked exceptions are vital for writing reliable applications.


    Of course they're not vital. Given complete knowledge of an application, inside and out, and perfect documentation, you can exclusively use RuntimeExceptions. But for APIs and components that are black boxes, I expect clear and unequivocal interfaces backed up by as much compile time safety as possible - is that so unreasonable?


    > What is much more important for writing reliable applications is:
    >
    > 1. You only use quality APIs and a poorly documented API is not a quality API.
    >
    > 2. You don't assume that something is working unless it has been tested.
    >

    This is irrelevant to this argument. We are not deciding in general what factors affect a robust application, we are specifically trying to determine what reasons a developer might have for choosing checked exceptions over unchecked exceptions for providing a robust API.

    > In fact, if the usage of checked exceptions causes APIs to get poorly documented or application code not to get tested then checked exceptions do more harm than good. I'm not saying this is the case, but the more I hear arguments such as yours, the more I start to worry.

    This is a bit of a straw man. Exceptions of any kind are a tool for building better and more robust software, and your strategy for using them affects the end result. To say that checked Exceptions can lead to bad documentation is ridiculous.

    Poor documentation and bad testing will likely cripple any product, no matter what exception handling strategy is used - as will incompetent developers, bad requirements, bankruptcy etc. etc. However, the more I hear arguments in favour of unchecked Exceptions such as 'its less code' backed with assurances that 'of course they will be fully documented' the more *I* start to worry.
  105. Just to wrap up the comments/questions on the code snippet - in request/reply scenarios it's common to use the idiom:

      // Acquire resource
      try {
       // use resource
      } finally {
        // release resource
      }

    What's easy to forget is that all the world is not request/reply - there's still cases where long-lived connections are required, and where resources outlive the scope of a single request. This is the domain my code falls into - a long-lived connection used between a client and server which are talking to each other asynchronously.

    The very low-level code (say, the bottom two calls in the call stack) is re-usable in many contexts (in fact, it's part of the library). As such, the code is too low-level to know how to respond to errors. This is left up to the caller, and is documented through checked exceptions as well as regular old documentation.

    I didn't post the full code, both to avoid confusion from details not relevant to the conversation, and 'cuz my company rather frowns upon posting our code on the Internet. However, in the actual code SO_TIMEOUT is set and InterruptedIOException is dealt with - yet another Exception that needs to be dealt with specially, and one that implies re-tryable requests. This is part of a larger framework which does connection timeouts and needs asynchronous closability of a socket from another thread, even if another thread is blocked on a read.

    Where checked exceptions come in is forcibly communicating to the user what exceptions they are expected to handle in a fashion that will cause a compiler error if they blatantly or accidentally ignore it. The difference in your approach is you somehow appear to divine what code can call exceptions - how you do that reliably is a mystery to me. You also tend to deal just with Exception, meaning that you can't have any specific handling behavior, and by catching exception you mask in your own code any changes in lower-level code that may have new exceptions added into it.

        -Mike
  106. Ok, let me now try to describe how this could work without checked exceptions. Without checked exceptions you would simply forget about handling ClassNotFoundExceptions and IOExceptions. Instead, at the place where you now handle these kinds of exceptions explicitly, you have something like this:

    >
    > try {
    > mikesMethod()
    > } catch (Exception e) {
    > log exception and alert administrator
    > send "Internal system error" message back to client
    > close connection
    > }
    >
    > Is this code more unreliable than your solution because it doesn't use checked exceptions?

    That depends on whether you have thought about and designed around *all* the run-time faults that are hidden within the scope of an "Exception". Don't forget to include all those that might be thrown by mikesMethod and by amitsMethod (which is invoked by mikesMethod) and by ivansMethod (invoked by amitsMethod) all of which were written 5 years ago by people in different companies. Yes, I realise that some argue this represents a scalability issue, but I'd rather spend 2 minutes coding to deal with exceptions than 2 hours on the phone to a poor field service engineer that is having chairs thrown at him by the customer because the customer is losing money while the fault is being resolved (no joke, unfortunately).

    Checked exceptions force you to explicitly state what you will do in the case of run-time errors; you can't invisibly forget to consider failure modes.

    I don't believe that code reviews are a sufficient answer (although code reviews are necessary). One of the hardware engineers' maxims that software engineers' ought to learn is that "it is not possible to inspect quality into a product after it has been implemented".
  107. Bad examples[ Go to top ]

    File f = new File(...);

    > if (f.exists()) {
    >     FileInputStream fis = new FileInputStream(f);
    > } else {
    >     ....
    > }
    >
    > This code forces met to handle FileNotFoundException although I know this will never happen.

    There is a time interval, however small, between f.exists() and "new FileInputStream(f)". Assuming f.exists() is invariant between those two API calls is incorrect I believe.
     
    > Another example:
    >
    > byte[] bytes = ...;
    > String s = new String(bytes, "UTF-8");
    > This code forces me to handle an UnsupportedEncodingException although I know this will never happen.

    Consider that only six charsets are required to be supported by a Java 1.4.2 VM -- you have chosen one of those six. If you were requesting a non-standard character set, which is entirely possible with that API specification, then it is good practice in my opinion for the API writer to have tapped you on the shoulder and insisted you consider whether the character set you are requesting is provided by the target VM.

    Which would you prefer -- 1) a different constructor call for using "guaranteed to be available charsets" (minus the checked exceptions), or 2) no checked exceptions ?

    Option #2 puts everyone back on an honor system for considering the possibility of a well-know failure condition.

    > One more (and then I'll stop):
    >
    > Class cls = Class.forName("java.lang.String");
    >
    > This code forces me to handle ClassNotFoundException although I know this will never happen.

    Um ... is "Class cls = java.lang.String.class" out of the question?

    Surely there are some better examples than these of your argument. These seem pretty contrived and weak.
  108. These examples are not too good[ Go to top ]

    File f = new File(...);

    > if (f.exists()) {
    > FileInputStream fis = new FileInputStream(f);
    > } else {
    > ....
    > }

    Why do you check for file existence this way - it mat lead to inconsistency (when eg. the parallel thread deletes a file between f.exists and new FileInputStream().
    And you may also face the problem of limited number of file handles in some operating system in new FileInputStream() for example - you never know. Your API may be used by someone to do parallely tens of thousands operations on files.
    So, It is much better in this case:
      try {
        FileInputStream fis = new FileInputStream(f);
       } catch (FileNotFoundException fnfe) {
         // something soft, eg. different action
       } catch (IOException ioe) {
         // this is fatal!!!
       }

    > byte[] bytes = ...;
    > String s = new String(bytes, "UTF-8");

    Better example. But you may encapsulate this is one method:
      String s = StringUtil.fromUTF8(bytes);
    once and forever - it is reusable. And not a big effort.

    > Class cls = Class.forName("java.lang.String");

    Not much sense:
      Class cls = java.lang.String.class;
    forName has sense mainly when you do not know the class name in advance (but eg. read it from property file). And in this case you may never assume that the class exists (mistyping in property file).

    Best regards,
    Piotr
  109. These examples are not too good[ Go to top ]

    Ben and Pjotr,

    I'm interested in your opinions. Would you say that there are any drawbacks to using checked exceptions?

    I think that most people agree that there are some drawbacks to using checked exceptions, if only that it requires you to write more code (and more code generally means more bugs, higher maintenance cost, etc). People in favour of checked exceptions say that these drawbacks are outweighed by the benefits of checked exceptions. They often cite higher reliability when using checked exceptions as the major benefit.

    What I would like to find out is if this is indeed the case: do checked exceptions increase the reliability of an application? That's why I'm interested to see actual code that proves that checked exceptions make applications inherently more reliable than applications that use only unchecked exceptions and handle them using top-level try/catch blocks. Can you show me?
  110. Pato Loco - it's not a question of absolutes, which is how you've framed your response. It's a question of making your application 100% bulletproof. It's a question of "what techniques are likely to _increase_ your robustness?". There's a difference between trying to increase your impact somewhere and actually achieving it 100%.

    >
    > Checked exceptions are a tool that's designed to increase the likelihood that something will be handled correctly. It's not a substitute for anything - instead, it's one more piece of the puzzle that can help you make your code better.
    >
    > And as I said in another post, you can pay the man now or pay more later. In the long haul, I've found checked exceptions decrease the overall development and maintenance times for large projects - I pay the hit up front to get corrections right, to communicate them forcibly through Checked exceptions, and having to deal with a compiler complaining about my mistakes. That hit is small in comparison to paying for it later, or trying to do manually what checked exceptions does automatically.
    >
    >     -Mike



    Mike, I would like to tell you I agree with everything you said in this thread on the checked exceptions issue :)
  111. I recently wrote some encryption code. I had to deal with 6 different possible exceptions being thrown from 1 method that I wrote which did the encryption. That is crazy. It makes fast development, propotyping etc. a real pain. What happens a lot of time is developers instead catch Exception and bury the exception.

    >

    I will second it. Checked exceptions maybe a better fit for a waterfall development when you know everything upfront how and where to process the exceptions but not so good for incremental development. Ideally it is great to have compiler to check for exceptions but the current remedy might be worse than the disease. Tools like lint could be a better solution to identify exceptions that are not handled. It should not be a compile time error maybe a warning. All latest API use unchecked exceptions whenever possible, i even saw publications that show how to wrap checked exceptions into unchecked ones and re-throw.

    should exceptions be part of the regular business logic? Checked exceptions could be appropriate for rather rigid framework to determine how the caller must react, but there are other ways to do it, callbacks come to mind for example. And code readability should be considered too.

    oleg
  112. \oleg shteynbuk\
    I will second it. Checked exceptions maybe a better fit for a waterfall development when you know everything upfront how and where to process the exceptions but not so good for incremental development
    \oleg shtenynbuk\

    I've always hated waterfall development, and my own development work for the past several years have been strictly incremental based. And I use checked exceptions.

    For me, I prefer strong API models, even when developing incrementally, which tell me alot about the mental model I should have the API. And alot of development work centers around starting out with a fairly weak API model and slowly tightening it up and strengthening it over time. Does this slow down my development? Yes, somewhat. But the Man always has to be paid eventually - the question is do you pay it now, or do you pay it later when it's more painful?

    People who eschew checking, and prefer lint-like "hints" over language enforced capabilities, IMHO are kidding themselves. They claim their unit tests and discipline and other practices shield them from problems of dynamic languages and things like unchecked exceptions - but, as I said, the Man always has to be paid. Those who choose unchecked exceptions take on extra work to manually check everywhere that they are catching the right exceptions in the right place, and need to dig extra hard into documentation to find what exceptions may be in play, and occasionally they will hit a deadline and just say "screw exceptions, just ship it". They're paying a price over their development lifetime that I prefer to take up-front. And if strengthing my models over time means some extra re-factoring pain to handle additional checked exceptions as the model evolves, so be it - it's still taking what I call "the correctness hit" as early in the process as is sensible. People who don't work this way are, as a rule, those who whistle past cemetaries, tend to despise error handling and put it off as far into the future as possible (or dispose of it altogether), or who deceive themselves in believing that their hand-written unit tests are as good as a compiler (and that they always, always ensure their unit tests are accurate and up to date).

    \Oleg Shteynbuk\
    It should not be a compile time error maybe a warning. All latest API use unchecked exceptions whenever possible, i even saw publications that show how to wrap checked exceptions into unchecked ones and re-throw.
    \Oleg Shtenybuk\

    All the latest APIs do XYZ right now. 2 years from now, the consultants of the world will decide they've saturated that idea, move onto something new, and suddenly all new APIs will instead do LMN at that point.

    Keep in mind - many people doing publishing these days are in fact salesmen who are selling something. And these salesmen change their stripes every 2-5 years so they have something "current" to sell. If you'd like to research it, do some research on Usenet over time from the 80's to now for some of the older consultant's and article writers' favorite cause-du-jour. You'll find that many of them have not only changed striped often, but have flip-flopped back and forth on the same fundamental issues time and time again.

    Some advice and opinions, on the web and elsewhere, are opinions that have been formed by years of experience and a consistent attempt at achieving intellectual growth. Many other opinions, in contrast, are offered strictly in a calculated way for someone to differentiate themselves from the pack, get noticed, and make a pile of money consulting.

        -Mike
  113. \ Mike Spille \
     But the Man always has to be paid eventually - the question is do you pay it now, or do you pay it later when it's more painful?
    \ Mike Spille \


    This argument is not very convincing, in most cases; too general and could be applied to just anything, the real question is the amount that you need to pay and the same amount today could actually be much costlier than say half a year later. if you are into incremental development that assumed that you do not know for sure how the final system will look otherwise you will do waterfall development. And if you take into account 20-80 rule, it might well be that you are putting quite a lot of effort into 20% of code that actually does not matter too much, then what is the point in the upfront payment, and all really important exceptions will get handled anyhow. Just for the record I thought differently not so long ago, does it put me into salesman category :)
    software development is a very dynamic field and if you learn a better way of doing things nothing wrong in using it, even if you need to adjust your position. Programming is all about tradeoffs and in some situations compiler checking is very important and in others dynamic approach is better. On this issue I am probably in Bruce Eckel camp.


    \ Mike Spille \
    > Some advice and opinions, on the web and elsewhere, are opinions that have been formed by years of experience and a consistent attempt at achieving intellectual growth. Many other opinions, in contrast, are offered strictly in a calculated way for someone to differentiate themselves from the pack, get noticed, and make a pile of money consulting.
    \ Mike Spille \

    It is true but probably it is possible to figure it out if you put some effort, so I will not worry about it.

    oleg
  114. \oleg shteynbuk\
    This argument is not very convincing, in most cases; too general and could be applied to just anything, the real question is the amount that you need to pay and the same amount today could actually be much costlier than say half a year later. if you are into incremental development that assumed that you do not know for sure how the final system will look otherwise you will do waterfall development. And if you take into account 20-80 rule, it might well be that you are putting quite a lot of effort into 20% of code that actually does not matter too much, then what is the point in the upfront payment, and all really important exceptions will get handled anyhow. Just for the record I thought differently not so long ago, does it put me into salesman category :)
    \oleg shteynbuk\

    The lynchpin to your own argument is that using checked exceptions somehow incurs "quite a lot of effort". It requires some effort, but it's generally measured in minutes, not in hours or days. As I mentioned before, I do incremental development as a rule, and the impact of using checked exceptions isn't significant to our development timelines. It's there, but it's not a deciding factor.

    As for the "when do you pay" rule, I find that it's a _very_ convincing argument when applied to software development, and specifically to a discussion over checked exceptions vs. unchecked. People who advocate unchecked exceptions want to go faster now, and are irked by compiler warnings about checked exceptions not being caught, and apparently do not have the time to work out a meaningful exception checked hierarchy that can be applied in proper contexts. But the fact that they're irked by such problems, and don't have the time or motivation to deal with exceptions comprehensively, do _not_ remove the need to deal with them. It just pushes it off dealing with into the future, as your operations staff slowly finds whacked-out servers and the development staff slowly adds in proper exception handling for all that unchecked stuff.

    It also happens that I am someone who is on-the-hook for operations support in my company, and also on the hook for problems that happen that could/should have been handled by the software (and I've been in this role before). I've observed that a number of unchecked-exception fans (not all, but many of them) often never get near any operations/production centers. To them most error checking is useless, because _they_ aren't the ones who get called when there's a problem. In the development environment, where few failure scenarios are conducted, the top-level catch-all block is sufficient for their needs. In fact, I've seen new Java systems thrown _out_ of production because they didn't properly handle exceptions.

        -Mike