Live data from Hacker News

Why checked exceptions failed

borretti.me

201–210 of 318 posts

Re: Why checked exceptions failed

#201
post #154

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…

> Go's exceptions have the same unfortunate property as Java's checked exception. Wait what? Here's where you lost me. You don't "throw" errors in Golang. Instead it's common practice for functions to return multiple values, one of which can be an error. Errors are just structs that implement the Error interface. The language (and the compiler by extension) doesn't make you explicitly handle errors. On the contrary:…

The point GP was making is that both Go and Java (in code which makes heavy use of checked exceptions and different exception types) mix together the business logic with error propagation. So, even though in Java you throw exceptions and in Go you return error values, they both end up (or can end up, in the case of Java) having lots of error handling boilerplate all around a function.

In Java of course this doesn't have to happen, but it can end up happening if you chose to have many exception types and different exceptions types when crossing layers (e.g. try { doX(); } catch (IOException e) { throw new MiddleLayerException("failed to do X", e);}).

To be fair though, Java still allows you to write that like this:

  try{ 
    x = doX();
    y = doY(x);
    z = doZ(y);
  } catch (XException | YException | ZException e) {
    throw new MiddleLayerException("...", e);
  }
Which is still better than Go's:

  x, err := doX();
  if err != nil {
    return MiddleLayerErr(err);
  }
  y, err := doY();
  if err != nil {
    return MiddleLayerErr(err);
  }
  z, err := doZ();
  if err != nil { 
    return MiddleLayerErr(err);
  }

Re: Why checked exceptions failed

#202
post #195

Earlier quoted context omitted.

Checked exceptions should be the default, exceptions should just be rare. They are overused in almost all languages.

What do you mean when you say "exceptions should be rare"? Do you mean they should not occur frequently during runtime, or that it should be rare to see explicit exception handling in a piece of code?

[deleted]

Re: Why checked exceptions failed

#203

Checked exceptions failed because developers are lazy and don't want to check for errors. Checked exceptions force you to do more work, but it's essential work to make your code more robust. Replacing them with runtime exceptions gives you the illusion of clearer code, but all you have is actually code that is more likely to crash.

It's not a matter of laziness. Most of the time there's just nothing you can do.

Like if you try to construct a URI based on a configured URI string, and get URISyntaxException... wtf should you even do? You can't recover, because your code shouldn't be mutating config. Similarly with basically any JSON parsing exception. And most disk read/write exceptions.

And in modern applications the caller is probably on the other side of an RPC call, and checked exceptions won't propagate sanely across the RPC anyway.

Re: Why checked exceptions failed

#204

Earlier quoted context omitted.

You are very confused... "strong" in strong typing doesn't mean you have to write much or at all. Actually, it doesn't mean anything really. But, let's say, Haskell is probably at least as "strongly typed" as Java -- at least that's how most people understand that wording. And you don't have to write types in Haskell at all. It will be a nightmare (as if Haskell can be anything else, but even by the very low Haskell…

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.

Re: Why checked exceptions failed

#205

Earlier quoted context omitted.

I misspoke. Ignoring the syntax for a moment, I want scoping to behave like this pseudo-code. So that the catch and finally blocks are lexically nested within the parent try block. try { OutputStream out = ... ... // Must be at end of try block catch ExceptionA, Exception B { ... } catch Exception C { ... } finally { ... } } // end of try Maybe even allow catch and finally to allow single expression in addition to bl…

If constructing "out" fails but one of the catch-blocks tries to use "out", what should happen?

Python is an example of a language that works like this. When the constructor throws, 'out' remains not defined, but you can just do 'out = ...' in the catch block and define one with a fallback value. So all the code after the error handing would just see a working 'out' variable. This works due to all variables being bound to the function scope, not to the code block, in Python.

Re: Why checked exceptions failed

#206
post #9

The issue with all exceptions, and error handling in general, is that only very rarely is there actually recourse for an error. For instance, in an HTTP request handler, the vast majority of errors will end up as something like a 500. Checked exceptions are annoying because they make you explicitly handle an error when you likely already have a handler in place to handle all exceptions, checked or otherwise.

To me, you kind of hit both the pros and cons of checked exceptions. It makes the calling code have to deal with an important error case. This is actually super useful for very important error situations (for instance, let's say you're writing some type of file-processing class, and the class was unable to open the file for some reason, it might be a good situation to throw a checked exception as this can probably happen reasonably often).

To me, the difficulty with exceptions is when writing a method that needs to throw an exception is deciding whether it should throw one that is actually checked. In fact, read a few of years ago most exceptions should actually be unchecked, but at least then, this was still greatly up for debate.

... as I type this, am realizing having the option of unchecked and checked exceptions is nice in that they reduce the amount error code you have to write. Because by throwing unchecked exceptions, this is error handling that all the entire calling code-chain doesn't need to deal with. The obvious situations are system errors like out of memory errors, missing resources... but also those programmatic errors that are unexpected, like array out of bounds, ClassCastException.

Also, the calling chain then has the option to handle it if it's needed. For instance, if you're writing a low-level messaging queue that needs to report system errors (btw, this was a real situation that happened to me). Just my two cents.

Re: Why checked exceptions failed

#207

Earlier quoted context omitted.

Checked exceptions should be the default, exceptions should just be rare. They are overused in almost all languages.

What about: NullPointerException? ArrayIndexOutOfBoundsException? IllegalArgumentException? UnsupportedEncodingException?

What about them? If your language semantics are pervaded by exceptions, that kinda suggests your language sucks. If you're unlucky enough to find yourself in this situation, then make exception contracts simple to express and propagate.

Re: Why checked exceptions failed

#208
post #195

Earlier quoted context omitted.

Checked exceptions should be the default, exceptions should just be rare. They are overused in almost all languages.

What do you mean when you say "exceptions should be rare"? Do you mean they should not occur frequently during runtime, or that it should be rare to see explicit exception handling in a piece of code?

Situations in which you must raise, propagate and handle exceptions should be rare.

Re: Why checked exceptions failed

#209

Earlier quoted context omitted.

Checked exceptions should be the default, exceptions should just be rare. They are overused in almost all languages.

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 avoided in the first place with sensible types (although, like null pointer exceptions, this typically requires some language support), and unsupported encodings should be rare assuming widespread UTF-8.

So yes, I agree, those should all be very rare exceptions to find in a function signature.

Re: Why checked exceptions failed

#210

Earlier quoted context omitted.

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.

If checked exceptions were implemented in such a way that they were inferred, and they weren't erased in the byte code, much like how people use strong types now, they wouldn't be seen as hoops. Meaning, if you didn't explicitly handle a checked exception, it would automatically bubble up yet be visible to your IDE. I would love if, at design time, all the possible exceptions that could happen were able to be inferre…

Exactly. I have no problem with a function declaring the sort of exceptions it can handle, although simply handling them when they occur is normally good enough.
Post reply on HN