Live data from Hacker News

Why checked exceptions failed

borretti.me

31–40 of 318 posts

Re: Why checked exceptions failed

#31
post #18

While I broadly agree with this, the author doesn't appear to go far enough himself. > Functional error handling, using Option and Result types, is rapidly becoming the standard operating procedure in essentially every language, because it relies on nothing but values and types. They are more of the same, and so they fit right into the existing language machinery. I agree that Optional types are better than checked e…

I often run into the opposite problem: There are union types, but I would really like sum types (i.e. tagged unions). The common case is a data structure where I cannot guarantee that the user will not want to use Null as a value in my data structure, but I also need to represent the absence of values myself. With a sum type, my absence would be None and the user’s absence would be Some(None). With union types, I need to somehow create an extra sentinel value myself.

Re: Why checked exceptions failed

#32

Checked exceptions are used to make up for Java's inability to return more than one value, plus it's inability to wrap two values without defining a new type. In other words, I think checked exceptions are basically a symptom of a lack of object literal syntax. This is in addition to their status as a "cool language feature" that is a siren song to new, bright programmers looking to spice up their designs. Exceptions…

Just came to say this. I think the best way to represent failure is in the return type, but Java made that very cumbersome and noisy.

Re: Why checked exceptions failed

#33
post #7
post #2

I am surprised an even more obvious interface definition of public interface ExampleInterface { void foo() throws IOException, AnotherException; } was not covered: is this also not supported? That would solve a lot of use cases if inheritance is respected.

It is supported, but does not actually solve anything, you're still limited to whatever checked exceptions the creator of the interface has decided might be valid (it's just that in the original it's "none"). Let's say that the creator of the interface allows IOException, but the backend of my implementation is a database so I have SQLExceptions, same issue. Is the creator of the interface supposed to add every check…

Maybe your SQLException should be caller's IOException? I don't code Java but IMO callers should be hit with errors at the right abstraction level. If caller is using that interface and not your low-level backend functions directly then caller should expect IOException not SQLException.

If the interface does not provide exception types for all cases so you are stuck rethrowing your error as a wrong one, and I'd say that means the interface is bad but not checked errors are bad...

Re: Why checked exceptions failed

#34

I have extensive experience in C# as well as Java. It is bizarre to suggest that checked exceptions have failed. It is unchecked exceptions that have failed. It is the biggest flaw of C#, in fact. Why? As an example, I wrote some very good C# code, carefully tested it, made it work flawlessly, then suddenly it started crashing. What happened? Someone made a change in a function I was calling, and it started throwing…

“I wrote some very good C# code“

We all do.. its always that other guy who is at fault :)

Re: Why checked exceptions failed

#36
post #7
post #2

I am surprised an even more obvious interface definition of public interface ExampleInterface { void foo() throws IOException, AnotherException; } was not covered: is this also not supported? That would solve a lot of use cases if inheritance is respected.

It is supported, but does not actually solve anything, you're still limited to whatever checked exceptions the creator of the interface has decided might be valid (it's just that in the original it's "none"). Let's say that the creator of the interface allows IOException, but the backend of my implementation is a database so I have SQLExceptions, same issue. Is the creator of the interface supposed to add every check…

> Let's say that the creator of the interface allows IOException, but the backend of my implementation is a database so I have SQLExceptions, same issue.

The creator of the interface should decide on a generic exception type:

  public interface UniversalStorageInterface {
      void store() throws StorageException;
  }
Then, in the present, the FileStorage can define (and throw) a FileStorageException (inherits from StorageException), and the SqlStorage may define (and throw) a DatabaseStorageException (same).

In the future, where we might want to store everything on a (non-existing yet) Cerulean backend, we would then define (and throw) a CeruleanStorageException (again, an implementation of StorageException), and our basic Interface would not need to change. We would also have no need to recompile FileStorage or SqlStorage (or proprietary SteelBlue storage where we have no code).

