Live data from Hacker News

Why checked exceptions failed

borretti.me

51–60 of 318 posts

Re: Why checked exceptions failed

#51
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…

If your language supports implicit user-defined conversions (like C#), you could `return "foo";` from a method returning `Result`.

Re: Why checked exceptions failed

#52

Earlier quoted context omitted.

Catching the root exception is not a bad idea. If you had caught the new exception what would you have done with it? Most of the time, it’s either catch the exception, log it in a central logging system keep moving and have a central alerting system or catch the exception log it and crash the program.

It is a bad idea according to Microsoft. See https://learn.microsoft.com/en-us/dotnet/fundamentals/code-a...

This is for a library. Whatever the “root” of your code is should have a generic catch all where you do “something”, you don’t want library code (either yours or the system) to decide for the user what should be done with exceptions.

As a library writer, you should do something about exceptions that you can and rethrow the ones you can’t,

Re: Why checked exceptions failed

#53

Earlier quoted context omitted.

We have it in Java too. For us it's try-with-resources and has nothing to do with checked exceptions. Checked exceptions remind you that you need to wrap the code and need to take that into account. They also force you to declare that an exception is thrown if you don't want to handle it in the current method. That's important as the signature of the method carries an important failure that can't be dismissed and is…

What “reminder” do you need to wrap your code? I can’t think of an instance that you wouldn’t wrap your code in a try/catch block around your code and either log and crash, log and continue, or for a specific exception that you know about, do “something”. But most of the time it’s the first two if you’re using RAII.

Let's say I write an API for handling IO. DB or File or networking or anything really.

I get a failure, what do I do?

I can throw an exception, but this is important how do I know the user of my API will actually do the cleanup after me. I can't do the cleanup since this is a part of an API not the actual usage of the API. How can I give the user of this API the right set of hint that "you need to pay attention to this" without worrying too much.

Checked exceptions are that. A large part of the problem is when people use them for things that aren't important, but when they are important I can just declare a "throws" and know that someone will handle the exception along the chain.

With runtime exceptions I have no guarantee.

Re: Why checked exceptions failed

#54
post #21

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…

> Someone made a change in a function I was calling, and it started throwing a new exception. If it has nothing to do with your code, why not either let it bubble up the stack or try/finally it to do whatever clean-up you need to do before re-throwing it and letting it move on to a global logger or similar. If it is something you care about you can always catch the specific exception type and handle it. Maybe whoever…

Imagine that the functionality implemented by your method is very important. This functionality should not be needlessly aborted. If so you want to be aware of errors you can recover from, correct? This is why checked exceptions are helpful. It gives you a guaranteed-by-compiler list of exceptions and you can decide which of those you should recover from.

Re: Why checked exceptions failed

#55

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 avoi…

Yes, in Java’s parlance an Exception is a recoverable code path, Error is the kind that is not.

E.g. a network call failing due to some IOException can be easily retried, that’s a proper error handling.

Re: Why checked exceptions failed

#56

Earlier quoted context omitted.

> Calls that must have proper cleanup after them e.g. SQL, IO are checked. Why? In C# you use a “using” block and whether your code exits the using block successfully or with an exception, the cleanup is automatic. RAII has been around at least since the 80s with C++.

We have it in Java too. For us it's try-with-resources and has nothing to do with checked exceptions. Checked exceptions remind you that you need to wrap the code and need to take that into account. They also force you to declare that an exception is thrown if you don't want to handle it in the current method. That's important as the signature of the method carries an important failure that can't be dismissed and is…

> 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 fail.

Re: Why checked exceptions failed

#57
post #36

Earlier quoted context omitted.

> 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 StorageExc…

So now whoever creates the interface needs to define an exception type per method, and whoever implements the interface needs to define a subclass of that per method and catch-and-wrap every exception their callee raises. You better add some serious tooling built into the language to facilitate this, because from experience ain't no way anyone's going to bother with this if they have to handroll it, even with IDE cod…

It doesn't have to be a type per method, and if someone is "going to bother with this" depends on the application — I guess in many cases it's perfectly fine to write a happy code with a single catch where you present a sad-face emoji and "try again later" line; in other types of applications this just won't fly.

Re: Why checked exceptions failed

#58
post #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 nee…

Something like String|NoAnswer|None doesn't sound too bad to me here...

Re: Why checked exceptions failed

#59

Earlier quoted context omitted.

It is a bad idea according to Microsoft. See https://learn.microsoft.com/en-us/dotnet/fundamentals/code-a...

This is for a library. Whatever the “root” of your code is should have a generic catch all where you do “something”, you don’t want library code (either yours or the system) to decide for the user what should be done with exceptions. As a library writer, you should do something about exceptions that you can and rethrow the ones you can’t,

> Whatever the “root” of your code is should have a generic catch all where you do “something”

If your only goal is to avoid crashing the app then you can catch the base Exception class at the root of you code and go home. But consider the scenario that you're writing a very important method, where the functionality of your method is very important. If your method does not do its job, the rocket may crash or the patient may die. In this case you want to know what recoverable errors are possible in the functions that your method calls, correct? Wouldn't be it nice to get a guaranteed-by-compiler list of possible, recoverable, errors?

Re: Why checked exceptions failed

#60

Earlier quoted context omitted.

> Calls that must have proper cleanup after them e.g. SQL, IO are checked. Why? In C# you use a “using” block and whether your code exits the using block successfully or with an exception, the cleanup is automatic. RAII has been around at least since the 80s with C++.

This is what try-with-resource does in Java. Introduced in Java 8 I think so better late than never

Anytime I see “something was added to Java” late in the game, it’s usually an ugly hack.

But I have to admit that the syntax for it is actually sensible.

Post reply on HN