4 ms·
Exceptions are bad and languages using them should feel bad. Go and Rust got it right, it is a major reason why Rust code Just Works. Yet some Rust folks are mo
by MrBuddyCasino 6y ago
Exceptions are bad and languages using them should feel bad. Go and Rust got it right, it is a major reason why Rust code Just Works. Yet some Rust folks are moving towards exceptions, and I find it unsettling.
- matsemann 6y agoExceptions are nice and languages without them should feel bad. Your comment is a pretty useless blanket statement. At least invite some discussion by coming with a few arguments..
- evilsetg 6y agoWhat is bad about exceptions?
- brobinson 6y agoThey will be used for flow control in small, individually innocent ways until they've accumulated into the type of hell the OP of this thread is describing.
- phoe-krk 6y agoA solution is to use languages that make explicit control flow available, instead of pretending that exceptions are a good way of performing non-local jumps. Have you investigated Common Lisp, its use of BLOCK/RETURN-FROM and TAGBODY/GO, and how it is possible to close over these lexical constructs to achieve non-local jumps to predefined points on the stack ? All of Common Lisp's error handling system is based on this primitive mechanism (and therefore written in Lisp itself). (Disclosure: wrote a book on the topic.)
- kettro 6y agoExceptions form a secondary, unseen form of control flow. A program can exit via ‘return’ calls (as normal), or at any time by some internal function way down the stack throwing an exception for something that could have been an error code. Exceptions are not Structured Programming: they are worse than goto, because at least goto is scope-local. If, maybe, the language enforced that all throwable exceptions are declared by the prototype, then it’d be alright. But I don’t know of any that do. So, given a function call, will it error out? Can you know without inspecting the source, if you even have it?
- MrBuddyCasino 6y ago> they are worse than goto, because at least goto is scope-local Thanks, you said it better than me. This is the essence.
- josefx 6y agoSo Go got it right by calling it panic/recover instead of throw/catch? Should we petition other languages to also change the keywords and correct whatever is wrong with throw/catch? Is Pythons raise/except safe or did they miss it when they cleaned up the master/slave mess?
- yati 6y agoPanic/recover isn't used nearly as much for error handling in Go as in Java. An online resource being unreachable does not cause the net package functions to panic.
- knorker 6y agoUsed or not, they ARE exceptions, and you need to write exception-safe code. fmt.Print can throw. And HTTP handlers throwing exceptions is silently hidden. If you don't write code assuming anything can throw, then your code is broken. And don't judge exception by how they are in Java. That's just a clusterfuck. No other language I'm aware of gets exceptions so wrong.
- makapuf 6y agoPanics Are exceptions but they should be seen as a fatal error. It is very discouraged from being used and the official doc insists that you should not use them for error handling. Qualifying a feature as exceptional use does count, just as having goto in C++ (and go) is possible but should be (and is) generally avoided should impact your perception of c++.
- knorker 6y ago> Panics Are exceptions but they should be seen as a fatal error. I agree. Well, "fatal" needs to be defined. If an HTTP handler throws an exception, is that fatal for the whole webserver? Java seems crazy about this. Exceptions seems like it's being treated as just another return value. And that leads to a mess. But C++? What parts of the C++ standard library have unreasonable exceptions used for errors? (there may be some, I just can't think of any) And note that you have to throw (no pun intended) away large parts of the language if you remove exceptions. E.g. you can't have constructors without exceptions. How else would you signify "those arguments you gave to the constructor are no bueno". Go doesn't have constructors, so it's consistent with what it says. Also see my comment here, about how common or not, discouraged or not, the mere existence of exceptions in a language changes how you must write code to not have it be buggy: https://news.ycombinator.com/item?id=25275580 https://news.ycombinator.com/item?id=25275580 Yes, in C++ 'goto' is a code smell. It's not in C (greatly used for error handling), but C++ has RAII so `goto` should be rare outside of "clever" code (where "clever" is rarely good). The mere fact that C++ doesn't have 'finally', and Java does, tells you a lot about how exceptions and RAII differs. If you write a macro for "finally" in C++ then you're doing it wrong. Pretty much all of my `catch` clauses are in main() (or the root of an event handler), to pretty print the error and/or log to central service, or in a top level event like HTTP handler. `catch` should be about as common in C++ as `rescue` is in Go. In Java it's fucking everywhere.
- KronisLV 6y agoI'd argue that Exceptions are good, because they attempt to illustrate all the ways code can go wrong and because you typically need to be at least aware that you're ignoring them. However, i'd argue for allowing no unchecked exceptions at all that can be thrown at runtime and instead forcing developers to handle every fail state, that can be encountered in the code that they call. If a method that you call can fail in 60 different ways, you should at least handle the 20 of them that you understand in their own ways and the rest in a blanket statement. All of that should be checked at compile-time, of course. Java, .NET and most other ecosystems (both languages and frameworks) don't really seem to want to bother with that, though.
- heavenlyblue 6y agoIs there a language that has optional checked exceptions? Basically if I define a checked exception function then I am expected to check all exceptions that will be thrown?
- MrBuddyCasino 6y agoIn Java there is Exception (checked) and RuntimeException (unchecked). Depending on which base class you use, the compiler will force you to handle them or not.
- MrBuddyCasino 6y agoOne of the problems with exceptions is that they bubble up the call stack, and then you've got layering violations: higher level modules should never depend on lower level modules. The "checked exceptions were a failure" meme goes towards this direction, it results either in nasty boilerplate because you've got to handle and re-wrap the implementation-specific exception in something more general to avoid leaking things that should have been hidden (like Hibernate does), or unsound error handling. Maybe the solution to that is 1. Only allow checked exceptions, and force error handling. 2. Only have 2-3 exception types, not user-extendable: Retryable, Unrecoverable, and Error (for non-user code errors like OOM). OTOH, how to distinguish between different exceptions thrown by the same method, and how to add additional error information (like status_code) would become a problem. Javascript doesn't seem to care tho? A Result type à la Rust solves most of that: you might still have to wrap lower layers, but at least the noise & syntax is much more sane (never thought I'd say that about Rust!).
- knorker 6y agoGo has exceptions, though. Unwind stack, calling cleanup functions in frames that need them, until caught higher up the stacks. Yah, that's exceptions.
- MrBuddyCasino 6y agoThis is insincere. Rust can unwind too, but as in Go, this not the usual error handling mechanism.
- knorker 6y agoI haven't learned Rust yet, but no it's not insincere. Go has a textbook definition of exceptions. The mere fact that they are less used doesn't make them "not exceptions". And importantly it doesn't matter that they are less common. Merely having exceptions means that everyone has to write exception-safe code. HTTP handlers silently swallow exceptions, so you can't rely on your program dying if there's a panic. fmt.Printf can panic as far as you know, too. Essentially you need RAII, except that because Go doesn't have RAII every single resource needs: r, err := getResource() if err != nil { … } defer r.Close() But because "Go doesn't have exceptions" people often don't bother with the defer, and then they get bugs. I see it happening frequently. You need to write exception-safe code. But also you're not allowed to use exceptions. So it's the worst of both worlds. I write and review a lot of Go code, and I like the language. But I don't like the dishonesty.
- MrBuddyCasino 6y ago> You need to write exception-safe code. But also you're not allowed to use exceptions. So it's the worst of both worlds. I wasn't aware that this is a real problem in Go land, thanks for the explanation. I wouldn't say the language is "great", was just using it as an example of a modern language where there is a consensus that "they got it right" and not using exceptions, even though error handling is still tedious right now. I think in Rust you have to consciously fuck up the panic handler to cause similar issues, but I'm not sure.
- CuriouslyC 6y agoThere are times that exceptions work really well, I think the problem isn't so much that they exist, as they're too often used wrong. Getting an exception due to a real error is nice, getting them as a generic flow control device, not so much.
- apta 6y agogolang definitely did not get it right. golang errors are error prone, I've seen several cases in production code where they were either accidentally ignored or overwritten. Makes it terrible for writing safe software.