Code Design Decision – Always throw custom exceptions
1–10 of 92 posts
Re: Code Design Decision – Always throw custom exceptions
#2What was null? Why might it be null? Mis-configuration? Missing configuration? Can't load some data or connect to some system? Which setting should be verified? Give simple hints on what might have gone wrong to help future you.
Re: Code Design Decision – Always throw custom exceptions
#3Re: Code Design Decision – Always throw custom exceptions
#4Re: Code Design Decision – Always throw custom exceptions
#5 class Error(Exception):
pass
class FooError(Error):
…
and then, in the generic case: try:
failing_external_function()
except Exception as e:
raise Error(*e.args) from e
(And if the code encounters a foo situation, it explicitly raises FooError, possibly with extra parameters, etc.)It is really annoying to have to catch all of, say, socket.error, SSL errors, FileNotFound, etc. etc. in every call to some function in a module, if you use that module extensively. It’s much easier to just catch module.Error and be done with it. If you need to handle foo errors specially, you catch FooError.
Re: Code Design Decision – Always throw custom exceptions
#6This is checked exceptions all over again... Frankly, I usually do exactly the opposite. Most cases I've seen the exceptions that can arise are not widely known in advance, and for most spots where exceptions can be raised from I simply do not care about them as much either. If my DB is not accessible - do I really, really need to wrap it? If the DNS resolver is failing - do I really really need to wrap it?
When debugging I actually appreciate when a library/controller/module/whatnot does not attempt to "enhance" the exception from something outside of its control with a wrapper, and value seeing the original failure instead.
Re: Code Design Decision – Always throw custom exceptions
#7In short: if you have a meaningful recovery pathway for a particular exception this can be useful, but I found that 9 out of 10 exceptions/errors in code cannot be recovered from. This is checked exceptions all over again... Frankly, I usually do exactly the opposite. Most cases I've seen the exceptions that can arise are not widely known in advance, and for most spots where exceptions can be raised from I simply do…
This is what Python’s “raise from” is for; to preserve the original exception.
Re: Code Design Decision – Always throw custom exceptions
#81. You don't know which exceptions will be raised in advance. Anything that involves IO can fail in a plethora of ways, and you don't even know which calls involve IO (e.g. a library might choose to cache something on disk).
2. Consumers of your code will not know how to deal with those exceptions.
3. Most of exceptions are unrecoverable (that's why they are called exceptions), the best course of action is to crash, which happens by default.
4. You debug those exceptions by looking at stack trace. Adding extra levels just to give a fancy meaningless name to an exception does not help.
5. The whole point of exceptions is to propagate. Parthenon essentially suggests converting exceptions into return values.
Re: Code Design Decision – Always throw custom exceptions
#9In short: if you have a meaningful recovery pathway for a particular exception this can be useful, but I found that 9 out of 10 exceptions/errors in code cannot be recovered from. This is checked exceptions all over again... Frankly, I usually do exactly the opposite. Most cases I've seen the exceptions that can arise are not widely known in advance, and for most spots where exceptions can be raised from I simply do…
That is an interesting topic, as I went through the cycle of adding and removing them, they always felt like the right thing, but they felt like "work". They make coding less fun, having to think through failure conditions, like you say, you don't care about.
I guess the answer is really there is no one sized fits all solution, we have some applications where the correct solution is to crash, we have other applications that can't crash under any condition. You just need to know where you are.
Edit:
Also, out of the box C++ checked exceptions implemented terribly.
http://www.gotw.ca/publications/mill22.htm
The (Mis)understanding section describes it pretty well.