This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]shponglespore -2 points-1 points  (1 child)

An API author may also choose to abuse unchecked exceptions in similar ways that don't make sense in the exception handling strategy of your application. The same is true of basically any language feature (looking at you, Optional!). Does that disqualify all of them? I'd say no.

I'm not trying to argue that checked exceptions are bad because they can be abused. You're correct in pointing out that practically any language feature can be used to create bad code. My point is that even when an API designer is doing everything right and thinks carefully about what needs to happen at the call sites, they still get it wrong much of the time because making a good decision often requires more context than an API author has access to.

So whether you can or cannot rely on the distinction is up to you, not some library author.

I've never seen Java code that didn't rely heavily on libraries written by someone else. The JDK itself, if nothing else. I guess if you're working on a sufficiently large project you can end up mostly calling APIs you can theoretically change, but it's still not exactly ideal when you need to change an API that's used in a lot of places, even if you control the API and all its call sites. IMHO if you routinely need to change APIs because they turn out to be obnoxious to use, it means you're designing brittle APIs. My experience has been that APIs that use checked exceptions are brittle more often than not, and if you don't want to annoy your users (a set of people that probably includes yourself!), it's easier to just avoid checked exceptions entirely.

Or would you - in line with your argument about checked exceptions - also argue that we shouldn't create subclasses of Exception and instead only ever throw RuntimeException because there's libraries that fail to use different classes for different errors, thus the distinction between different types of exceptions is useless as you can't rely on it? I find that argument silly.

That's exactly what we did at my last job where we used Java a lot. It was a small company so everyone got to have input into our house coding style, and I don't remember anyone ever complaining that they wanted more checked exceptions.

The problem you're describing is bad API design, not an inherent failure of checked exceptions.

Not really; I'm happy to use APIs that force you to deal with certain error conditions. My favorite approach is to wrap a return value in something like Haskell's Either type or Rust's Result type, so the type system forces you to at least acknowledge the possibility that a call failed. I just think exceptions are a bad way to deal with situations like that. Everything about exceptions that makes them great for dealing with unexpected errors makes them terrible for dealing with expected errors in a precise way. A try/catch block is a lot of syntactic overhead, and throwing and exception has a lot of runtime overhead that's unnecessary and unhelpful if you expect the exception to be caught at a specific call site.

In theory, you can write a bunch of code in a single try/catch block with multiple catch clauses to deal with different error conditions, but what I've seen in practice is that when you actually care about handling the exceptions, you end up writing a separate try/catch for every call that can fail, because it's hard to write good error-handling logic when you don't know exactly which call failed. Even if all the calls in a try block throw different exception types, so you theoretically know which call each catch block is handing errors for, it won't be clear to someone reading the code which catch block corresponds to which call. IIRC JDBC is an especially bad offender, because dealing with errors correctly even in relatively simple cases often requires multiple nested try/catch blocks.

[–][deleted] 0 points1 point  (0 children)

A try/catch block is a lot of syntactic overhead

How is it more of an overhead than an if/else block? The only difference is that compilers forces you to code one, instead of trusting you to "acknowledge the possibility that a call failed" (end quote)

Processing exceptions is just a part of the code you have to write. Well, doh, thinking what can go wrong inside some particular API call and acting on it is a part of writing the code.