0

Consider I am developing a library. When this library encounters an exception it can't handle itself (e.g. a WebException) it will wrap that exception to hide implementation details from clients and provide them a uniform way of exception handling.

Regarding the message of such an exception, what are the best practices / guidelines / do's /don'ts?

Option 1: Wrapper does not include anything

My personal favorite, each exception is responsible for its own message. The wrapper uses a more general wording than the one being expected from the inner exception.

try
{
  // ...
}
catch (WebException ex)
{
  throw new MyLibraryException("An error occured accessing a web ressource", ex);
}

Option 2: Display the inner message

What more could you want to say, than that what the inner exception has to say? Not sure whether this is viable...

try
{
  // ...
}
catch (WebException ex)
{
  throw new MyLibraryException(ex.Message, ex);
}

Option 3: Concatenate it

I don't believe that this is a good idea, but it came up in a discussion we had locally, so I want to present it as an option.

The outer exception will take care of concatenating inner exception messages.

try
{
  // ...
}
catch (WebException ex)
{
  string message = string.Format("An error occured accessing a web ressource: {0}", ex.Message);
  throw new MyLibraryException(message, ex);
}

I feel that there must be clear guidelines on that topic (e.g. MSDN), but I was not able to find them. I already checked Best Practices for Exceptions, but for no avail.

Option 4: Don't care

From the comments:

do not waste time catching exceptions you cannot handle. Let the caller deal with it.

I don't think that this option is viable, because though I can't handle the exception myself I know that it can occur and I want to hide specifics from the caller (e.g. which exception type to handle?). This is important, because I could someday switch to another framework providing me with Web-Access and thus the exceptions could change. The wrapping helps to maintain the abstraction (IMHO).

edit: There seems to be a lot of confusion. I don't plan to apply this pattern to each and every exception. I will usually ignore or rethrow (throw;) exceptions like FileNotFoundException and many other core framework exceptions. However, there are cases when I want to hide and how am I supposed to do this in the best way possible?

Read this question as: If I had a good reason to nest exceptions, how should my messages look like?

Discussions on if you want to nest exceptions better belong here.

Community
  • 1
  • 1
NobodysNightmare
  • 2,992
  • 2
  • 22
  • 33
  • 4
    Option 4: do not waste time catching exceptions you cannot handle. Let the caller deal with it. – Polyfun Nov 28 '14 at 09:39
  • WPF uses option 3 and it's a pain. I'd really like to see inner exception (option 4) directly. – Sinatr Nov 28 '14 at 09:49
  • 1
    If you know it can occur, perhaps you _should_ be dealing with it, and returning `false` or similar from your method, rather than letting the exception bubble up. From the best practices article you linked: "A well-designed app handles exceptions and errors to prevent app crashes." You're not handling or preventing crashes by simply replacing one exception with another. – James Thorpe Nov 28 '14 at 09:49
  • What happens when there is a legitimate error and you've stomped the stacktrace...[thats a criminal offence](http://stackoverflow.com/a/178464/495455) – Jeremy Thompson Nov 28 '14 at 09:52
  • @JeremyThompson: That is not what I am doing here. I don't throw the exception I received (which would kill the stacktrace), but I *wrap* the exception I received as legitimate innerException. I think that innerExceptions are generally a legitimate measure. – NobodysNightmare Nov 28 '14 at 10:05
  • 1
    If you feel that a custom exception makes sense (lets say for example that you want the user of your API to be able to catch on a specific error type or maybe there isn't a suitable exception class already in the framework), then I would recommend option #1. – Emil Lundin Nov 28 '14 at 12:17
  • 1
    A good discussion on when to create custom exceptions is found here: http://stackoverflow.com/questions/3443570/create-custom-exception-or-use-built-in-exceptions – Emil Lundin Nov 28 '14 at 12:18
  • Thanks @EmilLundin for pointing to this discussion, I believe most other commenters thought I was asking the same question. I think that I will stick with option 1, but I am kind of sad that the discussion here drifted so far away from my question... – NobodysNightmare Nov 28 '14 at 13:01

2 Answers2

2

If you need extensive logging it might be wise to capture the error high up the chain to be able to provide as much details as possible about the error in the log message. After logging you should re-throw the exception. Make sure that you use throw; instead of throw ex; to preserve the stack trace.

Emil Lundin
  • 577
  • 5
  • 14
0

Option 4: do not waste time catching exceptions you cannot handle. Let the caller deal with it. Does it really matter to the caller whether they catch MyLibraryException or WebException? If the caller can handle and recover from WebExceptions, then they will want to catch that, not your MyLibraryException.

Also if the exception is thrown up through several layers, with your reasoning each layer would add its own wrapping, which means the top layer then has to drill down through multiple inner exceptions to get to the actual error - ugh!

The very top level can always have a catch all to catch and log any exceptions that have not already been handled.

Finally, you should document what (underlying) exceptions are likely to be thrown from your library, or the code it calls.

Edit: regarding abstraction: abstracting the exception in your MyLibraryException does not help the caller - they cannot recover from a MyLibraryException without knowing the ultimate cause, which is the exception you have wrapped, therefore you might as well not bother wrapping it in the first place, and let the caller catch it directly. If the caller cannot recover from the ultimate exception, then they will probably just catch everything and log the fact that an error occurred, and perhaps then terminate the application.

A concrete example: a FileIOException occurs in your library because of a missing file. Surely it is better for this to be thrown to the caller so they can recover from it (perhaps the user forgot a critical file), rather than the caller having to interpret your MyLibraryException?

Polyfun
  • 9,479
  • 4
  • 31
  • 39
  • I tried to clarify my intent. I do not apply this pattern always. IOExceptions and FileNotFound are good examples of exceptions that I would usually pass untouched. But there are legitimate cases (after all: inner exceptions are not something I made up) and I want to deal with them as good as possible. – NobodysNightmare Nov 28 '14 at 10:10
  • So now it becomes arbitrary as to which exceptions you wrap and which ones you let through. Perhaps in some situations you let IOExceptions through, sometimes you do not. How is the caller meant to know all this? Libraries that use inner exceptions are generally operating much closer to the metal. – Polyfun Nov 28 '14 at 10:19
  • 1
    Lets assume I document this clearly. When asking a question I have to balance excessive detail and abstraction. I honestly don't understand why nobody intends to answer the question I asked: What are best practices regarding error messages of nested exceptions? and: are there guidelines? I **did not** ask, whether I *should* nest exceptions. – NobodysNightmare Nov 28 '14 at 10:59