DEV Community

Discussion on: Only 2 or 3 error types are needed

Collapse
 
mortoray profile image
edA‑qa mort‑ora‑y • Edited

The location of error handling, and the structure of the calling code, is more valuable than classes of errors. If you need to distinguish between parsing,or preparing message processing from the actual processing that split the code along those two lines.

If the state of processing needs to be communicating to higher layers than it should be communicated as a proper state and not through the error channels.

In virtually all cases where I've needed to distinguish the type of error handling based on what went wrong it's actually indicated some kind of architectural issue in the code.

Error types that carry extra meaning are local to the code that raises that error. If they escape that context they lose any special meaning. this implies any of these error types are not optional to handle, but mandatory to handle when calling a particular API.

They become part of the API contract, which starts sounding like checked exceptions. Checked excpetions have been a failure in all languages that have tried them. The idea is nice, but it just doesn't work out. It's too complex to get this working correctly and cleanly, and all it takes is one bad intermediate function to ruin the whole thing.

But even if you go down the error proliferation route, which I don't recommend, tagged exceptions are still the better alternative. If you truly wish to change the error handling based on an HTTP error, it makes more sense to encode that into a tag on the error. Then you have a guarantee that this information won't be lost during propagation. There's no wrapping, rewriting, or serialization issues to worry about.

Collapse
 
paolo_milani profile image
Paolo Milani

Thanks for the well-thought-out response.

If you need to distinguish between parsing,or preparing message
processing from the actual processing that split the code along
those two lines.

Definitely, that's a first line of defence. If I'm in the parsing routine I can catch the top level exception class and decide that I'm parsing a bad message if that is raised for whatever reason.

But whenever I am making a request of something outside of my process (a file system? network? database? API server?..) a single request can fail in many ways that may need to be handled in different ways.

My point is that the person who writes e.g. the db library or api client library cannot know what classes of error handling will be needed in the context of a given application, so they are not able to meaningfully raise exceptions of the two types listed in the article.

Instead, they presumably divide the errors that can happen into broad classes, which map to exception classes, and annotate them with the specific e.g. client or server error code and message.

If the state of processing needs to be communicating to higher
layers than it should be communicated as a proper state and not
through the error channels.

Here I disagree, an exception seems an effective language construct to communicate an error state up the stack.

Error types that carry extra meaning are local to the code that
raises that error. If they escape that context they lose any
special meaning. this implies any of these error types are not
optional to handle, but mandatory to handle when calling a
particular API.

More or less... you can have a default error handling behaviour for "all other errors".

But to do better than that, yes, at some point I need to examine the specific error cases raised and decide how to map them to my available error handling behaviours. This probably needs to happen not too far from the call site (as you say, where the semantics of the errors is known), while the actual error handling might happen far up the stack, in which case I will probably wrap the error into an exception class based on the type of error handling I need to do.

All of this could be done with a single exception class with tags, but since the language provides syntax to catch exceptions by class and not by tag, using multiple classes seems the more natural option.

Checked exceptions have been a failure in all languages that have
tried them.

that seems a strong statement, not an expert on this but "declare or raise" seems to be a good model for a statically typed language like Java, which hasn't been exactly a failure. Not an option in my current python work though, where not knowing what errors a library call might raise is a common problem we face.