I'm looking forward to what you write, but I think overall we need to balance between: (i) having a system that's easy to implement that does the right thing almost all of the time, or (ii) having a system that's hard to implement that would do the right thing all the time but that practically screws up more than option (i) because people keep dropping parts on the floor.
]]>But thank you. Between your post, it's comments, and comments on YCombinator, I must post myself on how to deal with exceptions properly: Without loosing original trace paths, without cluttering the throws clause, and without creating non-deterministic code from finally clauses.
]]>Exceptions are a language feature and should be used whenever they are linguistically convenient; i.e., wherever they result in cleaner, more robust code than if you had used a different construct. In many cases they're very convenient for error handling. Occasionally they're useful for (hopefully clearly documented) flow control. You only reason to worry about how common a case is is when you're trying to figure out if throwing and catching exceptions will cause performance problems.
]]>The (approximate) exception handling model used in Java is widespread in mainstream languages (C#, Python, PHP) and is also seen in emerging languages such as Scala, oCaml, and F#. Restartable conditions, as seen in some Lisp implementations, have advantages, but one has to weigh them against the advantages of today's mainstream and emerging languages — plus the switching cost. For instance, you could make a case that Python and Ruby are better than PHP (say 20%) but I'd need a language that would be much better than PHP to be worth the considerable cost involved in switching.
]]>That sounds like a social issue, not a technical one. There will always exist social problems that cannot be solved by technical solutions. Even if you didn't have to declare any exceptions, the correct fix at one level might involve changing interfaces at other levels.
And while I agree checked exceptions cause far more trouble than they're worth, isn't that a drop in the bucket compared to Java's lack of support for restartable conditions? You can say 2 words ("throws Exception") per method to basically escape the checked exception system, but if you want to fake restartable conditions it takes a ton of code every time (which Java doesn't offer the power to abstract). Whenever I've worked on large Java programs, "throw" hurts me far more than "throws".
]]>But, even so, you should pretty much never catch "Exception."
I'm not a C# programmer, but in Java you seem to think that checked exceptions are all that exist. There are runtime exceptions, and runtime exceptions do not need to be caught. IllegalArgumentException in Java is in fact a runtime exception. Runtime exceptions represent programming errors, not special conditions to be checked for. If you called the method incorrectly it's *your* fault not the users fault.
A SQLException is a special condition that can be checked for (it happens often enough that the DB just aint there) … and so Exceptions like SQLException must be specifically caught or rethrown to the calling code. The system shouldn't crash because the DB wasn't there. If you catch your SQLException with "catch ( Exception sqle)" … then you risk catching runtime exceptions that should not be caught there.
Exceptions that typically get thrown inherit from other exceptions. There could be a hundred sub-exceptions of illegal argument exceptions that could be thrown in Java (and a method signature might easily declare 5 of them), but I can easily enough catch all of them with one "catch(IllegalArgumentException ile)" line. I don't *have* to break it all up into each and every possible subclass.
]]>