Comment by rectang

Comment by rectang 2 days ago

1 reply

Invisible control flow is common to all implementations of unchecked exceptions (Java, C#, C++, Python, Ruby, etc). It means that any code, anywhere, at any time, can throw an exception which may represent a recoverable error.

People are used to that, and one common strategy is to not worry too much about handling individual exceptions but to instead wrap a big `try` block around everything near the outer boundary of your code. It’s good enough for many purposes and yields a high initial development velocity, but is comparatively fragile.

With Languages like Rust, Go, and Swift, only unrecoverable errors trigger the panic mechanism. Every call site where a recoverable error may occur is identifiable — in Rust via Result, `unwrap()`, the `?` operator, etc, in Go via returned Err (though unlike Rust you can discard them silently), and in Swift via the `try` operator.

You can still develop quickly by just unwrapping every Result, but unlike languages with invisible control flow, you can easily audit the codebase and go back to harden every site where a recoverable error may occur — yielding a level of robustness which is difficult to achieve in languages with unchecked exceptions.

peterashford 2 days ago

As someone who uses Go professionally now and Java previously, I disagree with your take on unchecked exceptions. I think that Panics and errors is worse than just using exceptions. I think the latter is just simpler to deal with. At the end of the day, when error handling is complex, its complex with either approach - you have to think carefully about what's happening in the problem domain and come up with a robust solution. What the code level adds is complexity: the Go approach is more complex and consequently worse. I love Go coding but its error handling sucks and I would gladly have the Java approach instead.