Live data from Hacker News

Why checked exceptions failed

borretti.me

281–290 of 318 posts

Re: Why checked exceptions failed

#281
I think Swift’s error model is my favorite (though Go’s new error stuff seems similar). Unrecoverable errors are unrecoverable (they’re aborts) and other errors are marked in the function’s signature and must be handled explicitly. This means the error effect is explicit along the call stack until somebody handles it

Re: Why checked exceptions failed

#282
post #228

Earlier quoted context omitted.

What about: NullPointerException? ArrayIndexOutOfBoundsException? IllegalArgumentException? UnsupportedEncodingException?

One of these things is not like the others ... The first 3 need to terminate your thread because something is irretrievably incorrect. The only sane thing to do is stop. "UnsupportedEncodingException" has lots of things you can do to recover. You can try different encodings. You can request retry of someting. You can check a CRC for corruption. etc. So, the first 3 really shouldn't litter your code. The final one pro…

Finally a person who knows Java ;-)

For other readers the first 3 are all runtime exceptions and the last one is a checked exception that a lot of people complain about...

I think the last one is an example of why people hate checked exceptions and the solution to this was to create newer APIs that focus on UTF-8 that just don't throw that exception.

Re: Why checked exceptions failed

#283
post #209

Earlier quoted context omitted.

What about: NullPointerException? ArrayIndexOutOfBoundsException? IllegalArgumentException? UnsupportedEncodingException?

Null pointer exceptions shouldn't exist in the first place, they're fairly trivial to avoid. Index out of bounds can be similarly avoided, although the cost in terms of economics is a lot steeper. I like Rust's strategy of providing a checked and an unchecked indexing mechanism, where the unchecked indexing mechanism typically crashes the program rather than just throwing an exception. Illegal arguments can often be…

Notice that parent comment was directed to a person who has the opinion of "everything should be a checked exception"... Not towards you.

Crashing the program isn't an option for a lot of applications. All those exceptions give me a runtime stack that I can log and an error that's very easy to fix quickly. The first 3 are runtime exceptions which means you won't know about them and don't need to write defensive code.

I love rust and its compile time checks. Checked exceptions are very similar to the concepts in rust, check as much as possible during compilation. However, this makes rust code non-trivial for some dynamic behaviors and sophisticated object graphs. There's a balance that we usually choose based on a languages target demographic. Rust is great for system programming, Java is great for enterprise programming. Both are very different domains with very different needs.

The discussion about null is a huge one and I'm already spending way too much time in HN comments. Forgive me if I don't open that damn can of worms ;-)

Re: Why checked exceptions failed

#284

Earlier quoted context omitted.

No. This comes from a misunderstanding of checked exceptions. Checked exceptions don't mean I need to handle the exception right now. They mean I need to either do that or declare throws. Declaring throws is fine it implicitly documents the code and enforces a similar requirement up the chain. Checked exceptions aren't the default and shouldn't be.

Declaring throws end up leaking layers of abstractions in practice. Many thrown checked exceptions are not appropriate to pass above certain layers. It is often not OK to expose checked exceptions that are really implementation details up the chain—-it’s not a “similar requirement”—-it is exactly the same requirement and often an inappropriate one at many levels up the chain. If you just pass exceptions up in throws,…

I think we're actually not that far off in our opinions.

Throwing an exception is an implicit part of our contract, whether we declare it or not. Since any method can throw an exception that implementation detail is already exposed we just don't know about it.

Yes. Propagating checked exceptions through a long chain is indeed a pita and as I said before, we need to be vigilant about using them correctly. But if I have library or infrastructure code that is doing IO/SQL, I still want people to know and handle the failure correctly.

I think they were never picked up in other languages because no one likes to tidy their room. You want to write a unit test or a hello world and suddenly there's a checked exception... No fun. Also it was used for many APIs that people felt were built badly (e.g. the infamous encoding exception, URL format, etc.).

Re: Why checked exceptions failed

#285
post #228

Earlier quoted context omitted.

One of these things is not like the others ... The first 3 need to terminate your thread because something is irretrievably incorrect. The only sane thing to do is stop. "UnsupportedEncodingException" has lots of things you can do to recover. You can try different encodings. You can request retry of someting. You can check a CRC for corruption. etc. So, the first 3 really shouldn't litter your code. The final one pro…

