4 ms·
The anti-pattern I've seen in dysfunctional enterprise development shops (i.e. most of them) is that checked exceptions mean exceptions that "we'll never have"
by jeremyjh 10y ago
The anti-pattern I've seen in dysfunctional enterprise development shops (i.e. most of them) is that checked exceptions mean exceptions that "we'll never have" get buried lower in the stack; so code can fail silently and continue running just to avoid the monstrous checking code and propagation of exception type declarations up the call stack.
I don't see how the Rust approach would avoid this fate but I doubt it will ever be used in these contexts to begin with.
- jimktrains2 10y agoI think that part of it is that the idea of a Result type being normal will help prevent much of the cruft and burying we see with exceptions. I also feel like handling Result types is more natural than exceptions. First, you _have_ to do it, even if that means a try! and passing the buck. The syntax for this isn't as monstrous as it is for checked exceptions as well. Second, it feels more like a natural code-flow, not the break that exceptions provide. Third, it's useful for more than just "Exceptions". Coupled with Optional types, it provides a more expressive way of not-hapy-path-code where exceptions just feel heavy handed. For instance https://docs.python.org/3/library/stdtypes.html https://docs.python.org/3/library/stdtypes.html d[key] Return the item of d with key key. Raises a KeyError if key is not in the map. The key not existing isn't really exceptional. A proper optional, union, or result type handles this case much more easily. In sum, I think the expressibility of Result and Option, along with a more natural flow for handling them will make working around them less tempting/viable/easy to pass over in a code review.
- jeremyjh 10y agoYou don't have to convince me of the value of Result types, I prefer them too. I've only written a couple thousands of lines of Rust but tens of thousands of Haskell which rely on the same concepts (though its nicer with do notation). I don't have faith in the masses though and right now there is a strong selection bias in Rust that means only people concerned with quality and correctness are using it in the first place. I think twenty-five years ago there were similar hopes and dreams for Java checked exceptions.
- jimktrains2 10y ago> I think twenty-five years ago there were similar hopes and dreams for Java checked exceptions. Yeaaaaaaah. I remember being a very strong supporter of checked exceptions before I got into a giant codebase and saw how not having speced a sane exception type can cause lots of pain and some really long declarations or dropped exceptions. catch (Exception e) { throw new RuntimeError(e); } :( You're right, I guess time will tell.
- int_19h 10y agoThe big problem with Java checked exceptions was that the language was simply not flexible enough in other areas to handle higher-order stuff. For example, quite often you want to define something like "this method takes object X, and throws everything that X.foo() can throw, and also E". But there's no way to express it in Java. So the moment you start doing any sort of HOF-like stuff - even as simple as event handlers - you have to struggle with checked exceptions. This is not a problem in Rust.
- int_19h 10y agoExceptions in Python are used rather differently than in most other languages. Their overhead is much lower than exceptions in e.g. Java or C++, so they're routinely used to indicate expected conditions, like missing key in dictionary, or end of iterator. Since the language is dynamically typed in the first place, there's no concern about it effectively circumventing the type system. That said, dict also has get(), which lets you specify the default value if key wasn't found (and the default default is None).
- _pmf_ 10y ago> fail silently No. They are usually logged. The difference is that with exceptions, the logging will occur at a higher level and be done uniformly while in Rust you'll have to explicitly thread the error through the call stack manually to log it at a higher level.
- cryptarch 10y agoOn that point, does that mean Rust libraries tend to have logging hooks or are all errors emitted by Result's? What about non-fatal errors such as retries in a GUI library that loads an image from the web, how are they logged or otherwise propogated to the developer?
- burntsushi 10y agoErrors in Rust are just normal values, so there's nothing special you have to do. You just write your retry logic, presumably after inspecting the kind of error that occurred.
- cryptarch 10y agoI'm aware of how Result works, I've written a little Rust. I was wondering how Rust libraries specifically deal with non-fatal error handling in parts of the library that are abstracted away from the library consumer, such as my example of a GUI library that has retry behavior that is not exposed to the user. Is there currently a convention for dealing with such "encapsulated but interesting" errors occuring in Rust libraries? It seems obvious to me that a web framework would have a logging hook but non-obvious how that API would function; would it call a logging callback with a severity and a string? Just a string? Or an error message and some kind of "related data" (such as a stack trace or relevant structs) container? It doesn't seem obvious to me to log only text in the context of a GUI library. I'm thinking of building a native cross-platform GUI library in Rust (borrowing concepts from IUP[0] but adding more typing) and I feel like there would be value in having structured data as part of the nonfatal error interface, so I'm curious if there are existing patterns to learn from. [0] http://webserver2.tecgraf.puc-rio.br/iup/ http://webserver2.tecgraf.puc-rio.br/iup/