Skip to content

Instantly share code, notes, and snippets.

@donalmurtagh
Created September 13, 2024 13:29
Show Gist options
  • Save donalmurtagh/795984103e639a4aaf2e0fb6a6019c16 to your computer and use it in GitHub Desktop.
Save donalmurtagh/795984103e639a4aaf2e0fb6a6019c16 to your computer and use it in GitHub Desktop.
A more realistic version of the code sample on https://result.leakyabstractions.com/
int getServerUptime() throws ConnectionException {
var server = connect();
server.refresh();
return server.getUptime();
}
@guillermocalvo
Copy link

I'm afraid there's a crucial difference between your counterexample and the original code. Your version of the method propagates the exception upstream, whereas mine returns a specific value to indicate that the result can't be obtained currently.

If ConnectionException is checked (which is kind of implied in the example), someone else will have to try and catch it. The new version of the method is simply kicking the can down the road. It will make someone else's code uglier.

Exception-throwing methods have even more inconvenient implications. For example, you can't possibly use your version of getServerUptime as a Supplier. One of the goals of this library is to make functional programming easier in Java.

@donalmurtagh
Copy link
Author

donalmurtagh commented Sep 13, 2024

If ConnectionException is checked (which is kind of implied in the example), someone else will have to try and catch it. The new version of the method is simply kicking the can down the road. It will make someone else's code uglier.

But if you handle the exception within getServerUptime you're preventing callers from handling the error in different ways. In most cases the right thing to do is to propagate the exception, so that (for example) caller A can ignore it and caller B can retry the operation

Exception-throwing methods have even more inconvenient implications. For example, you can't possibly use your version of getServerUptime as a Supplier.

That's true if the exception is checked. The consensus within the Java community is that checked exceptions were a mistake. For example, all exceptions thrown by the Spring framework are unchecked.

@guillermocalvo
Copy link

In most cases the right thing to do is to propagate the exception

I disagree. The right thing to do is to handle the exception where it makes sense, and to propagate it where it makes sense. And that depends on the specific semantics of the method invoking the exception-throwing API. There is no silver bullet strategy.

The consensus within the Java community is that checked exceptions were a mistake.

For what is worth, I don't think there is a consensus. And my quarrel is not with checked exceptions, anyway.

The problem Results are trying to solve is twofold:

  1. As a developer, I want to document what kind of errors my API can fail with. Accordingly, I want to know what kind of errors I should/could be dealing with when I use a third-party API.
  2. As a developer, I want to be able to use any API with a functional approach, regardless of the types of errors it may fail with.

Checked exceptions meet requirement #1, but the way they are designed in Java makes it hard to use such APIs freely with Function, Predicate, Supplier, Consumer, and the like. That's why checked exceptions are not a convenient solution for me.

Unchecked exceptions, on the other hand, meet requirement #2. But they remain documented by means of Javadoc only. The compiler will not complain if I neglect the possibility of errors. And that's why unchecked exceptions are not a solution I can rely on, either.

As a beneficial side effect, programs tend to run faster once you remove the overhead of exceptions. All in all, I'm better off using Results than using exceptions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment