Live data from Hacker News

Code Design Decision – Always throw custom exceptions

github.com

51–60 of 92 posts

Re: Code Design Decision – Always throw custom exceptions

#51
post #23

This 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…

IME, returning a "stringly-typed" error is only wrong if you don't provide enough context in the returned error message. You can describe what you were doing as an error message and pass it back up the stack, each layer adding their own context, ie what they were trying to do to what. At the top you (should) get a pretty complete picture of what went wrong and why. I have found this reasonable and proportionate for m…

That's all well and good if all you want to do it propagate the error up the call stack until some code prints it, but that's not really handling the error, any more than if err != nil { return error } is. If the calling code needs to behave differently depending on the details of the error, the worst way to do that would be examine the message string. A robust system is going to respond very differently if, for example, the error is one that indicates retrying is worthwhile vs an error indicating that no amount of retrying will ever succeed.

Re: Code Design Decision – Always throw custom exceptions

#52
post #6

In 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…

> If my DB is not accessible - do I really, really need to wrap it? I would say yes. Most of your code doesn't care that the database failed with a PG-300292-AB error. What you do care about is that there is a system failure. If you wrap your system failure, and document it as THE exception, the API caller will know what to look for. In general there really are only a few exceptions: system, invalid input, non found.…

Not that this invalidates your point in any way, but returning a 503 for database (or any other resource) unavailable is useful to disambiguate server errors from transient connectivity/database is temporarily unavailable errors.

Re: Code Design Decision – Always throw custom exceptions

#53
post #13

Earlier 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…

"Exceptions you expect the consumer to handle" should be explicit return values on the function signature instead, via an Either/Result type or similar. Unless you're writing Java where you can force certain exception types to be handled, but people never write that code properly.

Very few languages actually support Either or Result types ergonomically. I don't have a problem with people using exceptions for these but I do think if the language has compile time type checking it should provide a distinction between checked exceptions and non checked exceptions. I am very much in the minority here but I find it very useful to let robots tell me I forgot something than to discover I forgot it in production. I think this is the useful sort of lazy rather than the not useful sort. Not useful laziness is letting your customers discover the problem.

Re: Code Design Decision – Always throw custom exceptions

#54
post #50
post #21

Earlier quoted context omitted.

That is true, so the library should throw the checked exception, and if the caller has no way to handle it, it should wrap the checked exception in an unchecked exception and throw the unchecked exception. Not too hard, and library clients that can handle some checked exceptions will be able to. I hate libraries that only throw unchecked exceptions. It seems easier initially, but makes writing correct code more diffi…

> If the caller has no way to handle it, it should wrap the checked exception in an unchecked exception and throw the unchecked exception. Not you have a new problem: How is the code calling the caller supposed to know about that exception? You can't even catch it (even if you know about it!) using normal try-catch because what you have to do is catch the wrapper exception and then check inside that for the exception…

The error here is not that they are wrapping the exception necessarily. It is that they re-threw it as an unchecked exception. I strongly believe the only good use of unchecked exceptions is if the code should do the closest reasonable thing to crash safely. Everything should be clearly communicated to the callers so they can make good decisions about what to handle here and what to pass up the chain.

If the complaint is that you then have too many different unchecked exceptions perhaps the error domain has been improperly modeled and you are getting a clue that the system is poorly designed.

Re: Code Design Decision – Always throw custom exceptions

#55
post #49

Earlier quoted context omitted.

> 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. 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 t…

What do you use libraries for if not for the abstraction layer?

Well it certainly isn't so I don't have to understand what an ADO exception is.

Re: Code Design Decision – Always throw custom exceptions

#56
post #53

Earlier quoted context omitted.

"Exceptions you expect the consumer to handle" should be explicit return values on the function signature instead, via an Either/Result type or similar. Unless you're writing Java where you can force certain exception types to be handled, but people never write that code properly.

Very few languages actually support Either or Result types ergonomically. I don't have a problem with people using exceptions for these but I do think if the language has compile time type checking it should provide a distinction between checked exceptions and non checked exceptions. I am very much in the minority here but I find it very useful to let robots tell me I forgot something than to discover I forgot it in…

Yeah I agree. I think the problem with checked exceptions in Java is a combination of misuse on both the consuming and the throwing end. They're amazing when they provide a compile time checked way to make sure consumers handle stuff they actually definitely want to handle, but if you add too much noise then all the consuming code is just going to catch and rethrow even the important ones.

Re: Code Design Decision – Always throw custom exceptions

#57
post #38

Earlier quoted context omitted.

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.

This is the problem of Java's implementation of checked exceptions... because they are not generic. Which forces middle layers to make impossible decisions like this. If the type system were more capable, they'd just be equivalent to typed generic error returns, which work fine.

I mean, can't you just catch Throwable (base class) and be done with it?

Re: Code Design Decision – Always throw custom exceptions

#58
post #8

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…

> The whole point of exceptions is to propagate.

I thought the point of exceptions was what we're now calling observability.

If somehow wrapping them in your own goo because you, the dev of that code, can help diagnose problems, more power to you.

But most of the time that doesn't really help so letting them bubble up and not obscuring root causes is better.

So . . . Use judgement. If you don't have judgement, ask a friend. If you don't have a friend, just let the exceptions propagate on their own.

Re: Code Design Decision – Always throw custom exceptions

#59
post #48

Earlier quoted context omitted.

> 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. 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 t…

Haha, that's actually a good point. A single problem can affect dozens of modules, each having a different wrapper. If my db goes down, I very much prefer to see a single DatabaseConnectionFailed than a multitude of FailedToSaveObject, DatabaseError, CannotLoadData, IOError, SomethingIsWrongThisShouldNeverHappen, DBHostUnavailable all over the place. Good luck navigating through the noise and isolating those.

The article talks about solving that exact issue by wrapping all of those different exceptions so that you don't have to deal with them. Much easier to catch a single ThirdPartyInternalFailure exception than catch all the internal exceptions that could have caused an internal failure.

Re: Code Design Decision – Always throw custom exceptions

#60
Amazes me that so many people dont understand that if all things are dependant upon your business logic or on your domain then this is natural. Its natural hex architecture

but this is far nicer way of saying the same thing https://ericlippert.com/2008/09/10/vexing-exceptions/

I actually do not think your code should throw exceptions. It is really just an Either / result and then if something does blow its because you havent anticipated it via wrapping something in an either or result ... and so it should blow and the callers of your library should be submitting a defect..

Post reply on HN