3 ms·
Will people keep writing these annoying posts with no insight just to complain about Exceptions (and Java in general)? I've done a lot of Java. And quite a bit
by brabel 2y ago
Will people keep writing these annoying posts with no insight just to complain about Exceptions (and Java in general)?
I've done a lot of Java. And quite a bit of Rust too. The least thing (or close to it) that annoys me with Java is Java's error handling. It only really makes me upset when a lambda needs to call some method that has a checked Exception in its signature, usually because it does IO... yeah that's annoying... but I still get the job done without losing more than 30 seconds. Otherwise, I just make a decision on whether to handle errors locally or propagate them, and that's all there's to it.
Rust is nice and all. But the kind of annoyance I get with Result values are probably worse than is the case in Java with Exceptions. For example, as mentioned in the article, when you end up having multiple incompatible errors and you have to manually hack something, usually losing context, to make the compiler happy. Almost every project just adds yet another dependency on one of the error handling libraries (because this problem and similar ones, like losing the stack trace entirely, are all too common so there's lots of libraries to fix that) and you probably will end up with all of them in your project once you've written anything non-trivial.
The problem with API changes in Java are real, but the same exact issue exists in Rust: you inevitably have to end up adding new error scenarios as you add features to a library. Instead of a new Exception, you just end up with a new Error variant in Result.
Anyway, even though in the beginning I also got all euphoric with Rust, thinking it fixed every issue with every language, today I think it just shifted the sorts of problems you have to deal with. It definitely went in the right direction (specially with handling of closable resources and concurrency) and it's a better language in almost every way than Java and most languages. But sorry, with regards to error handling, it's a minor improvement at best.
- mrkeen 2y ago> it's a better language in almost every way than Java > with regards to error handling, it's a minor improvement Then let's keep pouring out these articles until we stop using a language that's worse in almost every way than Rust (and error handling that's a little bit worse).
- brabel 2y agoIt shouldn't be an objective to stop using any language. There's lots of people who like Java (or whatever language you don't like) and they're happy with that. It does the job, it gets them what they want. Rust perhaps does not and never will. It's not our job to tell people they need to stop doing whatever they're doing unless what they're doing is causing trouble for everyone else, which you'll have a hard time arguing is the case here (a better case, I think, could be to convince people to stop using C and C++ because of the real dangers of lacking memory safety?! But I am sure lots of C user would respond the same way I am doing here about Java :D).
- Expurple 2y ago> Will people keep writing these annoying posts with no insight just to complain about Exceptions (and Java in general)? I'm sorry if the post comes off like that. This wasn't intended. Originally, I was writing a post explaining why I like using Rust as a high-level language for non-demanding tasks. I'm really excited about its error handling, so the section about error hanling got so large that I had to extract it into a separate post. And then also had to artificially limit its scope to exceptions and first-party solutions. And then hyperlinked everything to prevent bloat from inlined code examples for every single point. The post wasn't even intended to be about exceptions :) I brought in Java specifically to cover checked exceptions and avoid responses like "all of this in solved with checked exceptions, Result is the same thing". Now, I think that the part where I define a Result in Java was a bit unfair and too-specific, because other languages with exceptions sometimes provide a standard Result type. > the kind of annoyance I get with Result values are probably worse than is the case in Java with Exceptions In the end, this is a subjective judgement call that everyone makes based on their own experience. My experience doesn't match yours here. But I tried my best to be objective and list these disadvantages so that readers can make their own conclusions based on the information. > The problem with API changes in Java are real, but the same exact issue exists in Rust: you inevitably have to end up adding new error scenarios as you add features to a library. Instead of a new Exception, you just end up with a new Error variant in Result. It exists, but Rust allows you to solve it my marking this error #[non-exhaustive] early in the evolution of the library. I don't know an equivalent in Java that simultaneously: 1. preserves concrete types 2. allows to evolve the API 3. forces the caller to handle unknown future variants. > Anyway, even though in the beginning I also got all euphoric with Rust, thinking it fixed every issue with every language, today I think it just shifted the sorts of problems you have to deal with. Sure. I did my best to describe this shift. And then made a subjective judgement about it. I respect yours too.
- brabel 2y agoThanks for the reply. I know my comment was very blunt, and didn't mean to cause offence - hope you didn't take any. The reason I responded like that was that I really disagree with many Rust users who keep saying Rust error handling is so much better in every way and that Exceptions are stupid and stuff like that... and I was responding to those kind of people, not really you as your post was well balanced. > In the end, this is a subjective judgement call that everyone makes based on their own experience. My experience doesn't match yours here. Absolutely. Subjective topics can still be discussed, but yeah we're very unlikely to all agree, ever. > I don't know an equivalent in Java that simultaneously... Well, the way you do it in Java is using OOP: basically, have a single Exception type at the root of the Exception type hierarchy and make your library only throw sub-types of that. Then you may handle specializations of that, but you need to also handle the root type in case an unknown variant comes along. That leaves your last point unaddressed, but you can either make the root type a sealed interface, or have an enum describing all cases, so that the caller can opt-in to have their code break if they fail to handle one of the cases in the future.