Finally a person who knows Java ;-) For other readers the first 3 are all runtime exceptions and the last one is a checked exception that a lot of people complain about... I think the last one is an example of why people hate checked exceptions and the solution to this was to create newer APIs that focus on UTF-8 that just don't throw that exception.

Why is "UnsupportedEncodingException" an issue?

It should throw only on creation and then never be an issue from that point forward, no?

If it's throwing everywhere then, as you point out, that is an API problem rather than a problem with exceptions, themselves.

Re: Why checked exceptions failed

#286
post #285

Earlier quoted context omitted.

Finally a person who knows Java ;-) For other readers the first 3 are all runtime exceptions and the last one is a checked exception that a lot of people complain about... I think the last one is an example of why people hate checked exceptions and the solution to this was to create newer APIs that focus on UTF-8 that just don't throw that exception.

Why is "UnsupportedEncodingException" an issue? It should throw only on creation and then never be an issue from that point forward, no? If it's throwing everywhere then, as you point out, that is an API problem rather than a problem with exceptions, themselves.

Yes. It's 100% an API problem...

Re: Why checked exceptions failed

#287

Earlier quoted context omitted.

I'm curious how this is possible? Exception throwing and handling is fundamentally a flow control construct. ie: throwing an exception must control flow. A counter-example snippet where throwing an exception does not control flow would be appreciated.

He means exceptions are not for common control flow that shows up everywhere, like a return value. You want an exceptional control flow change when your hard drive runs out of storage, but you don't want exceptional control flow change when your hashtable doesn't have the key you're looking for. The categories and frequency of these conditions are very different.

Hmmm, sounds like it just transforms into a Sorites paradox, no?

Re: Why checked exceptions failed

#288
post #239

Earlier quoted context omitted.

> The map function can throw a superset of the exceptions that its argument can throw. Wait. Why should a map care about what exceptions it's arguments can throw? A map is storing a thingit. A thingit should exist independently before it gets placed into a map. Placing a thingit into a map should not invoke anything on the thingit. The only exceptions coming back from attempting to place a thingit into a map should b…

You're thinking of a finite map, also called a hash table or a dictionary. The map function takes a function and a list and applies the function to every element of the list: map(double,[1,2,3]) = [2,4,6] Grandparent could've used the for loop rather than the map function to make his point: for i in [1,2,3]: print i * 2 -- because in general instead of the i * 2 we might have a call to a function that might raise an…

Whoops. Yeah, I wasn't thinking about map, fold, accumulate, etc. Thanks for the correction.

Re: Why checked exceptions failed

#289

Earlier quoted context omitted.

Declaring throws end up leaking layers of abstractions in practice. Many thrown checked exceptions are not appropriate to pass above certain layers. It is often not OK to expose checked exceptions that are really implementation details up the chain—-it’s not a “similar requirement”—-it is exactly the same requirement and often an inappropriate one at many levels up the chain. If you just pass exceptions up in throws,…

I think we're actually not that far off in our opinions. Throwing an exception is an implicit part of our contract, whether we declare it or not. Since any method can throw an exception that implementation detail is already exposed we just don't know about it. Yes. Propagating checked exceptions through a long chain is indeed a pita and as I said before, we need to be vigilant about using them correctly. But if I hav…

> Throwing an exception is an implicit part of our contract, whether we declare it or not

I think this is the main reason why checked exceptions and errors as values work. The alternative is having to always specify all the exceptions in documentation so the caller knows what to expect, and hope that documentation covers everything and doesn't get out of date. That also has to propagate if the caller doesn't handle all exceptions, just like checked exceptions.

It's much better to encode this directly with checked exceptions or Result. Why people like errors as values so much but dislike checked exceptions is beyond me. They're basically the same thing with different syntax.

Re: Why checked exceptions failed

#290

Earlier quoted context omitted.

"All non-primitive values are nullable references" is a feature of the language. You posted that you are trying to avoid using that feature (instead using non-null references to a special Null value?) and trying to avoid having null references for the types you create. It seems like you do not actually think the feature is a good feature.

> Ditto @Nullable and @Nonnull. I was referring to the annotations. My proposal moots them. References would still be nullable.

Can you explain why it is good that null is a valid value for your types at the same time as you are trying to prevent them from ever containing that value?
Post reply on HN