Live data from Hacker News

Why checked exceptions failed

borretti.me

131–140 of 318 posts

Re: Why checked exceptions failed

#131
post #103

Yeah. The thing is, I like the idea of checked exceptions. You could go ahead and define a number of error situations or error kinds and annotate methods with these checked exceptions to force applications to handle these errors. Like, you have a Database.query function and it might throw different exceptions - ConnectionInterrupted, QueryPreparationFailed, QueryFailed, TransactionCancelled. And then you could catch…

> This however runs into issues. One really annoying one: Checked exceptions are part of your API. If you forget an error condition and want to introduce a new exception for that, well guess what, that's a breaking API change. There is no easy way to evolve an API with checked exceptions, because changing them requires new major versions, because it prevents code from compiling. This sounds like a good thing. Throwin…

That's not true in java.

You can gradually increase the granularity of unchecked exceptions using subtypes. For example I might initally have AnythingFailedDuringTheQueryException with a Subtype of QueryPreparationException. If I introduce new subclasses of QueryPreparationException to increase the precision of the error reporting, all existing catches for QueryPreparationException will still function as they did before. A "NotEnoughParametersException" subclass of a QueryPreparationError is still caught as a QueryPreparationError. Only if you introduce catches for the new more granular unchecked exception, your codes behavior changes to use the new behavior.

That's a very clean way to improve error reporting in a backwards compatible way.

Re: Why checked exceptions failed

#132
post #66

Earlier quoted context omitted.

I stopped using Java a long time ago, and so I assume the language has gotten better since then, but early on at least it felt like Java almost took pride in making the developer jump through extra hoops. Compared to many other languages, using Java just made me feel tired. Checked exceptions - a feature that seems to be a cost to the developer 100% of the time while being a benefit far less than 1% of the time - is…

Some people say the same about strong typing. Like, why do I have to write down the type of every single parameter or variable? Java is making me jump through hoops! The point is, if you don't need the rigor of a strongly typed compiled language, there are other languages you can use. Perhaps a bash script is all you need.

If checked exceptions were implemented in such a way that they were inferred, and they weren't erased in the byte code, much like how people use strong types now, they wouldn't be seen as hoops. Meaning, if you didn't explicitly handle a checked exception, it would automatically bubble up yet be visible to your IDE.

I would love if, at design time, all the possible exceptions that could happen were able to be inferred. But, the way it happens in java, it's entirely manual, and it won't catch things where I'm referencing compiled code. The design of checked exceptions in Java lead to all kinds of exception anti-patterns becoming common, just to shut up javac.

Re: Why checked exceptions failed

#133
post #106

Earlier quoted context omitted.

> infuriating that try{} opens up a new lexical scope This slays me. The try, catch, and finally blocks should be just one lexical scope.

I don't think that helps? If, as is kind of the point of RAII, your constructors do some initialization and that initialization may fail, then: If you have a single object that may fail to construct then maintaining it in scope for the catch block doesn't make sense; it's not initialized. If you have several, then you still can't maintain them in scope, because you don't know which ones are actually valid. Yes there…

I misspoke.

Ignoring the syntax for a moment, I want scoping to behave like this pseudo-code. So that the catch and finally blocks are lexically nested within the parent try block.

  try {

    OutputStream out = ...

    ...

  // Must be at end of try block
  catch ExceptionA, Exception B { ... }

  catch Exception C { ... }

  finally { ... }
    

  } // end of try

Maybe even allow catch and finally to allow single expression in addition to blocks. Just like with if/then/else.

Re: Why checked exceptions failed

#134

Earlier quoted context omitted.

That is not better code. Couple of try-catch-catch-catch-...-catch cases in a function that would otherwise be 2-3 lines long makes for an awful code. Also, imagine a situation when an iterator throws an exception. Or you wanted to write f(g()) but now you can't and have to do: try: T t = g(); catch E1: ... catch En: ... f(t); Now it takes a much greater effort for the reader to figure out what's going on. It's also…

