Live data from Hacker News

Unchecked Java: Say goodbye to checked exceptions

github.com

281–290 of 297 posts

Re: Unchecked Java: Say goodbye to checked exceptions

#281
post #259

Earlier quoted context omitted.

I think the issue is with checked exceptions as a solution to how to declare this signature, or at least with how they are designed in Java: if you add a new exception to the signature, every downstream call site needs to change, recursively. This means it is impossible to add new exceptions to library methods without breakage, and even in your own code it may mean hundreds of changes throughout your code to add a ne…

> This means it is impossible to add new exceptions to library methods without breakage That’s a feature, not a bug. If it wouldn’t, an exception of that kind could bubble up at a place you didn’t expect. Also, it doesn’t require that many changes, it only has to be changed up to the point where you intend handling it. I don’t see how rust would be immune to that. Though it is true that polymorphism with respect to c…

> If it wouldn’t, an exception of that kind could bubble up at a place you didn’t expect.

You should always be able to handle an unknown exception. Sure you can't do much about it, but it shouldn't be a big deal. An exception only occurs if the code can't continue as expected.

Libraries are supposed to be a point of abstraction. They should be allowed to change their implementation fundamentally as long as they continue to respect the same interface. Exceptions should not be part of the interface explicitly because are they implementation-detail related.

Re: Unchecked Java: Say goodbye to checked exceptions

#282

Earlier quoted context omitted.

> One of the biggest flaws in C#, in my experience, is lack of checked exceptions. I couldn't disagree more. Checked exceptions in Java have ruined a generation of programmers. The truth is, under checked exceptions, to satisfy the compiler the function that you called would declare that it throws a SomeModuleException and the programmer who wrote that function would put all his code in try/catch block that catches a…

From a type theory perspective, an exception is another type of return value that a function can have, and not documenting those in the function signature is absurd. I have seen libraries that make network calls that do the following: * Throw an exception on certain types of network errors * Return an HTTP error code for other types of network errors * Return an object with error set to true and an error string for o…

From a type theory perspective if you want to track exceptions as return values you want a composable container class (best case, a full monad) so that you aren't writing a lot of ad hoc code every time to handle them.

That's a big problem with Java's checked exceptions, it's not very composable and flow control can just stack up into deeper and deeper "waterfalls" of code rather than simpler pattern matching. (To be fair that's a big problem with exceptions in general as "flow control", they aren't very composable.)

Something like an Either monad in a language with sum types can be a great way to describe errors/exceptions usefully as return types. From a type theory perspective, checked exceptions can be seen as a hack for a language that doesn't support sum types and doesn't have great native monad binding.

Re: Unchecked Java: Say goodbye to checked exceptions

#283

Earlier quoted context omitted.

> And I guess this is precisely why so many developers hate them; they don't like the extra work they have to do to catch all those edge conditions I hate checked exceptions when they force me to handle an exception which I know is impossible given the arguments passed to the method. For example, some older Java APIs take an encoding name and force you to handle the checked UnsupportedEncodingException - even when th…

> I hate checked exceptions when they force me to handle an exception which I know is impossible given the arguments passed to the method. If I want to ignore a set of exceptions, I have the option to catch(Exception e) {} signaling that I recognize the risks that have been explicitly communicated by the API (that throws). An @IgnoreExceptions annotation would help dump the 5? boilerplate lines. The unknown risks for…

I've seen checked exceptions cause numerous bugs. Why? Because they encourage you to put catch clauses everywhere, and a lot of developers don't know how to write them properly (and even the best developers sometimes make mistakes that slip through the cracks). A common result of this is that a bug causes an exception, but the catch clause loses information about the original exception (such as by logging it without the stack trace, or throwing a new exception without setting the cause). Or else the catch clause just ignores the exception, and then you get some other error later (e.g. NPE because some field was unexpectedly null), but again you've lost the info on what the root cause problem is. If your code base contains 100s of catch clauses, that's 100s of opportunities for buggy catch clauses to exist. And even if you eradicate them all from your own code base, then you might get hit by one buried in a third party library.

Without checked exceptions, you end up with far fewer catch clauses, and hence far fewer opportunities for buggy catch clauses. I think in most apps, most of the time, you just want to bubble all exceptions up to a central point which handles them – for example, in a web server, you can have a single catch clause for the whole HTTP request. If need be, you can make that central point extensible with custom handling with specific exceptions (like JAX-RS ExceptionMapper, or @ExceptionHandler beans in Spring – which you can then inject using IoC/DI). Once you've got that working, if you need catch clauses deeper in the code (e.g to return an error code to the frontend when the client sends bad data instead of just failing the request with a `NumberFormatException`), you can add them where appropriate – but unlike checked exceptions, you aren't forced to add them where you don't need them.

Re: Unchecked Java: Say goodbye to checked exceptions

#284
post #261

Earlier quoted context omitted.

A person can also accidentally break it - by adding some new code which contains a bug which causes an unchecked exception or error to be thrown (e.g. NullPointerException, ArrayIndexOutOfBoundsException, StackOverflowError, etc). Checked exceptions do nothing to protect against those kinds of mistakes, which in my personal experience are vastly more common than whatever mistakes for which they may provide some prote…

Everything can fail at every time — that’s part of the art of programming to discern which error conditions are meaningful to be included in the signature, and which are not.

> Everything can fail at every time — that’s part of the art of programming to discern which error conditions are meaningful to be included in the signature, and which are not.

But that's a major flaw with checked exceptions – very often, whether an error is recoverable or not depends, not on the API itself, rather on how it is used. Yet checked exceptions force the API designer to make that decision while designing the API, when they can only guess at how it will be used.

