Hacker News new | ask | show | jobs
by norswap 502 days ago
While I agree exceptions should not be used for control flow except in the rarest of circumstances (every rule has exceptions — pun fully intended), I think checked exceptions are very useful.

I wrote a whole article about this, way back when: https://norswap.com/checked-exceptions/

But for the tl;dr: checked exceptions represent somewhat expected issues, things like IO errors. There are two okay ways to handle those: checked exceptions and result types, and one bad way: unchecked exceptions.

Unchecked exceptions end up being undocumented in the API, and people forget to handle them.

Result types add a lot of ceremony, as you have to unwrap them at every level of the call stack. I've seen code dominated by error checking logic many times in C and Go (and the frequent alternative is to ignore error, which is easy in C).

Checked exceptions are much less verbose, you just let the exception pass through and annotate the function signature with the checked exception. It's type-safe, self-documenting and easy.

Unchecked exceptions "leak", checked exceptions propagate at the type-level, which is exactly what you want — making sure every caller is aware of what exceptions might occur and letting them make an explicit decision to handle or pass the buck upwards.

By the way, checked exceptions are coming back in favour with "effects" which are basically a generalization of checked exceptions beyond the realm of errors, trying to encode things into the type system.

2 comments

These arguments have been going back and forth forever. I don't think either of us would be able to change each other's position on this based on arguing either way.

I'll take a different tack - look at the empirical evidence. If checked exceptions were a good/useful/helpful language feature, then the feature would have been adopted by other languages, especially new ones. But this simply hasn't happened. Java is unique in having checked exceptions.

Wouldn't you think that there would have been proposals to introduce checked exceptions for C++, Python, JavaScript, C#, and Rust, Kotlin, etc. if they were a useful software engineering tool?

I used to think checked exceptions were stupid, so I'd catch and wrap them in a RuntimeException at the first opportunity just to get rid of them.

These days I've come around to your viewpoint that checked exceptions are great because all you have to do is declare them until you get to a point in the call hierarchy where you either can handle them or it's impossible to handle them so you wrap them.

In some cases, like with reflectively-invoked JUnit test methods, they only need to be declared because JUnit has its own exception handler. But you wouldn't believe the crazy amount of test code I see that eats exceptions instead of declaring them.

I think the confusion comes because with very simple programs you only ever see the point where you have to handle the checked exception, so a habit of writing catch blocks forms. It's only when designing libraries that you would declare checked exceptions as part of your method signatures and just allow them to naturally propagate. Therefore new Java programmers see all these extra catches and think it's just a burden they have to meet.

Another thing about Java that's bad for casual coding is that it exits 0 (success) when all non-daemon threads have ended, even if those threads ended because of an exception. It would be really nice if there was some internal flag set by the default uncaught exception handler that would cause a non-zero exit later when all threads are finished (which might be right then). Maybe I should submit a JEP.