Just because it's useful to wrap exceptions in 5% of the cases doesn't mean you should wrap the rest 95% just in case . YAGNI. 1. 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 excep…
4. When you catch the third party exception you typically throw away the stack trace which can make it harder to debug.
Code Design Decision – Always throw custom exceptions
31–40 of 92 posts
Re: Code Design Decision – Always throw custom exceptions
#32Just because it's useful to wrap exceptions in 5% of the cases doesn't mean you should wrap the rest 95% just in case . YAGNI. 1. 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 excep…
Re: Code Design Decision – Always throw custom exceptions
#33Just because it's useful to wrap exceptions in 5% of the cases doesn't mean you should wrap the rest 95% just in case . YAGNI. 1. 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 excep…
I'm going to curse here, but ... fucking seriously.
If I get a .net ADO exception coming out of a 3rd party library it's absolutely not going to shock me or throw me for a loop. But do you know what IS a pain in the ass? Using 3 different libraries, all that wrap that same ADO exception in their own custom exception.
Re: Code Design Decision – Always throw custom exceptions
#34This idea can also be explored in the Go programming language. Go has an error type, not exceptions, but error checking famously can be rather verbose. Two cases to consider come to mind. First, the common pattern result, err := SomeFunc() if err != nil { return err } Here the code is just passing along the error to the caller, unchanged. Second, signaling errors ab initio result := // some calculation or behavior if…
The whole DomainError thing only makes sense if you expect someone to handle this error (and by handle, I mean doing something other than logging and aborting some operation), or if you are writing a very generic library. Otherwise, it is wasted time and extra complexity that makes the code harder to read.
type ParseError struct {
Line int
Col int
Message string
}
The user of your library isn't expected to handle this error explicitly, but when they print the output, they can see exactly where the issue was.Re: Code Design Decision – Always throw custom exceptions
#35In 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…
We primarily use custom exceptions to add detail to our error logs while still remaining concise. Generic exceptions are exceptionally useless for trying to debug issues, I've found.
Re: Code Design Decision – Always throw custom exceptions
#36Earlier quoted context omitted.
> You don't know which exceptions will be raised in advance. > Most of exceptions are unrecoverable (that's why they are called exceptions), the best course of action is to crash, which happens by default. I prefer to propagate such unknown exceptions to a top-level catch to clanly log that something happened. I usually have two types of exceptions: the ones I expect at some point (a HTTP call failing for some reason…
I really wish English had different individual words for the concepts "known [problem] we should not worry about" and "[problems] I did not anticipate".
error (a fatal thing I was expecting happened; I couldn't reach the API)
exception (a fatal thing I wasn't expecting happened; the runtime fault handler did a thing named XYZ)
Re: Code Design Decision – Always throw custom exceptions
#37Earlier quoted context omitted.
> You don't know which exceptions will be raised in advance. > Most of exceptions are unrecoverable (that's why they are called exceptions), the best course of action is to crash, which happens by default. I prefer to propagate such unknown exceptions to a top-level catch to clanly log that something happened. I usually have two types of exceptions: the ones I expect at some point (a HTTP call failing for some reason…
I really wish English had different individual words for the concepts "known [problem] we should not worry about" and "[problems] I did not anticipate".
Everything goes to ERROR by default, some errors get downgraded to WARNING when you confirm they are not important.
Send ERRORs to Sentry (or whatever you use) and deal with them immediately. Send WARNINGs to your favorite centralized logging solution and deal with them when there's too many.
Re: Code Design Decision – Always throw custom exceptions
#38Earlier quoted context omitted.
I think there are two kinds of exceptions in languages that have them as their error handling mechanism. 1. Exceptions you expect your consumers to handle. 2. Exceptions you don't expect your consumers to handle. The first one I would argue you should wrap third party exceptions. There is in nearly every case important context in your code that the thrower of the third party exception will not know and whoever is rea…
This is one of the problems with checked exceptions. The library author is in no position to expect me to handle an exception. Whether or not I can relies on the design of my system, which they have no window into.
If the type system were more capable, they'd just be equivalent to typed generic error returns, which work fine.
Re: Code Design Decision – Always throw custom exceptions
#39Earlier quoted context omitted.
We primarily use custom exceptions to add detail to our error logs while still remaining concise. Generic exceptions are exceptionally useless for trying to debug issues, I've found.
Typed exceptions convey a bit of information to enable specialized handling at runtime, they are not meant to try and make debugging easier.
Re: Code Design Decision – Always throw custom exceptions
#40Yes. The Python modules I write generally have: 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, FileNotFoun…
This sounds like viral boilerplate: any function that can fail forces all other functions in the stack trace to be wrapped. Seems quite unpythonic, the whole point of exceptions is to avoid this boilerplate by propagating.
Are you just writing boilerplate to assign exceptions to modules? But this information is already present in the stack trace, what is the point? It's too generic to actually handle exceptions, and too redundant to provide debugging value.