8 ms·
Having programmed for over 30 years, including nearly a decade of C#, I would say exceptions are one of the worst ideas in all of programming. They are just ho
by abtinf 2y ago
Having programmed for over 30 years, including nearly a decade of C#, I would say exceptions are one of the worst ideas in all of programming.
They are just horrific gotos that any library can invoke against your code. They are pretty much never, ever handled correctly. And nearly always, after an exception is “handled”, the application is actually in an unknown state and cannot be reasoned about.
Even junior engineers have a trivial time debugging most go errors, while even experienced principles struggle with figuring out the true cause of a Java exception.
- rand_r 2y ago> never handled correctly I’ve seen this argument, but if you look at real golang code and examples, it’s just a bunch of “if err <> nill” copy pasta on every line. It’s true that handling errors is painstaking, but nothing about golang makes that problem easier. It ends up being a manual, poor-man’s stack-trace with no real advantage over an automatically generated one like in Python.
- swiftcoder 2y agoWhich could be solved in one swipe by adding a Result<T, Error> sum type, and a ? operator to the language. This is more a self-inflicted limitation of Go, then a general indictment of explicit error handling.
- rand_r 2y agoNothing prevents explicit error handling in Python either. Forcing explicit error handling just creates verbosity since no system can functionally prevent you from ignoring errors.
- kaoD 2y agoMany people against Go's error handling do not advocate for exceptions, but for a combination of an Either/Result type (for recoverable errors) and fully aborting (for unrecoverable errors).
- OtomotO 2y agoAbort on the other hand is used WAY to liberally in Rust. How I hate it, that every second function call can break my program when it's clearly not a "halt the world, it's totally unrecoverable that the user sent us nonsense" type. Return a Result and get on with your life!
- Chai-T-Rex 2y agoIf a Rust function can panic, there's generally a non-panicking alternative. For example, `Vec` indexing has `vec[n]` as the panicking version and `vec.get(n)` as the version that can return `None` when there's nothing at that index.
- mathw 2y agoI do wish this is something Rust had done better though - the panicking versions often look more attractive and obvious to developers, and that's the wrong way round. Vec indexing, IMO, should return Option<T>.
- sshine 2y agoWhile that is true, there are clippy::indexing_slicing, clippy::string_slice for that: https://github.com/rust-lang/rust-clippy/issues/8184#issuecomment-1003651774 error: indexing may panic --> src/main.rs:100:57 | 100 | rtmp::header::BasicHeader::ID0 => u32::from(buffer[1]) + 64, | ^^^^^^^^^ | = help: consider using `.get(n)` or `.get_mut(n)` instead = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing
- quotemstr 2y agoOne of my dream projects is creating a Rust stdlib based solely on panics for error handling. Sure, it'd be incompatible with everything, but that might be a feature, not a bug.
- pyrale 2y agoException and explicit on-the-spot handling are not the only two ways to handle failing processes. Optional/result types wrapping the are a clean way to let devs handle errors, for instance, and chaining operations on them without handling errors at every step is pretty ergonomic.
- quotemstr 2y agoRust's error handling evolution is hilarious. In the beginning, the language designers threw out exceptions --- mostly, I think, because Go was fashionable at the time. Then, slowly, Rust evolved various forms of syntactic sugar that transformed its explicit error returns into something reminiscent of exceptions. Once every return is a Result, every call a ?, and every error a yeet, what's the difference between your program and one with exceptions except the Result program being syntactically noisy and full of footguns? Better for a language to be exceptional from the start. Most code can fail, so fallibility should be the default. The proper response to failure is usually propagating it up the stack, so that should be the default too. What do you get? Exceptions.
- maleldil 2y ago> what's the difference between your program and one with exceptions Because errors as values are explicit. You're not forced to use ? everywhere; you can still process errors however you like, or return them directly to the calling function so they deal with it. They're not separate control flow like exceptions, and they're not a mess like Go's.
- quotemstr 2y agoNo, because you end up with a function coloring problem that way. A function that returns something other than Result has to either call only infallible code or panic on error, and since something can go wrong in most code, the whole codebase converges as time goes to infinity on having Result everywhere. Yeah, yeah, you can say it's explicit and you can handle it how you want and so on, but the overall effect is just a noisy spelling of exceptions with more runtime overhead and fewer features.
- quotemstr 2y agoHard disagree. Exceptions are actually good. They make code clear and errors hard to ignore. I've written a ton of code over decades in both exceptional and explicit-error languages and I'll take the former every day. There's no function color problem. No syntactic pollution of logic with repetitive error propagation tokens. Also, exception systems usually come with built in stack trace support, "this error caused by this other error" support, debugger integration ("break the first time something goes wrong"), and tons of other useful features. (Common Lisp conditions are even better, but you can't have everything.) You can't just wave the word "goto" around as if it were self-evident that nonlocal flow control is bad. It isn't. > And nearly always, after an exception is “handled”, the application is actually in an unknown state and cannot be reasoned about. That's not been my experience at all. Writing exception safe code is a matter of using your language's TWR/disposable/RAII/etc. facility. A programmer who can't get this right is going to bungle explicit error handling too. Oh, and sum types? Have you read any real world Rust code? Junior developers just add unwrap() until things compile. The result is not only syntactic clutter, but also a program that just panics, which is throwing an exception, the first time something goes wrong. Many junior developers struggle with error handling in general. They'll ignore error codes. They'll unwrap sum types. They might... well, they'll propagate exceptions non-fat ally, because that's the syntactic default, and that's usually the right thing. We have to design languages with misuse in mind.
- OtomotO 2y agoBah, no, I hated that you had to wrap basically every code block in a try/catch in Java, because the underlying lib could change and suddenly throw a Runtime-Exception. At the same time Checked Exceptions were a nightmare as well, because suddenly they were part of the contract, even though maybe wrong later.
- quotemstr 2y agoChecked exceptions are more trouble than they're worth. That doesn't make exceptions in general bad.
- 2y ago
- OtomotO 2y agoBut with Exceptions you can easily implement multiple return types in e.g. Java ;) I shocked my Professor at university with that statement. After I started laughing, he asked me more questions... still went away with a straight A ;D
- Cthulhu_ 2y agoAs you should, it shows a deeper insight in the language beyond the base course material and out of the box (and cursed) thinking.
- sshine 2y agoWhen I took the compiler course at university, the professor would have a new coursework theme every year, and the year I took the course, the coursework compiler was exception-oriented. So exceptions were the only control flow mechanism besides function calls. If/else, while, return were all variations of throw. To me this proved that there's nothing inherently wrong about exceptions. It's how you structure your code and the implied assumptions you share with your colleagues. Some people are way too optimistic about their program will actually do. Happy path programming.
- BoiledCabbage 2y agoSounds interesting - any link to the control flow implementation online? Or how does one optionally throw and exception without an "if" statement? What's the "base" exception call? Ie if "if" is implemented via exceptions, how do exceptions get triggered? And is "while" done via an "if exception" and recursion? Or another way?
- Yoric 2y agoIn OCaml, that's actually a common use for exceptions, as they let you unwind extremely quickly and carry a result (helped by the fact that OCaml doesn't have finally or destructors).
- mike_hearn 2y agoWell, I've also programmed for over thirty years and I wouldn't use a language without exceptions and even wrote a whole essay defending that position: https://blog.plan99.net/what-s-wrong-with-exceptions-nothing-cee2ed0616 https://blog.plan99.net/what-s-wrong-with-exceptions-nothing... > Even junior engineers have a trivial time debugging most go errors Not my experience at all. I had to do this once. An HTTP request to a production server was yielding a 400 Bad Request with no useful information for what was bad about it. No problem, I'll check the logs and look at the source code. Useless: the server was written in Go and the logs had no information about where the error was originating. It was just getting propagated up via return codes and not logged properly. It ended up being faster to blackbox reverse engineer the server. In a language with exceptions there'd have been a stack trace that pinpointed exactly where the error originated, the story of how it was handled, and the story of how the program got there. Diagnosing errors given stack traces is very easy. I've regularly diagnosed subtle bugs given just logs+stack trace and nothing else. I've also had to do the same for platforms that only have error codes that aren't Go (like Windows). It's much, much harder.
- bob1029 2y ago> Diagnosing errors given stack traces is very easy. This is the most important aspect of exceptions in my view. The line that threw the exception isn't even the part of a stack trace that I find most interesting. The part that is most valuable to me when working on complex production systems are all of the call sites leading up to that point. I remember in my junior years I wasn't a big fan of exceptions. A stack trace would make my eyes glaze over. I would try/catch at really deep levels of abstraction and try to suppress errors too early. It took me a solid ~5 years before I was like "yes, exceptions are good and here's why". I think a lot of this boils down to experience and suffering the consequences of bad design enough times.
- mike_hearn 2y agoException usability is definitely an area that needs work. If you work support for a dev platform for a while, it's a really common experience that people will post questions with a copy/pasted stack trace where the message+stack actually answers their question. You can just copy/paste parts back to them and they're happy. There's too much information and not enough tools to digest/simplify them and people get overwhelmed. Still, better to have too much data than too little.
- bazoom42 2y agoIs “goto” just used to mean “bad and evil” here? Because exceptions are not a goto anymore than a return is a goto. The problem with goto is it can jump to any arbitrary place in your code. Exceptions will only go to catch-blocks up the call stack, which presumably you have written on purpose.
- vaylian 2y ago> Because exceptions are not a goto anymore than a return is a goto Not true at all * goto goes to a specific hard-coded address * return looks up the previous address from the stack and goes there * exceptions are a complex mess that require branching logic to determine where to resume execution
- abtinf 2y agoVery well put.
- Seb-C 2y agoI agree about implicit exceptions, but I think that there is a sweet spot with explicit exceptions like Swift (and maybe Java): where you cannot not-handle one, it is part of a function's signature, and the syntax is still compact enough that it does not hurt readability.
- therealdrag0 2y agoI think checked exceptions are noise. They usually never provide value, and are often just caught and rethrown as runtime exceptions to avoid the boilerplate. Scala did right to remove them.