5 ms·
Great error handling? What does that mean? Checked exceptions seem cool at first, but are really just nonsense… as your only real way of dealing with this is:
by dfee 5y ago
Great error handling? What does that mean? Checked exceptions seem cool at first, but are really just nonsense… as your only real way of dealing with this is:
1. Catch, log and rethrow, or
2. Wrap as a runtime exception (so you don’t have to change every method signature up to main())
Sure, there’s option 3: catch and handle… but this is used 1/50 times, and the ergonomics of (2) overwhelm the utility of this.
BTW, vavr is nice. Just, “run it all” and optimize for the golden path. If there’s an error account for it locally.
- junon 5y agoWas referring more to structured stack traces. You're able to shoot yourself in the foot in any language's error handling system - quite trivially at that.
- dfee 5y agoBut the problem is that checked exceptions create the same “what color is your function” problem for errors.
- simion314 5y ago>But the problem is that checked exceptions create the same “what color is your function” problem for errors. Compared to "SEGFAULT at 0x000000 in some xxx.dll" having to handle exception and having readable stack traces is a productivity win.
- vips7L 5y agoNo one really uses checked exceptions. But I agree they suck, IOException is the bane of my existence. It's the #1 reason why I don't like Rust or Go. Checking errors is dreadful.
- pkolaczk 5y ago> Checking errors is dreadful. That's true, but that doesn't mean we should pretend the problem does not exist. Using unchecked exceptions is sweeping things under the carpet. Generally unchecked exceptions should be used only for bugs (array index out of bounds) or unrecoverable situations (JVM crash, no memory). I/O does not belong there.
- pkolaczk 5y agoThat's not the real problem with checked exceptions in Java. You actually have the same problem with any result type in a language with static types and mandatory explicit types in function signatures - you change one type and you have to adjust the callers, sometimes many levels above. This is just life ;) One of biggest troubles with checked exceptions is that in Java it is impossible to generify them the same way you can do with argument and return types. You can't write a generic filter or map function that throws the same checked exceptions as the lambda (or any other interface object) that gets passed as an argument. This makes it impossible to use code that throws checked exceptions in some contexts and forces developers to wrap them in RuntimeException. And because those situations are extremely common these days, especially after some FP techniques influenced how Java code is being written, almost noone uses checked exceptions and you typically get runtime exceptions flying around the whole codebase. Which are even worse - they turn very quickly into an unmaintainable mess - because now any function can throw just anything at any time, and that's not even explicitly visible. And here we get to the next big problem with exceptions (not just checked exceptions): they add a high number of alternative control flows you need to analyze in addition to the main "happy path" of the program. An exception can happen anywhere and it might leave the data in incorrect, partially updated state. In reality many devs simply pretend the problem doesn't exist, and they check the happy path only. In languages with no exceptions, a function can exit only by an explicit return - and that is way more readable and easier to analyze. And the last thing which seems to be more a cultural problem, rather than a Java problem, is that somehow most Java programs communicate typical, expected problems with ugly and mostly useless exception stacktraces. Can't connect to a host? I get a stacktrace. File not found? Two screens of stacktraces... That's IMHO a terrible approach to error handling. As a user I am totally uninterested in what code was being executed when something failed (that should be reported only for bugs so the developers can fix). I'm interested in getting a human-readable message with context helping me understand what went wrong and how to fix it.
- sabageti 5y agoIt isn't? You have a function red that doesn't throws anything you use a function blue that throws checked exceptions you handle the exception and it's all. The red functions doesn't become blue.
- dfee 5y agoif the "red" function isn't successful, than you're mapping that error to what? a RuntimeException? great – you've now escaped the indirection with the original solution – just use RuntimeExceptions. map it to another checked exception and you now have a "blue" function. and, you also have another layer of abstraction in your errors. if you can't actually handle the error, skip the circus and just let the exception propagate to a general error boundary (alongside all those RuntimeExceptions you're unaware of). It's a deep ocean, your defense mechanism of guarding against Checked Exceptions is a small fraction of all exceptions. To be fair, I did really like the idea of checked functions when I first started using Java. But in practice, it's just too hard to tell what operations should be Checked / Unchecked (sometimes).
- pritambarhate 5y ago>> 1. Catch, log This is not as useless as it sounds. You can analyse the logs and find out why these exceptions are occurring. A lot of times these lead you to subtle bugs which you might not have noticed otherwise.
- dfee 5y agosure. or if using something like Vavr... catch a bunch of 'em all at once. ``` Try.success(foo. .map(...) .mapTry(...) .map(...) .mapTry(...) .onFailure(e -> LOGGER.warn("Failed %s", e) .get() ```
- Slartie 5y agoAnyone not seriously considering option 3 as the default, with options 1 and 2 being the exception that one must have good reason to take, automatically disqualifies himself as ignorant of proper error handling. Of course you catch and handle errors. Or at the very least you must think about whether it makes sense to handle an error on the current abstraction level that you are on, which means you must always consider option 3. Only if you decide that it's not possible or doesn't make sense to handle it ("I am too lazy" is not a reason to not handle it!) you decide whether you need to throw it one level up the stack. And if doing that is the sensible thing, you think about whether you want to make the exception part of the API of whatever you currently write or not. If you want to, you throw the exception without doing anything (most of the time you don't even log it, because you understand that the receiver at the end, the one who finally handles it, is responsible of logging it, otherwise you get multiple logs of the same exception written out just because someone sprinkled logging into several abstraction layers). If you want to hide the exception type somehow, you wrap it in a more fitting exception that's explicitly or implicitly part of the API of whatever you're writing, and throw that one. That can, but doesn't have to be, a runtime exception. I really don't get what's so hard about exception handling. Java's exceptions are a pretty good analog to how one must model proper error handling in multi-layered software applications anyway, regardless of the programming model used to implement it.
- isbvhodnvemrwvn 5y agoBy your opinion 90%+ of Java ecosystem is ignorant of proper error handling, which in itself is a statement on how poorly this method of error handling is looked at.
- Slartie 5y agoI have seen quite a bit of code in the Java ecosystem over more than 15 years, but far less than 90% of it. And even in the small slice that I've seen, I'd say the quota of ignorant error handling is way lower than 90%. Especially the higher-quality Java libraries that people reuse over and over usually behave okay with regard to exception handling nowadays.
- 5y ago
- ahtihn 5y agoOkay,so what's a better way to do error handling? Returning an Either<Result, Error> is pretty much the same thing conceptually. Either you propagate the error or you handle it.
- dfee 5y agoI'm just suggesting that Checked Exceptions aren't well enough adopted and there's grey area between what constitutes a checked / unchecked exception. I have no problem with Either<Error, Result> though.