Hacker News new | past | comments | ask | show | jobs | submit login

> checked exceptions fundamentally violate interface encapsulation

You have that backwards. Unchecked exceptions will blithely and without warning completely explode your stack. They're the Atomic Goto.

The only way to know whether you're going to get one is to check the documentation, where you can only hope that the API author -- and the author of every API he calls -- has actually documented the exceptions that get thrown, because the compiler will be no help whatsoever, and god forbid an API start throwing an exception later.

> ... try throwing a meaningful exception through Runnable or Iterator.

If you pass around an object that conforms to Iterator, but throw an exception within it, __YOU'RE BREAKING THE API CONTRACT.__

Anyone that relies on the API contract of the Iterator class could have their state completely walloped by the Atomic Goto you inserted with a runtime exception.

> Stop it. JUST STOP IT. Checked exceptions have wasted hundreds of hours of my time, not just writing lame wrappers so that I don't have to type try/catch on every line of code, but also by making debugging and error handling five times more painful than it should be.

This makes no sense, because more work is required without checked exceptions.

Without checked exceptions:

- You must check the API docs for every line of code you write to see if it will throw an exception, and if so, what types.

- If it throws an exception, you must either add a try/catch block to handle the error appropriately (or wrap it in a new exception type), or you must add documentation to your method to declare that it will bubble up an exception, and of what type.

- If new exception types are thrown by underlying code, nothing tells you until your application explodes.

With checked exceptions:

- The compiler tells you what exceptions code throws, and of what type.

- If it throws an exception, you must either add a try/catch block to handle the error appropriately, or declare it in the method prototype. The IDE will do both of these things for you.

- If new exception types are thrown by underlying code, the compiler will warn you.

> If you're still touting checked exceptions in 2013, you are part of the problem. Stop it. Java needs to evolve, and your fresh-from-1995 opinion is not helping.

Stop advocating broken API design and ignorance of API invariants.




I will try to follow the HN ethos and give you the benefit of all the doubt I can. I have to admit, as someone who has been working with this language since the beginning, it's a deeply frustrating struggle. This debate is a microcosm of exactly what went wrong with Java, and why "kids these days" are abandoning it in droves. Have you noticed that all the post-Java languages, from C# to Ceylon, abandon this misfeature?

Point by point:

Unchecked exceptions will blithely and without warning completely explode your stack.

No. They rewind back to the level at which you catch the appropriate exception - possibly Exception. It's true that you aren't always able to catch each exception as specifically as you want. But at least you have a hope of doing that instead of catching RuntimeException and searching back through a dozen nested exceptions, which is today's reality.

In actual practice, there's usually a place you can (and should) catch Exception so that you can log and either retry or abandon the unit of work. In the context of a web server, this is usually "one request". That's why your appserver doesn't crash when something goes wrong.

This isn't theory, your appserver already does this, and it's a wonderful thing. Try doing some node.js programming sometime for a taste of what it's like without that.

Your mistake is believing that there is an alternative to RuntimeException. There is not.

If you pass around an object that conforms to Iterator, but throw an exception within it, __YOU'RE BREAKING THE API CONTRACT.__

Again, your mistake is believing there is an alternative. With the exception of very simple classes, all code has exceptional conditions. Do you create DatabaseIterator which throws DatabaseException (and NetworkException) every time you want to iterate a result set? Then you can't use it with Guava or any of the other 10 million Java libraries that consume standard interfaces, and you might as well not have interfaces at all.

Only pedants care if the compiler checks every single exception. Real-world programmers expect that code will complete normally, and catch exceptions at a high enough level that they can do something useful about it (eg, retry or return an error code to the client).

Exceptional conditions cannot be part of the API contract, because every body of code has different exceptional conditions, and if you try to account for them, you have one of two results:

* You give up on standard interfaces completely. You have DatabaseIterator (which doesn't extend Iterator), FileIterator (which doesn't extend Iterator), etc.

or:

* You throw IteratorException from each method. This is what the Java SDK ends up doing in various places (eg, InvocationTargetException) which is just plain retarded. It would make more sense (and be less annoying) to just throw Exception and leave off the wrapper exception.

You must check the API docs for every line of code you write

Sorry, you are not excused from this, ever. At least with exceptions, you have the option of ignoring the problem at deep levels and catching them higher up - which you already have to do anyways, because nobody wants their app to crash at the first exception. In webapps or appservers it's at the request level; in GUI apps it's usually the UI event handler.

With checked exceptions:

No, the compiler doesn't do any of that shit. Because in the Real World, you end up passing data through a standard interface and the exception gets wrapped. Don't believe me? When was the last time you saw a stacktrace that wasn't wrapped with several Caused by clauses? With the exception of remote API calls (where the exception class may not exist on the client), Caused by: is a fundamental failure of language design. There's no sane reason for this construct to exist. Try writing code in other languages and feel how refreshing it is to get clean stacktraces. You don't even have to leave the JVM, you just have to use any of the languages designed since 1995.


I am having a lot of trouble giving you the benefit of the doubt, since what you seem to be arguing for is leaving API contracts completely ambiguously defined because it's too much effort for you to do otherwise. You're not arguing for correctness, or for reliability, but rather for your own convenience in the face of something you find burdensome. That is uninteresting to me.

This subject has been hashed to death, we're repeating the same arguments. You want to leave things ambiguous, I want to ensure that behavior is well-defined.

You're right that this has been abandoned by other languages. In many of those languages -- including Scala -- you can make use of Either/Option monads to achieve the same effect without exceptions at all. In others, you just have to either expend a bunch of mental effort to ensure you code defensively, or take your approach of spinning the chamber and hoping for the best.

Your argument for "well defined points" only begins to make sense in purely functional languages. Otherwise, there's no way to guarantee a lack of side-effects in your use of atomic-goto, and the result is invariably that the software is unreliable and prone to strange stateful failure.


Working with the org.json.JSON classes is what made me switch my mind about the use of checked exceptions. Catching these checked exceptions makes no sense at all.


That API in particular has 'opt' variants of its accessors that return NULL rather than throwing an exception.

That said, a standard clean usage model for the checked variants would be to declare a 'throws' from your JSON parsing code, and then at a higher level wrap that in an InvalidMessageException or similar. The non-checked approach would be to check for NULLs and ensure that none escape your parsing code.

The only time the checked version becomes burdensome is if you don't encapsulate your JSON -> app model parsing in a single place, and instead sprinkle the code with unencapsulated JSON parsing. In that case, I believe the problem is a lack of encapsulation, not the checked exceptions -- the exceptions just highlights that one is not separating concerns between code that must be aware of parsing issues and potentially invalid data, and code that can be guaranteed to only operate on valid and whole data.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: