Question

Say your making a library Foo that depends on a 3rd-party library Bar.

Bar throws a custom exception \OtherVendor\Bar\CustomException.

Is it recommended to just throw that exact exception to your clients (devs using your lib) or should you catch it then convert it to your own exception? E.g.,

try {
    $bar->stuff();
} catch (\OtherVendor\Bar\CustomException $ex) {
    throw new \MyLib\Foo\MyCustomException();
}

To explain further, is it better for your clients to know about that 3rd-party exception in your documentation? e.g.,

You can catch \OtherVendor\Bar\CustomException in case of x...

or should you "rebrand" the exception so clients don't need to deal with another lib's namespace? E.g.,

You can catch \MyLub\Foo\MyCustomException in case of x...

Was it helpful?

Solution

Generally speaking, it's fine to use a language's own exceptions, since these are commonly understood. I wouldn't use 3rd party exceptions, since using that 3rd party library isn't part of the API you're offering and you might swap it for another 3rd party library (or remove it altogether) in future versions. If a client of your library built some of their error handling based on the 3rd party exception, they will have to rewrite their code. By using your own exception ('rebranding it', as you call it), you'll have the option of keeping the interface identical to previous versions.

(disclaimer: I use PHP only very sparingly, this recommendation is based on experience with half a dozen other languages)

OTHER TIPS

TL;DR: It's a waste of time to rebrand exceptions, in at least 99 percent of all situations.

A valuable rule of thumb is to catch exceptions only:

  • At application top level (telling the end user about the failure) or
  • At places where you know and implement a strategy how to achieve your overall goal even in that specific failure case. In other words: if you receive an exception you don't fully understand, and don't have a generic "retry" or a "try-a-different-way" strategy, don't catch! Let your caller deal with the situation that his call failed.

Both valid cases don't apply to you, but maybe to your caller. You're designing a library, not a top-level application. Your code shows that you don't want to recover from the exception (retrying or whatever), but just tell your caller about it.

So the main question about your API design is "Will rebranding the exception make it easier for your caller to decide about and implement an error-recovery strategy?"

There are a few situations to be considered now:

  • Most probably your caller doesn't want to implement any recovery strategies, but just report an error to the user and restart from top level. In that case, the exception type doesn't matter at all.

  • Maybe your caller seriously needs your API call to succeed, so he's ready to retry it a few times in case of failure. He'll write a retry-loop around your API call, and the only aspect where your rebranded exception can help him, is if it reliably tells him that retries won't change the outcome of your call. This "help" only shortens the time until he gives up...

  • Maybe your caller has an alternative way of reaching his goal instead of your library call (that's a very rare situation). Then he'll most probably do that if he gets an exception, no matter what type of exception that is.

So in general, to your caller's program flow it doesn't matter what type of exception he gets.

But there's the error message to be presented to the user, and the information to be written into some kind of log.

  • If your rebranded exception can provide a description that's presentable to the user, it might be worth the effort. Of course, you have to document that fact with your exception, otherwise your caller will create his own messages anyway. And hopefully you know enough about the end user's problem domain and native language so you can really supply a useful message. Considering that, you most probably won't be able to supply a useful message.
  • Make sure your rebranded exception contains all information relevant for a technical analysis of the problem, esp. the complete stack trace. So, if you create a rebranded exception, make sure to include the original one as its "previous". And maybe you have some context information you'd like to add to the logged problem description, then "rebrand" the exception and add the context to the message.

So, there are very few situations where I see a benefit in rebranding an exception.

Licensed under: CC-BY-SA with attribution
scroll top