I have an Accessor
and Repository
interface. Accessor
abstracts over where to store JSON documents (local file system, NoSQL database, etc). Repository
abstracts over the representation of my domain objects and does my object-relational mapping. Accessor
is injected into a Repository
.
I have a UserRepository
that is injected with any Accessor
. For example, I could inject a FileSystemAccessor
into this UserRepository
, and it would pull JSON documents from my file system, mapped to User
objects.
Accessor
provides a method get_for_unique_value
that finds a JSON document by a unique value for a specific key, given the name of a "collection" containing all these JSON documents. If multiple documents exist with the same value, a NonUniqueValueError
is thrown.
UserRepository
provides a method get_user_by_email
that finds a user by their email. Multiple users are not supposed to exist with the same email, so I want to throw an exception to indicate this. The underlying injected Accessor
provides get_for_unique_value
, so get_user_by_email
uses this internally. Any top-level controller would not be able to derive context from NonUniqueValueError
bubbling up, so I want to catch the underlying NonUniqueValueError
and throw a NonUniqueUserError
instead.
NonUniqueUserError
can be declared in three ways:
NonUniqueUserError
takes the thrownNonUniqueValueError
, and extendsException
.NonUniqueUserError
takes the thrownNonUniqueValueError
, and extendsNonUniqueValueError
.NonUniqueUserError
extendsNonUniqueValueError
, without taking the caughtNonUniqueValueError
.
(1) preserves the underlying stack trace of the thrown NonUniqueValueError
, but is not caught by a broader NonUniqueValueError
clause higher up the call stack. (3) would be caught by such a clause, but loses the stack trace. (2) seems to combine the best of both worlds.
Am I approaching this problem right by catching a NonUniqueValueError
and throwing NonUniqueUserError
instead? If so, is there any reason I shouldn't go with (2)? I've read Is it really that bad to catch a general exception?, but want to confirm that I am still properly addressing the NonUniqueValueError
exception here (as it is more general than NonUniqueUserError
).
Catching base Exception to preserve data integrity shows a situation where the same exact exception is caught and thrown, but I'm trying to add context by throwing a new more specific exception.