If there's a benefit to compile-time exception checking over this method, I have to admit I don't see it. But I've also never worked deeply enough with Java to be familiar with the nuances of its exception handling, so that may be why.
That's why it is really useful to know when a call can fail, and what kinds of errors you have to expect.
If you always have to add a generic error handler for possible unknown errors, then you'll write a lot of untested, dead code.
Sure there is. Find the way it happens, do that, and test that the handler does what it's supposed to. Or, if you can't do that, mock the error.
I suppose that's not guaranteed to be straightforward in Java; it's been a long time but I seem to recall libraries being provided in compiled form, without sources, and it therefore not always being possible to identify the conditions that need to be set up in a unit test. If I recall that correctly, it makes me very glad I no longer use the language.
> If you always have to add a generic error handler for possible unknown errors, then you'll write a lot of untested, dead code.
The generic handler in this case is
else {
throw error; // rethrow
}
You're not wrong that there's value in knowing what exceptions can be thrown at a given point in code. But, as I mentioned in another comment, that's something that can in the general case be known through static analysis, and should. In fact, the Java compiler must already be doing something substantially similar to that analysis for checked exceptions to work at all! Looking for throw statements rather than "throws" declarations seems like it shouldn't be that much more difficult, and I think the burden on Java developers could be substantially lightened thereby in that "throws" declarations would no longer be required.It's useful when there are one or two error cases you want to retry or handle specially, but you want to just barf any other error up the stack. It's a specific use case but it's prevalent.
The downside is that sugar can only separate your error conditions by Java type. If everything is just an Exception, you'll have to use sort out your error cases in code.
Being able to know what exceptions can possibly be thrown at a given point is useful, but seems like a problem better solved through static analysis than by requiring annotations.
In F# it works quite well, though.
You can write almost exactly the same code with your Result by ignoring the error until the point you would catch it with exceptions.
The only difference is that exceptions bubble up if unhandled, which requires a generic catch to match code ignoring errors otherwise.
It is quite a bit more explicit in that something can have an error and in what ways it can error (if you enrich the type in that way), while still being ergonomical. And it reserves exceptions for the truly unexpected/exceptional cases.