Exception catching best practice (c#/.net) - c#

If I have code like this:
void a()
{
try
{
b();
}
catch (MyException)
{
// Handle any problems that occurred in b(c(d()))
}
}
void b()
{
c();
// Do something else
}
void c()
{
d();
// Do something else
}
void d()
{
// Do something, throw a MyException if it fails
}
Assuming no cleanup is necessary at any point, is it best to put a try{}catch{throw;} around the call to d() in c() and the call to c() in b() or is it considered OK to let the exception from d() bubble up to a() "naturally" without any intervening try/catch blocks?
I suppose the extra try/catch block act as a sort of "documentation" but they seem superfluous so I'm just wondering what other people would consider the best way.
Sorry if this is all a bit too basic, I'm trying to get my head around exceptions but I don't seem to have a good feel for them yet.

Let it propagate until you can handle it. If you can't handle it, there's no point catching it. So the question is, can you effectively handle the exception inside the c() method?

Basically, no. This is not the suggested way to handle these situations.
You should catch exceptions if and only if you can either handle them and do something appropriate with them or to provide more info to the callers higher in the call stack (by encapsulating it in a more generic exception). If you can't do it, you should let the exception bubble up in the call stack until someone can handle it appropriately.

The great advantage of exceptions is that you can deal with problems where you can do womething about them, rather than directly in the function where e.g. a missing file is detected, or in the function's caller, or its caller, &c.
However, exceptions also have to be handled somewhere along the chain. Where these points occur depend on the framework you are using, and what its exception management consists of. The key question is: what are your points of entry where allowing an exception to escape uncaught would have bad effects? Typical examples include
Event processing code in interactive UI applications (which at least in WinForms and ASP.NET can be caught en masse by providing exception event handlers).
Integration points where you respond to external messages (e.g. picking up messages from a queue, processing a file, listening on a named pipe, implementing a WCF service).
Timer events where you do background processing.
Thread start methods.
Sometimes, you also want to catch a low-level general technical error and rethrow it as a more domain-specific exception. This typically done in well-designed libraries to shield users from its internal implementation details. In an enterprise application, you might want to catch certain SqlExceptions and rethrow them as application-specific exceptions (e.g. YourApp.UnknownCustomer), in order to deal with them at higher levels of logic.
My advice would be: deal with problems at the highest level possible, but ensure that the exception catchers up there have reasonable exceptions to work with. And, by the way, unless you hate your users, don't display the exception and its stack trace to them! ;-)

I'd say, it depends on what you want to do with the information.
I always try to catch problems as close to the source as possible - why run all the way back with the problem, instead of trying to deal with it where it happens? For readability and understanding of the code, I also believe in try/catch as close to the source of the problem as possible.
If you're writing the program for yourself, and noone else will ever touch it, do whatever works best for you and the code.

Related

Handling Identical IO Exceptions In Different Code Blocks

I'm working on a WinForms project that involves multiple IO calls. With IO comes great responsibility as many IO methods are fairly prone to exceptions (UnauthorizedAccess/file in use/etc.).
I'd like to know how to best handle the same exceptions throughout multiple spots in the code. For example, if I call FileInfo.CopyTo() in 7 different code blocks, all of which could throw UnauthorizedAccessExceptions, how should I handle that? I know that the general consensus dictates that exceptions should only be caught when they can be properly handled. I'm unsure of a "proper" way to handle an UnauthorizedAccessException, but I do want to display a MessageBox informing the user that the file was not copied.
In this case, I would have to wrap the 7 calls to CopyTo() in a try/catch statement and pop up the same MessageBox 7 times. To avoid reusing code, my first thought is to create something like this:
public void SafeCopy(FileInfo file, string targetPath)
{
try
{
file.CopyTo(targetPath);
}
catch (UnauthorizedAccessException ex)
{
MessageBox.Show(ex.Message);
}
}
This is obviously simplified and would handle additional exceptions. However, it doesn't quite feel right to create a "wrapper method" simply designed to handle exceptions for a single method call.
I know this could be considered subjective, but I feel there is a correct answer or alternate path here.

Exception propagation in C#

Suppose I have three functions doA(), doB(), and doC() in a C# program where I know that doA() will call doB() which in turn calls doC().
Since doC() has to interact with a database, I know that it could very well generate exceptions that it won't be able to resolve that need to be brought to the user's attention. At the moment, I have the code which might throw the error in a try / catch blow in doC() and then the call to doC() in doB() in another try / catch and similarly the call to doB() in doA() in try / catch block. This allows me to just use throw; to kick the exception up to doA() where something can reasonably be done to display this to the user.
This seems a little like overkill though. I am wondering if since I don't plan on dealing with the exception in doB() or doC() if I can just get rid of the try / catch blocks there.
Assuming there are no finally blocks involved, what is the best practice for dealing with situations like this?
If your catch blocks are just like this:
catch (Exception)
{
throw;
}
then they are pointless indeed. You're not really handling the exception - don't bother with try/catch at all.
Personally I have very few try/catch blocks in my code - and although there are plenty of implicit try/finally blocks, most are due to using statements.
Yes I would get rid of the try/catch blocks - just let the exception propagate up to the top level and then catch it there. Catching an exception just to rethrow with throw; is simply not useful, although the following variation is actually harmful as it destroys the stack trace information:
catch (Exception exception)
{
throw exception;
}
You only need to catch if you intend to do something (or are trying to stop propagation). If you don't catch, it goes to the catch in the caller. In your case, it seems like doA() (or possibly its caller, depending on where you can handle it) is the only function that needs try/catch.
Exceptions bubble up the call stack.
If the method where the exception happens doesn't handle it, the methods caller gets it. If the caller doesn't handle it, it goes further up the call stack until the framework handles it and crashes your application.
To answer your question: there is no need to rethrow an exception in your case.
Type of exceptions you ll be catching can be different in every level, I m not sure what you are doing in 3 levels, but at the top of the stack you can only can 1 type of exception, in the lower level there might be different type of exception, which kinda forces u to use a broad exception type then a specific one, which might not have clear information in it.
So it depends on the types of Exceptions you ll be throwing.
IMHO, an exception should be caught the fewest number of times possible, it's actually a rather expensive operation to catch an exception.
The case might come up where you're crossing application layers, and might want one layer to log/rethrow, and the next layer up also needs to catch it. But in your case, it's just one layer so I'd say at the highest place in the call stack where you can do something with the exception, log it and do your business logic.
In short the answer to your question is yes. The only reason to catch an exception is to do something with it. If you can't do anything useful with it in DoC() then just let it bubble up.
It is always a good practice to have try catch blocks at the entry points to your code (typically in event handlers in a win forms app) so that nothing goes uncaught. At that point what you can do with it is tell the user.
However, you may also want to put some lower level handlers in place as appropriate if they can take reasonable action. For example, in doC() you might want to catch exceptions that have to do with deadlocks and retry. At some level you may also want to catch constraint errors and throw more meaningful user targeted errors in their place. I have a blog post about that here.

Eating Exceptions in c# om nom nom

Given that eating exceptions is always bad juju and re-throwing the exception loses the call stack, what's the proper way to re-factor the following?
Eating Exceptions:
try
{
… do something meaningful
}
catch(SomeException ex)
{
// eat exception
}
try
{
...
}
catch(SomeException e)
{
//Do whatever is needed with e
throw; //This rethrows and preserves call stack.
}
Catch and handle specific types of exceptions. Good practice is to not just catch System.Exception. A robust routine will strongly type the exceptions it knows how to handle.
Exceptions shouldn't be used for control flow, but there are often specific unwind procedures that need to be taken based on the type of exception.
Depending on the specific type, you may or may not choose to rethrow it. For example, an ASP parsing exception being thrown to an error page that USES the code causing the exception will cause an infinite loop.
try
{
}
catch( FileIOException )
{
// unwind and re-throw as determined by the specific exception type
}
catch( UnauthorizedAccessException )
{
// unwind and re-throw as determined by the specific exception type
}
catch( SomeOtherException )
{
// unwind and re-throw as determined by the specific exception type
}
catch( Exception )
{
// log and re-throw...add your own message, capture the call stack, etc.
// throw original exception
throw;
// OR, throw your own custom exception that provides more specific detail and captures
// the original exception as the inner exception
throw new MyStronglyTypedException();
}
finally
{
// always clean up
}
Most people think it's utterly evil to eat/suppress exceptions, especially with catch-alls. (Ironically, they use the catch all response of "don't use catch-alls, it's evil" :-). I don't understand the religious fervour with which people parrot this view, because if used sensibly, there is nothing wrong with this approach.
In my book, the worst case scenario is that my program catastrophically exits -> this creates a very unhappy customer with a total data loss situation. An unhandled exception is guaranteed to cause this every time. So failing to handle an exception is statistically more dangerous than any risk of instability that may occur if an exception is suppressed. In light of this, anything we can reasonably do to protect against an unhandled exception occurring is a good thing.
Many people seem to forget that catch alls can often handle any exception correctly, even if they don't know the details of what the exception was. By this I mean that they can guarantee that the program state remains stable, and the program continues to run within its design parameters. Or there may even be side effects such as the user finding a button unresponsive, but they still won't lose any data (i.e. graceful degradation is better than a fatal crash). For example, sometimes you want to return one value on success and a default if you fail for any reason. Part of designing code is knowing when to report errors to the user and when to fix a problem on their behalf so their program "just works". In this situation, a well designed catch-all is often the correct tool for the job.
Exceptions worry me. Fundamentally an exception is a guaranteed program crash if I don't handle it. If I only add specific exception handling for the exceptions I expect, my program is inherently fragile. Consider how easily it can be broken:
If a programmer forgets to document one exception they might throw, I won't know I need to catch it, and my code will have a vulnerability I'm not aware of.
If someone updates a method so that it throws a new exception type, that new exception could ripple up the call stack until it hits my code. But my code was not built to handle the exception. Don't tell me that the libraries I'm calling will never change.
Every exception type you specifically handle is another code path to be tested. It significantly multiplies the complexity of testing and/or the risks that a broken bit of handling code might go unnoticed.
The view underpinning the "suppression is evil" view is that all exceptions represent an instability or error - but in many cases programmers use exceptions to return little more than status information. For example, FileNotFound. The programmer writing file I/O code has decided on my behalf that a missing file is a fatal error. And it might be. It is up to me to catch this and decide that actually it's a common and perfectly normal, or expected, situation. A lot of the time, suppressing exceptions is necessary to simply stop someone else's "decision" taking out my application. The old approach of simply ignoring error return codes wasn't always a bad thing, especially given the amount of effort it takes to catch and suppress the myriad "status" exceptions that are bandied about.
The trick to silently eating/suppressing exceptions is just to be sure that this is the correct way to handle them. (And in many cases, it's not). So there may be no need to refactor your example code - it might not be bad juju.
That all depends on where the code lives.
In the depths of the system? If that is the case then I would gather some form of standard error handling should exist across the product, if not it needs to.
If it is on the presentation side for instance it may have no value to anyone except the code, and in that case additional logic may need to be placed in a finally block.
Or let it roll up hill altogether and don't wrap it in a try catch if you aren't going to do anything useful in the catch anyways.
… do something meaningful
To add to the excellent comments already provided.
There are three way to "re-throw" an exception:
catch (Exception ex)
{
throw;
}
The above preserves the call stack of the original exception.
catch (Exception ex)
{
throw ex;
}
The above eats the original exception chain and begins a new one.
catch (Exception ex)
{
throw new MyException("blah", ex);
}
The above adds the original exception to the InnerException of a new chain. This can be the best of both worlds, but which one is correct is highly dependent on what you need.
Your code can be rewritten (to eat exception) like this
try
{
… do something meaningful
}
catch
{
// eat exception
}
But I don't understand what you want to do by refactoring!!
Edit:
Re-throwing using throw; doesn't work always. Read this ->
http://weblogs.asp.net/fmarguerie/archive/2008/01/02/rethrowing-exceptions-and-preserving-the-full-call-stack-trace.aspx
In general, it's not a good idea to catch the general Exception unless you can actually handle it. I think the right answer is a combination of Tim's and Joshua's answers. If there are specific exceptions that you can handle and remain in a good state, for example FileNotFoundException you should catch it, handle it, and move on, as seen here:
try
{
// do something meaningful
}
catch(FileNotFoundException)
{
MessageBox.Show("The file does not exist.");
}
If you can't handle it and remain in a good state, don't catch it in the first place.
However, one case where you would want to catch the general Exception and re-throw it would be if you have any cleanup that you will need to do, for example aborting a database transaction, before the exception bubbles up. We can accomplish this by extending the previous example like so:
try
{
BeginTransaction();
// do something meaningful
CommitTransaction();
}
catch(FileNotFoundException)
{
MessageBox.Show("The file does not exist.");
AbortTransaction();
}
catch(Exception)
{
AbortTransaction();
throw; // using "throw;" instead of "throw ex;" preserves
// the stack trace
}
Refactor it to:
// No try
{
… do something meaningful
}
// No catch
and let the exception be handled at the main loop.
if the catch() block only rethrows exception and does not do any real exception handling then you don't need try..catch at all.
Part of the problem with eating exceptions is that it's inherently unclear what they're hiding. So... the question of the proper refactoring isn't easily answered. Ideally, however, you'd remove the try...catch clause entirely; it's unnecessary in most cases.
Best practice is to avoid try...catch entirely wherever possible; if you must deal with exceptions, then do so as locally and specifically as possible and don't propagate them up the stack; finally, include a global unhandled exception handler that does the appropriate logging (and perhaps offers to restart the application if necessary).
Unless the catch block actually does something with the exception (e.g., logging it to a system error file), there is no need to even have the try/catch block.
That being said, if the exception is worth informing the user about (e.g, logging it), then by all means use a catch block to do so.
One particularly bad pitfall of ignoring exceptions is that certain (fatal) exceptions should cause the program to terminate. Such exceptions (e.g., failure to load a class) leave the program in an unstable state, which will only lead to disaster later on in the execution. In these cases, logging the exception and then gracefully terminating is the only reasonable thing to do.
The particular way in which exceptions are eaten is not important. Never eat exceptions by any means!
Only catch exceptions that are expected to occur and which you can do something about. Examples of this include file and network IO, security exceptions, etc. For those cases you can display an explaination of what happened to the user, and sometimes you can recover gracefully.
Do not catch exceptions that should never occur. Examples of these are null-reference exceptions, invalid operation exceptions, etc. The code should be written so that these exceptions will never happen, so there is no need to catch them. If those exceptions are happending, then fix the bugs. Don't swallow the exceptions.
It is OK to log all exceptions, but this should be done with the unhandled exception handler on the program and any threads that are created. This is not done with a try/catch.
You can rethrow exception without losing call stack just re-throw as
catch(Exception e)
{
throw;
}
Why would you need this?
Usage example:
Somewhere in your app you have 3rd party code and you wrap it, and if it throws exceptions you throw WrappingException.
When you execute some other code you might get exception either from 3rdparty or either from your own so you may need:
try
{
//code that runs 3rd party
//your code, but it may throw Null ref or any other exception
}
catch( WrappingException)
{
throw;
}
catch( Exception e)
{
throw new MyAppLayer3Exception("there was exception...", e);
}
In this case you do not wrap WrappingException with your MyAppLayer3Exception.
So, at the top level of you application you may catch all exceptions and by knowing Type of exception you will know where from it came!
Hope it helps.
eating exceptions is not always "bad juju". There is no magic here; just write code to do what you need to do. As a matter of hygiene, if you catch an exception and ignore it, comment as to why you are doing it.
try
{
.....
}
catch (something)
{
// we can safely ignore ex becuase ....
}
Sometimes, it's just best not to deal with exceptions if you really don't want to deal with the added responsibility that comes with exceptions. For example, rather than catching an NullReferenceException, why not just make sure that the object exists before you try to do something with it?
if (yourObject != null)
{
... do something meaningful with yourObject ...
}
Exceptions are best reserved to handle those things you really have no control over, such as the sudden loss of a connection, or things which have the potential to kill a long-running process, such as a data import. When an exception is thrown, regardless of the reason, your application has reached a point of instability. You catch the exception to return the application to a point of stability by cleaning up the mess, e.g. disposing of the lost connection and creating a new one OR logging the line where the error occurred and advancing to the next line.
I've been dealing with exception handling for the last 15 years, starting with the first six versions of Delphi, up to (and including) .NET 1.0-4.0. It is a powerful tool, but it is a tool that is often overused. I have found consistently, during that time, the most effective exception handling process is deferring to if-then before try-catch.
One major problem with the exception hierarchy is that exceptions are categorized based upon what happened, rather than based upon the system state. Some exceptions mean "a function couldn't perform its task, but it didn't disturb the system state either". Others mean "Run for your lives! The whole system is melting down!" In many cases, it would be entirely proper for a routine which could handle the failure of a called method to swallow any and all exceptions of the former type; in other cases, such exceptions should be rethrown in a manner which indicates possible state corruption (e.g. because there was a failure in an operation necessary to reset the system state; even though the attempt to perform that operation didn't disturb anything, the fact that the state wasn't reset means it's corrupted).
It would be possible for one to manage one's own exceptions into such a hierarchy, but I don't know any good way to deal with other exceptions.

Catching specific vs. generic exceptions in c#

This question comes from a code analysis run against an object I've created. The analysis says that I should catch a more specific exception type than just the basic Exception.
Do you find yourself using just catching the generic Exception or attempting to catch a specific Exception and defaulting to a generic Exception using multiple catch blocks?
One of the code chunks in question is below:
internal static bool ClearFlags(string connectionString, Guid ID)
{
bool returnValue = false;
SqlConnection dbEngine = new SqlConnection(connectionString);
SqlCommand dbCmd = new SqlCommand("ClearFlags", dbEngine);
SqlDataAdapter dataAdapter = new SqlDataAdapter(dbCmd);
dbCmd.CommandType = CommandType.StoredProcedure;
try
{
dbCmd.Parameters.AddWithValue("#ID", ID.ToString());
dbEngine.Open();
dbCmd.ExecuteNonQuery();
dbEngine.Close();
returnValue = true;
}
catch (Exception ex)
{ ErrorHandler(ex); }
return returnValue;
}
Thank you for your advice
EDIT: Here is the warning from the code analysis
Warning 351 CA1031 : Microsoft.Design : Modify 'ClearFlags(string, Guid)' to catch a more specific exception than 'Exception' or rethrow the exception
You should almost never catch the top level Exception.
In most cases you should catch and handle the most specific exception possible and only if there is something useful you can do with it.
The exception (haha) to this is if you are catching for logging and re-throw the exception, then it is sometimes OK to catch a top level Exception, log it and rethrow it.
You should almost never catch a top level Exception and swallow it. This is because if you are catching a top level exception you don't really know what you are handling; absolutly anything could have caused it so you will almost certainly not be able to do anything that will handle every single failure case correctly. There probably are some failures that you may just want to silently handle and swallow, but by just swallowing top level Exceptions you'll also be swallowing a whole bunch that really should have been thrown upwards for your code to handle higher up. In your code example what you probably want to do is handle a SQLException and log+swallow that; and then for an Exception, log and rethrow it. This covers yourself. You're still logging all exception types, but your only swallowing the fairly predictable SQLException which indicates problems with your SQL/database.
A common practise is to only every handle exceptions that you can actually resolve at that point, if you can't resolve it at that point in code then you allow it to bubble upwards. If you can't resolve it at the next level up, allow it to continue up. If it reaches the top unhandled then display a polite appology to the user (perhaps attempt a quick autosave) and close the app. It's generally considered worse to allow an app to continue running after an unhandled exception because you can't predict the state of the application as something exceptional has occured. It's better just to shutdown and restart the app to get back to an expected state.
Have a look at this article by Krzysztof Cwalina, which I've found very helpful in understanding when to catch or ignore exceptions:
How to Design Exception Hierarchies
All the principles it describes about designing exception hierarchies are also applicable when deciding when to catch, throw, or ignore exceptions. He divides exceptions into three groups:
Usage errors, such as DivideByZeroException, which indicate errors in code; you shouldn't handle these because they can be avoided by changing your code.
Logical errors, such as FileNotFoundException, which you need to handle because you can't guarantee they won't happen. (Even if you check for the file's existence, it could still be deleted in that split-second before you read from it.)
System failures, such as OutOfMemoryException, which you can't avoid or handle.
You should read a general paper or google "Structured Exception Handling" and get a better big picture of what this topic is all about, but in general, catching every exception is considered bad practice because you have no idea what the exception was (Memory fault, out of memory error, Disk failure, etc.).
And for many unknown/unexpected exceptions, you should not be allowing the application to continue. In general, you "catch" and handle only those exceptions toy have determined, as a result of an analysis of the method you are coding the catch clause for, that method can in fact create, and that you can do something about. The only time you should catch all exceptions (catch Exception x) is to do something like logging it, in which case you should immediately rethrow the same exception (whatever it was) so that it can bubble up the stack to some general "Unhandled Exception Handler" which can display an appropriate message to the user and then cause the application to terminate.
Yes,
You should catch from the most specific exception down to the least, so you can deal with things in an appropriate manner.
For example, if you were making a web request, you should catch things like TimeOuts and 404s first, then you can inform the end user they should retry (timeout) and/or check they URL they entered.
Then you could catch something less general, in case something a bit more wacky goes wrong, then fall right back to just catching an Exception in the case that something ridiculous happens.
As a best practice, you should avoid catching Exception and using flags as return values.
Instead, you should design custom exceptions for expected exceptions and catch those directly. Anything else should bubble up as an unexpected exception.
In your example above, you may want to rethrow a more business specific Exception.
I agree that, in general, you should only catch exceptions you're expecting and understand how to handle. A few cases where I often don't do this:
As mentioned above, if I'm capturing some sort of useful information to log and then rethrow.
If I'm performing an asynchronous operation, such as handling queued messages or jobs in a worker thread, and I want to catch the exception for rethrowing in a different context. I also often use an ugly hack here that tricks the CLR into appending stack trace information, so that it's not lost when rethrowing in the new context.
If I'm working with an isolated task or operation and I can handle the exception by shutting down the task, without shutting down the whole application. I often wish here that there were a top-level exception for truly fatal exceptions (like OutOfMemoryException), as I've been ignoring these. The proper way to handle this would be to run the isolated task in its own AppDomain, but I haven't had the available schedule time to implement this on a project yet.
I agree with the code analysis tool. My exception to the rule is that I catch the general exception in my event handlers and the user is given the option to report the error or to ignore it.
In the example you provide, I think the code analysis got it right. If you can't handle a specific exception right there, you shouldn't be catching anything at all and let it bubble up to the highest level. That way you'll have a much easier time recreating the issue when you try to fix it.
You could make your example better by adding the connection string and the ID value to the exception's Data property and be sure it is logged as well. That way you give yourself a fighting chance at reproducing the error.

Why do exceptions propogate out of an event handler?

Consider the following program. How is the behaviour that it displays (namely that exceptions will propagate out of an event handler) a "good thing"? As far as I can tell, it could only ever be bad; unexpected exceptions popping up from functions that they shouldn't. In my particular case, it was killing threads. So, is this behaviour actually a good thing in some cases? Is this a reason to say that letting exceptions out of event-handlers is poor design?
static class Program {
static void Main()
{
Foo foo = new Foo();
foo.SomeEvent += ThrowException;
try
{
foo.OnSomeEvent();
}
catch (Exception)
{
// This is printed out
Console.WriteLine("Exception caught!");
}
}
static void ThrowException(object sender, EventArgs e)
{
throw new Exception();
}
}
// Define other methods and classes here
class Foo
{
public event EventHandler SomeEvent;
public void OnSomeEvent()
{
SomeEvent(this, EventArgs.Empty);
}
}
What's your preferred alternative - silently swallowing the exception? I wouldn't like that at all.
Events are just a way of implementing the observer pattern, really. If a listener throws an exception, I'd absolutely expect that exception to be thrown back to the caller. Any other behaviour I can think of would effectively treat the exception as unimportant. The whole point of exceptions is that when something goes wrong, you find out about it quickly and implicitly. You have to explicitly handle exceptions, so that you don't go on your merry way in a corrupt state without realising it.
You make a valid point about whose responsibility it is to handle exceptions. Broadly speaking, I find it best to assume that just about anything can throw an exception at any time. Other than special cases where I know a specific exception may occur and I can handle it, I don't usually catch exceptions other than at the top level - except possibly to wrap and rethrow, or log and rethrow.
Now it's possible that one of your event handlers really shouldn't be throwing an exception - that they haven't really run into an error condition - but what should happen if it's a perfectly reasonable exception which indicates a serious problem? While a program crashing is ugly, it's often better than continuing with some of it malfunctioning, possibly corrupting persisted state etc.
Fundamentally, I don't think the CS/SE field has got error handling "right" yet. I'm not even sure that there is an elegant way of doing the right thing which is simple to express in all situations... but I hope that the current situation isn't as good as it gets.
The main aspect of exception handling discussed here is: do not catch exception if you don't know how to handle it. But let's talk about the observer pattern, where notifier emits event (or signal) about it's state change and listeners handle it. A good example of a notifier is a button emitting 'clicked' event. Does a button care about who are the listeners and what they do? Not really. If you're a listener and you got this event, then you've got a job to do. And if you can't do it, you have to handle this error or inform user, because passing exception to the button makes no sense - button definitely does not know how to handle errors of listener job. And buttons state changer (probably some message loop) does not either - your application will end up at Main() with a crash.
That's how observer pattern works - event emitters don't know what their listeners are doing and there's very little chance they will handle this exception properly.
Also bear in mind, that if your exception handler throws exception, there may be other listeners that won't receive notification and that may lead to undefined application state.
So my advice is to catch all exceptions at event handler, but figure out how to handle them there. Or else no one will.
My personal prejudice is that not catching exceptions is generally a bad thing. The only "exception" to this rule for me is for simple applciations where the uncaught exception termianates the process, you see the error and fix it.
For multi-threaded apps, if the default behaviour of uncaught exceptions is to zap threads then it seems to me absurd not to catch exceptions. Hence event handlers should not just punt the exception up the stack and hope for the best.
Silently swallowing exceptions is usually bad too, something bad has happended it needs fixing. So perhaps log a message, and then return?
You need a contract with the event source on whether the event handler can throw exceptions. For example, if a COM object is an event source this is strictly prohibited - exceptions should never cross COM boundary.
An event is nothing more than syntactic sugar around a function call, so it makes sense that it would propagate up to the function that raised the event. What, otherwise, should the behaviour be? The exception has to go somewhere.
It would be the best to think about exception as part of your contract with event listeners.
Which means, if the listener is nice and catches its Exceptions (it can do that for known ones), you are OK.
For the rest, unknown exceptions, or in Java speech "Runtime exceptions", you need to be ready for them the same way as if they would occur in your code.
What I am trying to say is, if you are building a contract with the event listeners, you cannot force them to throw just one exception type (so that you can consume them) and you need to take all Exceptions seriously. After all, they are indications of "wrong states" which you don't want to hide for consumers.

Categories

Resources