A good example of this is FileNotFoundException – whether that is a recoverable error which ought to be handled, or whether there is nothing better to do than crash, depends on what the file is. If we are implementing a File Open dialog box in a GUI app – okay, we better catch the FileNotFoundException and display an error box, not just crash. But, suppose I am writing a micro-service, and the first thing it does on startup is read its config file, and the config file isn't there: is there any point in trying to handle that exception, or should it just crash? Obviously the designers of Java's file IO classes had the first scenario in mind more than the second, but it is an inherent flaw of checked exceptions that they forced them to make this decision at all.

Re: Unchecked Java: Say goodbye to checked exceptions

#285
post #259

Earlier quoted context omitted.

I think the issue is with checked exceptions as a solution to how to declare this signature, or at least with how they are designed in Java: if you add a new exception to the signature, every downstream call site needs to change, recursively. This means it is impossible to add new exceptions to library methods without breakage, and even in your own code it may mean hundreds of changes throughout your code to add a ne…

> This means it is impossible to add new exceptions to library methods without breakage That’s a feature, not a bug. If it wouldn’t, an exception of that kind could bubble up at a place you didn’t expect. Also, it doesn’t require that many changes, it only has to be changed up to the point where you intend handling it. I don’t see how rust would be immune to that. Though it is true that polymorphism with respect to c…

If you don't control the code where the superclass or interface is defined then you're stuck. You can't change that code even if it would be only a tiny edit. Checked exceptions are absolutely not a "feature".

Re: Unchecked Java: Say goodbye to checked exceptions

#286

Earlier quoted context omitted.

And do what with it? If you don't know what it really is, the best thing is to let things fail fast and the standard logging to kick in and record all the details of the crash.

Depends on what you are doing. If I’m processing a monthly report for millions of customers, I don’t want to abort processing after running into one problem customer. I want to continue to process the rest of them, and log the problem customers exception for troubleshooting and analysis offline.

Depending on what actually happened, that could be disastrous and result in data corruption or account reconciliation failures or worse. It often would be safer to go ahead and fail even in that circumstance.

Re: Unchecked Java: Say goodbye to checked exceptions

#287

One of the biggest flaws in C#, in my experience, is lack of checked exceptions. As an example, I wrote some very good code, carefully tested it, made it work flawlessly, then suddenly it started crashing. What happened? Someone made a change in a function I was calling, and it started throwing a new exception. This would have caused a compile error in Java, not a crash. More on checked vs unchecked exceptions here:…

In Rust instead of throwing, you have results that can be either successful or errors. And it is all type safe and fast.

Re: Unchecked Java: Say goodbye to checked exceptions

#288
post #117

Earlier quoted context omitted.

Lets be honest. The more likely thing is that either the coworker would use an unchecked exception or that they would change the callsite to: try { theUpdatedFunction(); } catch (MyNewCheckedException e) { logger.warn("Whoopsie doopsie", e) throw new SomeUncheckedException("Something failed, idk", e) } Which really is a zero sum game. The code still breaks the same way, but the checked exception gets eventually wrapp…

Let's be really honest try { theUpdatedFunction(); } catch (MyNewCheckedException e) { logger.warn("Whoopsie doopsie", e); throw new SomeUncheckedException(e.message); } There's a special place in Hell for these people, but at least they'll get to see all of their friends again.

Oooo, lookit you working with professionals; I've seen waaaaaaay too many instances of this shit

  try {
    somethingImportant();
  } catch (Exception e) {
    // can't happen
  }
IJ finally started chirping about this other anti-pattern

  try {
    doit();
  } catch (Exception e) {
    System.err.println("something didn't work");
    // failure to reference "e" is now a yellowbox
  }
I have to constantly ask for them to either log it, or rename the variable to `ignored` to get IJ and future readers on the same page that it was intentionally swallowed

Re: Unchecked Java: Say goodbye to checked exceptions

#289
post #190

Earlier quoted context omitted.

stream.filter(p) requires wrapping checked exceptions in p, or altering the language so that they’re no longer checked. Same with Runnable.

or you start doing monads instead, where p operates on a monad (aka, the Optional type). Unfortunately, this ends up propagating out and your entire code base needs to also do this. Tho i reckon it will make your code better in the future, for a short term/temporary pain converting/adding breaking changes etc.

Yeah, switching to Scala or Kotlin would be the shortest path to do that.

Re: Unchecked Java: Say goodbye to checked exceptions

#290
post #165

Earlier quoted context omitted.

Exception based error handling is unsafe when they are unchecked exceptions. Checked exceptions however are as safe as Either, Try, Monads, Applicatives or whatever. You are forced to declare them in your method signature, the caller is forced to either handle them or rethrow them + declare them as well. And I guess this is precisely why so many developers hate them; they don't like the extra work they have to do to…

Checked (and unchecked) exceptions create an exponential number of control flow paths. Consider: try { throws_a(); r = grab_resource(); throws_b(); r.throws_a(); } catch (a) { r.release(); // oops; null pointer some times } catch (b) { try { r.release(); } catch (a) { // nooo.... } } finally { if r != null { r.finalize() // use after release (sometimes) r.release() // ??? } } There is plenty of academic literature sh…

The construction of arbitrary convolutions of logic is not demonstrative of your assertions. A multitude of code paths is not specific to checked exceptions. Note: It is possible to try catch a union of exception types in the recent versions of Java (catch X | Y | Z).

The paths are still there if the exceptions are all unchecked or combined or not using exceptions at all. Passing exceptions up is rarely the right choice, imo. If it's a terminal runtime, sure, obv.

Post reply on HN