|
|
|
|
|
by kisielk
4385 days ago
|
|
That's not been my experience, often it helps to add more context to errors as they propagate through the layers. Unless you control the entire stack of function calls top to bottom as part of your application, I think it's ogyrn bad form for one library to bubble up another library's errors directly. It's effectively leaking implementation details and it means the clients of your library may also have to import your dependencies to handle the errors. |
|
Wrapping exceptions as they bubble up is only helpful if the wrapped exception adds context that aids in diagnosing the issue. Otherwise it's just boilerplate that obfuscates and gives a certain type of developer warm fuzzies. "Exposing implementation" is a non-counterargument - the component failed because its implementation preconditions were violated, you need to address those implementation preconditions to fix the problem!
You don't need to import dependencies unless you intend to catch the specific originally thrown exceptions, and that's not normally what happens in the top loop; it normally logs, dumps or transmits the exception message and possibly its stack trace. These operations are normally only rely on the base exception type, so there's no need to catch a more specific exception.
Problem languages for this approach, though, are C++ (where the culture makes a single base class for exceptions awkward) and Java (where throws clauses, a deeply misguided feature, may force dependency imports unless you specify 'throws Exception' - or my preference, wrap in RuntimeException).
PS: I should add the other fundamental problem with the Java throws clause is that it uses static types to analyze dynamic data flow in a language with polymorphism, which makes it a usability disaster. When the code being invoked is indirectly accessed via polymorphic references, exception flow checking falls apart. There's a reason Google Guava's Function and Predicate interfaces don't throw. But that's enough of my bugbears.