Re: Why checked exceptions failed

#37
post #19

I have extensive experience in C# as well as Java. It is bizarre to suggest that checked exceptions have failed. It is unchecked exceptions that have failed. It is the biggest flaw of C#, in fact. Why? As an example, I wrote some very good C# code, carefully tested it, made it work flawlessly, then suddenly it started crashing. What happened? Someone made a change in a function I was calling, and it started throwing…

>you would have to catch the root Exception class, which everyone agrees is a bad idea. It's a bad idea to catch an unexpected exception?

The issue brought up by the parent is that the exception needed not be unexpected. If the compiler had generated an error because a new exception type could be thrown by the third party API, the developer could have decided that they either couldn't do anything with it and just add a catchall, or actually implement code specifically to handle this issue.

IMO the entire concept of "unexpected exception" is bogus in and of itself. That's like calling "exit(1)" in your code when something goes wrong instead of using proper error handling facilities.

Admittedly it's very convenient for small scripts where proper error handling might be overkill, but for any serious application it's a massive footgun IMO.

Re: Why checked exceptions failed

#38

I have extensive experience in C# as well as Java. It is bizarre to suggest that checked exceptions have failed. It is unchecked exceptions that have failed. It is the biggest flaw of C#, in fact. Why? As an example, I wrote some very good C# code, carefully tested it, made it work flawlessly, then suddenly it started crashing. What happened? Someone made a change in a function I was calling, and it started throwing…

Why not catch System.Exception also? Or just catch

When you catch the root Exception class in C# you end up catching IndexOutOfRangeException as well. You should let the program crash instead because this happened due to a bug in your program. Continuing as if nothing happened is unsafe.

Another issue is that you are not allowing higher layers see the exception, even though they may have logic for recovering from the exception. To see the exception they have to now fix your code by removing the catch-all.

Re: Why checked exceptions failed

#39

I have extensive experience in C# as well as Java. It is bizarre to suggest that checked exceptions have failed. It is unchecked exceptions that have failed. It is the biggest flaw of C#, in fact. Why? As an example, I wrote some very good C# code, carefully tested it, made it work flawlessly, then suddenly it started crashing. What happened? Someone made a change in a function I was calling, and it started throwing…

> The list of recoverable exceptions that can be thrown by a method should be part of the contract.

If it’s really recoverable, then should it actually be an exception? How often do you see exceptions that are recoverable?

> If not, then to avoid crashing you would have to catch the root Exception class, which everyone agrees is a bad idea.

I disagree that it’s a bad idea, having a catch-all exception handler to avoid crashing the entire app is a good idea.

Java also has RuntimeException, and with it, a whole host of exceptions that may occur but are not declared. Should every function that uses the division operator be marked with `throws ArithmeticException` since it may end up being a division by zero? That would quickly become absurd.

Re: Why checked exceptions failed

#40
post #15

Earlier quoted context omitted.

Wouldn't it still be a problem? By putting "throws [Exception List]" in the interface, the interface making assumptions about the implementation details of every potential implementation. The interface can't know every exception that an implementation might throw, and using your example, some implementations may not use IP at all and won't throw those exceptions. It seems like you'd end up needing to list every possi…

> the interface making assumptions about the implementation details of every potential implementation. No, as you'd force the implementation to catch their implementation specific exceptions and rethrow them in the way defined by the interface. That's really the crux of it, when I call foo(), I expect to see a FooException when something goes wrong, since that's the only one I can meaningful react to. If I get an Imp…

Unless the language does that for you (both enforcing it, and providing tools to make it absolutely trivial), it will never happen, it's just way too much overhead to have to define a new exception for every method in an interface, then a sub-exception for every method in the implementation of that interface, then go through the internal conversions from the underlying exceptions to the parent one.

People can't be arsed to do that in Rust where there's ways to abstract over those things and macros to define them.

If that's the route you assert is necessary, you need something like Zig's errors.

Post reply on HN