This is only because you use exceptions incorrectly. You can (and should) write: try { final var fResult = f(g()); //do something with fResult } catch (E1 e) {...} catch (En e) {...} That's the main idea of exceptions in all languages: main flow is kept together and exceptional flows are separate.

I think there’s a strong assumption in this pattern that can and should be handled immediately and that there is a recovery path from the failure, if there is no recovery path and you’re just propagating the error this pattern becomes an awfully verbose return statement.

Re: Why checked exceptions failed

#135

Earlier quoted context omitted.

From your OC: > Null is fast. Super fast. Literally free. Yes and: The JIT will optimize away Null Object method invocations. All my composable classes have a Null Object. No null checks means concise iteration (eg graph traversal). Eliminates NPEs. Just as fast. Win / win / win. Optionals (classes and operators) continue to be turrible mistakes. So much unnecessary effort, so little benefit. Ditto @Nullable and @Non…

It seems like when one is implementing Null Objects and making incomplete attempts to prevent values from ever being null it is not really an argument in favor of nullable values being good and the only type of values that should be present in a language.

I'm not smart enough to parse this. Try again?

Re: Why checked exceptions failed

#136

My opinion is the exact opposite see https://debugagent.com/everything-bad-in-java-is-good-for-yo... Checked exceptions are unpopular since no one likes responsibility. But they are great when used right. Calls that must have proper cleanup after them e.g. SQL, IO are checked. The fact that this must be communicated via interfaces is hugely important. There are "weird" problems such as stream close() throwing a check…

This comes from a misunderstanding of the reason why exceptions where designed they way they were. The whole point of exceptions bubbling up w/o having to write support code to deal with passing exceptions further is to make it so that the purpose of the function is clear to the reader.

Go's exceptions have the same unfortunate property as Java's checked exception. And that's what makes Go's code atrocious. Every other line you see something like:

    if x, e := f(); e != nil {
        ...
    } else {
        return y, e
    }
It makes it very easy to make mistakes when you have to write a lot of repetitive code. You make typos, and because they often land on the "bad" path, they aren't immediately discovered. You have to memorize the state of your function wrt' variable initialization, because now you cannot automatically initialize and destroy them all together. You need to create a lot of helper variables whose purpose is only to transfer return value from one function to another...

If you think that you want checked exceptions, then you don't want exceptions at all. You are denying them the very purpose they were created for. But there are alternative ways to deal with unexpected events in program execution. Monads would be one of those. So... maybe just don't use exceptions?

Re: Why checked exceptions failed

#137
Checked exceptions failed in Java because they don't play well with parametric polymorphism. Union types might help (exception list declaration is actually a union type) but I don't think it would succeed anyway as it is not general enough.

Handling effects and effect polymorphism in programming languages is an active area of research and there are some new languages that try to approach the problem (ie. Koka).

Haskell has several effect libraries (effectful, cleff, eff, polysemy) that look quite nice.

Idris with its dependent types allows precise definition of effects in function signatures.

Re: Why checked exceptions failed

#138

My opinion is the exact opposite see https://debugagent.com/everything-bad-in-java-is-good-for-yo... Checked exceptions are unpopular since no one likes responsibility. But they are great when used right. Calls that must have proper cleanup after them e.g. SQL, IO are checked. The fact that this must be communicated via interfaces is hugely important. There are "weird" problems such as stream close() throwing a check…

This comes from a misunderstanding of the reason why exceptions where designed they way they were. The whole point of exceptions bubbling up w/o having to write support code to deal with passing exceptions further is to make it so that the purpose of the function is clear to the reader. Go's exceptions have the same unfortunate property as Java's checked exception. And that's what makes Go's code atrocious. Every oth…

No. This comes from a misunderstanding of checked exceptions.

Checked exceptions don't mean I need to handle the exception right now. They mean I need to either do that or declare throws. Declaring throws is fine it implicitly documents the code and enforces a similar requirement up the chain.

Checked exceptions aren't the default and shouldn't be.

Re: Why checked exceptions failed

#139

Earlier quoted context omitted.

It seems like when one is implementing Null Objects and making incomplete attempts to prevent values from ever being null it is not really an argument in favor of nullable values being good and the only type of values that should be present in a language.

I'm not smart enough to parse this. Try again?

"All non-primitive values are nullable references" is a feature of the language. You posted that you are trying to avoid using that feature (instead using non-null references to a special Null value?) and trying to avoid having null references for the types you create. It seems like you do not actually think the feature is a good feature.

Re: Why checked exceptions failed

#140
post #30

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.

> Catching the root exception is not a bad idea. If you had caught the new exception what would you have done with it? Something relevant to the error condition, probably? There may be some cases where the total set of possible errors is too large to meaningfully handle every one of them specifically (for instance if you call a high level GPU initialization routine that can fail in a myriad of ways) but that's not tr…

Realistically speaking, you should essentially never try to "handle" errors with tricky program logic: propagate them up (automatic in languages with exceptions) and eventually--in as few places as possible--report them to the user so the user can decide what to do, not the code.
Post reply on HN