Live data from Hacker News

Why checked exceptions failed

borretti.me

231–240 of 318 posts

Re: Why checked exceptions failed

#231
post #212

Earlier quoted context omitted.

> important failure that can't be dismissed But importance of the failure is determined completely by the program, not the library. Grep fails to open a file for reading -> message the user and exit Nuclear reactor controller fails to read important a file -> initiate reactor shutdown or something. If file read is critical, you have to handle failure no matter what the interface is. Because you know that disk can fai…

But the point is that in both cases the failure needs to be handled somewhere and somehow. Surfacing the error might be a valid option, but to make the decision you need to know that the error is there in the first place. This can be solved with good documentation, but it can also be solved in the type system. Typically, if I can get my computer to do work for me (e.g. make sure that I've handled all possible error c…

Exceptions aren't normal parts of the type system though, they're a way to enforce control flow to deal with them. Another way to do this is with a Result type, which would actually be part of the same type system that you use in the rest of the language.

Re: Why checked exceptions failed

#232

Earlier quoted context omitted.

The library knows which are crucial issues that warrant your attention. A checked exception is a regular exception, it's just one that you can't miss and must either handle or propagate. As a library author if you don't feel you need it then don't use it. It's optional. That's the beauty of it. > First thought: documentation. (which is required for both, checked and unchecked exceptions). Documentation > But overall,…

> The library knows which are crucial issues that warrant your attention The library author can’t know what’s crucial in the context of my program.

Indeed. For most applications, an out-of-memory exception is typically one that's not necessary to handle and just let it bubble to the top, as there's not much sensible you can do if you can't allocate a few hundred bytes for a new object.

However I've written several pieces of code where allocating a large buffer could fail but where this failure was not crucial. So I handled the out-of-memory exception and just moved on.

Re: Why checked exceptions failed

#233

Earlier quoted context omitted.

Agreed. Too often exceptions end up driving normal control flow, when the should just be...exceptions.

You must have a real panic when you see a sign saying “No parking except weekends.” Weekends happen all the time!

You're right, weekends happen all the time, which means they're not exceptional, so you shouldn't throw an exception if you encounter a weekend.

Re: Why checked exceptions failed

#235

Checked exceptions failed because 99 times out of 100 the exception is not recoverable, so the try/catch block is just wasting everyone's time. (In 7 years as a Java dev I can think of one time I wrote code that tried to recover from IOException instead of just making the caller retry.) Even when the exceptions is theoretically recoverable, it has to get propagated up properly to the caller who should be handling rec…

Though I mostly agree it's slightly more subtle IMO. They failed because the writer of the method cannot know what the caller can recover from but must decide before compile time. The caller gets little say.

Re: Why checked exceptions failed

#236

Earlier quoted context omitted.

Type inferencing can get you in trouble quickly. Consider this code: var fireable = someMethod(); firable.fire(); The programmer intended this code to fire an employee. Let's say this code is in a military application, and another programmer modified the someMethod() function to return a missile. As long as the missile object has a fire() method this code will compile just fine... and do something the code didn't int…

This is kind of a ridiculous thing to worry or think about. I’m seeing a lot of type inference in modern Java, and it’s the default way of writing Kotlin.

It is dangerous to call a method on an object whose type is not being checked by the compiler. Whether that's a ridiculous thing to worry about depends on how important your program is. If you work for NASA and your code will run inside the Mars rover, it is not ridiculous to worry about such things, but if you're writing some code that will be used once and thrown away then yeah, it might be ridiculous.

Re: Why checked exceptions failed

#237
post #66

Earlier quoted context omitted.

I stopped using Java a long time ago, and so I assume the language has gotten better since then, but early on at least it felt like Java almost took pride in making the developer jump through extra hoops. Compared to many other languages, using Java just made me feel tired. Checked exceptions - a feature that seems to be a cost to the developer 100% of the time while being a benefit far less than 1% of the time - is…

Some people say the same about strong typing. Like, why do I have to write down the type of every single parameter or variable? Java is making me jump through hoops! The point is, if you don't need the rigor of a strongly typed compiled language, there are other languages you can use. Perhaps a bash script is all you need.

> The point is, if you don't need the rigor of a strongly typed compiled language

This has nothing to do with strongly typed compiled languages vs alternatives.

Re: Why checked exceptions failed

#238

Earlier quoted context omitted.

This comes from a misunderstanding of the reason why exceptions where designed they way they were. The whole point of exceptions bubbling up w/o having to write support code to deal with passing exceptions further is to make it so that the purpose of the function is clear to the reader. Go's exceptions have the same unfortunate property as Java's checked exception. And that's what makes Go's code atrocious. Every oth…

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, you end up causing cascading checked exceptions chain changes and creating a bunch of noise, which is what many times people resort to doing in practice, because they don’t have the experience and it is very rare/almost never done to have any kind of automatic enforcement/linters/static analysis that prohibits implementation detail checked exceptions from propagating past above certain levels.

It is almost never OK to propagate IOException, for example, past maybe 1 or 2 levels of private helper methods, almost never should be propagated past your class boundary and you have to think twice about adding throws to protected methods even, unless your subclass implementations are specifically implementing alternate IO calls.

So yes that’s why checked exceptions have failed. And when you actually take this extreme discipline to your code, yes you end up with a ton of try/catch handling noise and a whole lotta new exceptions classes, and it takes similar extreme discipline to always avoid poor/improper try/catch handlers. Refactoring code across certain boundaries becomes a much bigger hassle, so your end up discouraging refactoring across those boundaries, which leads to code that is more easily stale and design decisions that are much harder to back out of.

Re: Why checked exceptions failed

#239

Earlier quoted context omitted.

> write generic functions that take functions as arguments and re-throw the errors thrown by these functions There is a philosophy that applies here: simple things should be simple, complex things should be possible. The scenario you're mentioning is not common enough that the language design should be centered around it.

It's a very common pattern, almost every modern language has a "map" function. The map function can throw a superset of the exceptions that its argument can throw. If checked exceptions can't deal with this, they'll be of limited use.

> 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 be exceptions caused by the map.

What am I missing?

Obviously, there are maps that conflate themselves and do things like take ownership when an object is placed into the map. But that's not the general case and presumably you wrote the map specifically with that in mind.

Re: Why checked exceptions failed

#240

Earlier quoted context omitted.

Java is the only mainstream language with checked exceptions and checked exceptions are nowhere near usefulness of static typing. Following your logic, Java developers can now say “if you don’t like freedom of Java, use Rust/Haskell/Scala to validate everything at compile time”

Java is not the only language that has checked exceptions. C++ has them too, for example, but thanks god virtually nobody uses them in C++.

C++ never had checked exceptions. It had dynamic exception specifications but they were a very different (and useless) thing as they were runtime checked not statically.

I wish C++ had checked exceptions.

Post reply on HN