Using events rather than exceptions to implement error handling - c#

I'm working on some code that uses a pattern in its business and data tiers that uses events to signal errors e.g.
resource = AllocateLotsOfMemory();
if (SomeCondition())
{
OnOddError(new OddErrorEventArgs(resource.StatusProperty));
resource.FreeLotsOfMemory();
return;
}
This looked superficially rather odd, especially as the code that calls this needs to hook into the events (there are four or five different ones!).
The developer tells me that this way they can refer to the properties of the allocated resource in the error handling code, and that responsibility for cleaning up after the error is kept by this tier.
Which makes some kind of sense.
The alternative might be something like
resource = AllocateLotsOfMemory();
if (SomeCondition())
{
BigObject temporary = resource.StatusProperty;
resource.FreeLotsOfMemory();
throw new OddException(temporary);
}
My questions are:
As this "BigObject" is freed when the exception object is released, do we need this pattern?
Has anyone else experience of this pattern? If so, what pitfalls did you find? What advantages are there?
Thanks!

It seems odd to me too. There are a few advantages - such as allowing multiple "handlers" but the semantics are significantly different to normal error handling. In particular, the fact that it doesn't automatically get propagated up the stack concerns me - unless the error handlers themselves throw an exception, the logic is going to keep going as if everything was still okay when it should probably be aborting the current operation.
Another way of thinking about this: suppose the method is meant to return a value, but you've detected an error early. What value do you return? Exceptions communicate the fact that there is no appropriate value to return...

This looks really odd to me, firstly IDisposable is your friend, use it.
If you are dealing with errors and exceptional situations you should be using exceptions, not events, as its much simpler to grasp, debug and code.
So it should be
using(var resource = AllocateLotsOfMemory())
{
if(something_bad_happened)
{
throw new SomeThingBadException();
}
}

If you think in terms of "Errors" and "Warnings", I've had lots of luck when reserving events for the "Warning" category and Exceptions for the "Errors" category.
The rationale here is that events are optional. No one is holding a gun to your head forcing you to handle them. That's probably okay for warnings, but when you have genuine errors you want to make sure they are taken a little more seriously. Exceptions must be handled, or they'll bubble up and create a nasty message for the user.
With regards to your Big Object question: you definitely don't be passing big objects around, but that doesn't mean you can't pass references to big objects around. There's a lot of power in the ability to do that.
As an addendum, there's nothing stopping from from raising an event in addition to the exception, but again: if you have a genuine error you want something to force the client developer to handle it.

Take a look at this post by Udi Dahan. Its an elegant approach for dispatching domain events. The previous poster is correct in saying that you should not be using an event mechanism to recover from fatal errors, but it is a very useful pattern for notification in loosely coupled systems:
public class DomainEventStorage<ActionType>
{
public List<ActionType> Actions
{
get
{
var k = string.Format("Domain.Event.DomainEvent.{0}.{1}",
GetType().Name,
GetType().GetGenericArguments()[0]);
if (Local.Data[k] == null)
Local.Data[k] = new List<ActionType>();
return (List<ActionType>) Local.Data[k];
}
}
public IDisposable Register(ActionType callback)
{
Actions.Add(callback);
return new DomainEventRegistrationRemover(() => Actions.Remove(callback)
);
}
}
public class DomainEvent<T1> : IDomainEvent where T1 : class
{
private readonly DomainEventStorage<Action<T1>> _impl = new DomainEventStorage<Action<T1>>();
internal List<Action<T1>> Actions { get { return _impl.Actions; } }
public IDisposable Register(Action<T1> callback)
{
return _impl.Register(callback);
}
public void Raise(T1 args)
{
foreach (var action in Actions)
{
action.Invoke(args);
}
}
}
And to consume:
var fail = false;
using(var ev = DomainErrors.SomethingHappened.Register(c => fail = true)
{
//Do something with your domain here
}

1) is it needed? no pattern is absolutely necessary
2) Windows Workflow Foundation does this with all the results from the Workflow Instances running inside the hosted runtime. Just remember that exceptions can happen when trying to raise that event, and you might want to do your cleanup code on a Dispose or a finally block depending on the situation to ensure it runs.

To be honest, events signaling errors strikes me as scary.
There's a disagreement between camps around returning status codes and throwing exceptions. To simplify (greatly) : The status code camp says that throwing exceptions places detecting and handling the error too far from the code causing the error. The exception throwing cap says that users forget to check status codes and exceptions enforce error handling.
Errors as events seems like the worst of both approaches. The error cleanup is completely separate from the code causing the error, and notification of error is completely voluntary. Ouch.
To me, if the method did not fulfill it's implicit or explicit contract (it didn't do what it was supposed to do), an exception is the apropriate response. Throwing the information you need in the exception seems reasonable in this case.

The first snippet should probably be
resource = AllocateLotsOfMemory();
if (SomeCondition())
{
try
{
OnOddError(new OddErrorEventArgs(resource.StatusProperty));
return;
}
finally
{
resource.FreeLotsOfMemory();
}
}
otherwise you won't free your resources when the event handler throws an exception.
As Mike Brown said, the second snippet also has a problem if resource.FreeLotsOfMemory() messes with the contents of resource.StatusProperty instead of setting it to null.

We have a base Error object and ErrorEvent that we use with the command pattern in our framework to handle non-critical errors (e.g. validation errors). Like exceptions, people can listen for the base ErrorEvent or a more specific ErrorEvent.
Also there's a significant difference between your two snippets.
if resource.FreeLotsOfMemory() clears out the StatusProperty value rather than just setting it to null, your temporary variable will be holding an invalid object when OddException is created and thrown.
The rule of thumb is that Exceptions should only be thrown in non-recoverable situations. I really wish C# supported a Throws clause that's the only thing I really miss from Java.

Another major problem with this approach are concurrency concerns.
With traditional error handling, locks will be released as control moves up the call stack to the error handler in a controlled manner. In this scheme, all locks will still be held when the event is invoked. Any blocking that occurs within the error handler (and you might expect some if there's logging) would be a potential source of deadlocks.

Related

try-catch instead of if in edge cases

Would it be a good idea to replace the if statements with try-catch in the following usecases (performance and readability wise?):
Example 1
public static void AddInitializable(GameObject initializable)
{
if(!HasInstance)
{ // this should only happen if I have forgotten to instantiate the GameManager manually
Debug.LogWarning("GameManager not found.");
return;
}
instance.initializables.Add(initializable);
initializable.SetActive(false);
}
public static void AddInitializable2(GameObject initializable)
{
try
{
instance.initializables.Add(initializable);
initializable.SetActive(false);
}
catch
{
Debug.LogWarning("GameManager not found.");
}
}
Example 2
public static void Init(int v)
{
if(!HasInstance)
{// this should happen only once
instance = this;
}
instance.alj = v;
}
public static void Init2(int v)
{
try
{
instance.alj = v;
}
catch
{
instance = this;
Init(v);
}
}
Edit:
Question 2: How many Exceptions can I get to be still performance positive?
It depends.
Try-blocks are generally cheap, so when the exception is not thrown, that would be an acceptable solution. But: In your case, if the condition is not satisfied (meaning the thing was not initialized before that method was called), this is a programming error, not something that should ever happen in the finished program. It is perfectly valid that such errors crash the program. Makes spotting the bugs and fixing them much easier in development, and avoids that you silently hide it (in example 1, you silently don't do anything, which might cause confusing behavior later).
So: If it would be a programming error, don't use an exception handler, nor a test (except maybe an Assert). Just let the program crash (with a NullReferenceException in this case).
I would agree with PMF: Depends!
On your specific use case and in specific whether something is your fault or something you can't control / predict.
So in general I'd say there are three ways of how to handle stuff that isn't behaving as expected
A) let throw an exception to indicate that this is really bad and there is no way to recover => and most probably crash your app
This usually makes totally sense on development time because while debugging you explicitly want your app to crash so you can find and fix the issue.
This should be happening for everything where the cause is basically something that you messed up and can be fixed by you. (In your case instance not initialized correctly)
B) return something e.g. false to indicate that something went bad but allow this to be handled by the code and e.g. try something else.
In my eyes this should be the preferred way of dealing with stuff you can't control yourself like e.g. user input and other unpredictable conditions like internet connectivity etc.
C) Just ignore it and do nothing at all.
Depends of course on what exactly you are doing but this should actually happen almost never. For a User this can be extremely frustrating and also for you as developer it makes debugging hard to impossible!
In combination with B of course this is valid since something else will already have delt with the issue.
And to add just in general unless you work on some core / reused library I would actually never throw exceptions myself except you are re-throwing caught ones to add additional debugging information. This basically falls under "you can't control" how others will use your library -> this basically from your perspective falls under user input ;)
Now all three options can be achieved by try - catch or if checks internally of course and it depends on your specific case which way you want to go.
Some thoughts of mine on this
Readability wise I would prefer the if already alone because it makes clear exactly which condition is checked. When I see a try - catch I don't know exactly at which point which exact exception might be thrown on first glance.
Thus using try - catch as a replacement for if just obscures what exactly is failing and makes debugging hard to impossible
Exceptions are quite expensive! So performance wise I would say use if wherever possible.
There are cases though - and in my opinion these are the only ones where try - catch would be allowed - where you use a library and there simply is no way to prevent an exception.
Example: FileIO
the file you want to access does not exist
-> You don't need try - catch for this (in my eyes it would be the lazy way). This is something you can and should actually check first if(!File.Exists(...)) so your program can correctly deal with it and handle that case (e.g. you might want to tell the user instead of simply crash or doing nothing).
The file is currently opened by another program so you can't write to it.
-> There is no way to find this out beforehand. You will get an exception and can't avoid it. Here you want to try - catch in order to still allow your code to deal with such case (as before e.g. tell the user instead of simply crash).
But then how you actually deal with them again depends:
If you e.g. use some hardcoded paths and these files definitely should be there -> Exception because it means you as developer messed something up.
If the path comes from user input -> Catch because this is something you as developer can't control but don't just want your app to crash, rather show a hint to the user that he messed it up.
Now in your use case the Example 1 both of your solutions seem pretty bad to me. You go with the last option C and just ignore the call - a user won't see the warning and also a developer might just not note / ignore it.
You definitely want to get an Exception here if this means that your app will not behave correctly and not catch it at all!
In general there is no need for a special bool flag. I would rather go with
if(instance == null)
{
Debug.LogError(...);
return;
}
Because this is most probably a more severe error not only a warning so it at least gains visibility.
In your Example 2 you actually have kind of a lazy initialization anyway so either way the call itself is basically valid.
In such case though again this is something you can easily check and I would not wait for an exception (especially not simply any) because I already know that there definitely will be one at least once.
In my opinion this should rather be
if(instance == null)
{
// I have put `???` because, well, in a "static" method there is no "this" so
// I wonder where the instance should come from in that case ;)
instance = ???;
}
instance.alj = v;
So you're kind of along the right lines here.
Unless you are in dire need of increasing performance, don't try to optimize, and if you do need to optimize, make sure you're doing it right (exceptions are more expensive that if statements, especially if you know they're going to happen)
The first example you've given, I can kind of get behind. You're making the assumption that something was initialized, and if it turns out it wasn't, throw an error. You're logging it, it's ok, you initialize it and you'll probably never have to worry about that exception again.
The second example you've given is a big no no. You should not use exceptions to fall into other logic in your application. Instead, in the Init() method, just always have the line 'instance = this', don't do the if statement. Once you know it's initialized, there should never be a reason for it to throw an exception when used.
Of course, don't go crazy with this, exceptions should only be used for exceptional circumstances. If you write your code and are thinking 'Hmm, so it could be either A scenario or B scenario, and in B scenario I want this to happen, so I'll throw an exception' that's completely the wrong line of thinking. Instead it should be 'Hmm, so all this will happen, but just in case something breaks, I'll put it in a try catch and log it, as who knows, I'm not infallible'
You can see how I've applied the above logic to your two examples,
To my point of view, this is not a good idea.
We usually use try catch when we know what kind of exceptions will appear in the context, and hence a catch without exception type is not a good practice. Moreover, try catch is not expensive only if the exception rarely happens.
In your scenario, since you already know the only problem is that the property HasInstance may be false, you could directly check it with if statement. Using try catch seems more like a cost here, although it works. This seems like you are expecting an error, and you just ignore that error because its message does not matter.
Besides, I see you are using Unity and are creating a singleton GameManager, and actually I think the singleton pattern here might not be quite correct.
For example, if you use the code like this, actually there is virtually no possibility it does not have an instance if you treat your scene and gameobjects properly :)
Exceptions are there when an "impossible" state occurs in your interfaces (Not the keyword - just the word), if you have to try - catch inside your business logic, your design is compromised.
In this case, you would likely gain both extendability, and readability, if you implement the slightly miss-named null-object pattern. (Should be called default object pattern)
And simply never be able to pass a null'ed interface to the method.
So:
public interface IGameObject {
void Activate(instance initializable);
}
public class GameObjectDefault : IGameObject {
public void Activate(instance initializable){
--Does nothing on purpose
}
}
public class GameObjectReal : IGameObject {
private Instance _instance;
public GameObjectReal(Instance instance)
{
_instance = instance;
}
public void Activate(IGameObject initializable) {
_instance.initializables.Add(initializable);
--Do whatever you need to do to the object
}
}
This is pseudo, because I can't see your whole system.
But this way, if you initialize all game objects as DefaultGameObjects, your activate or any other method, will just do nothing.
Now, there is no reason to check for null.
And no reason to do a try catch. Your impossible state, is now, literally, impossible.

Try-Catch or Result object for making rest requests?

We have two versions of a wrapper method/class for making rest requests and converting them to objects in our project. This wrapper method handles various things like preventing us from going over limits among other things.
The first version uses a result object and never throws exceptions like so:
var result = JsonPost1<CustomObject>("/resource");
if(result.data != null)
{
CustomObject obj = result.data;
//Do logic with object here
}
else if(result.statusCode == HttpStatus.NotFound)
{
//Handle issue.
}
The second one uses a custom exception instead and returns the object directly:
try
{
CustomObject obj = JsonPost2("/resource");
//Do logic with object here
}
catch(CustomNotFoundException e)
{
// Handle issue
}
In at least 99% of requests the exception will not be hit. Which method is generally a better approach and why? Or is there a better approach than either of these?
IMHO - Exceptions should only be used for exceptional things.
Do not use exceptions for things you can check in code.
However, this does not mean that your wrapper class should handle any possible response from the service - Only the common ones.
Ideally, if your service has a unified API (meaning all possible responses share at least some of their properties (like Status and ErrorDescription), you would want to handle that in your wrapper class. Anything that is used only in a specific type of response should be handled after you get the data from the wrapper class.
Update
Microsoft's Best practices for exceptions page states:
The method to choose depends on how often you expect the event to occur.
Use exception handling if the event doesn't occur very often, that is, if the event is truly exceptional and indicates an error (such as an unexpected end-of-file). When you use exception handling, less code is executed in normal conditions.
Check for error conditions in code if the event happens routinely and could be considered part of normal execution. When you check for common error conditions, less code is executed because you avoid exceptions.
(emphasis mine)
This might be interpreted as the first option you've shown, if the fact that the data was not found is not considered an error (as the specific business logic dictates).
However, it might also be interpreted as the second option you've shown - since the catch clause will only be activated in 1% of the cases.
I still stand by my original answer, though. If the fact that the data was not found is not an error, it should be handled with a condition and not with a try...catch.

Catching all exceptions for detailed logging purposes - pros and cons

I'm in the middle of writing a saving and loading system that saves game objects to a JSON compatible format and loads them back. Saving objects is fine and fairly fool-proof. However, I'm in the process of trying to make the loading process more bullet-proof and easier for me to pin-point errors. Obviously as I'm loading data from a JSON file, everything is being converted from strings, with the potential for all kinds of user error.
Each objects loading method contains something similar to this ---
public void Load()
{
try
{
// Deserialize..
// Potential for all kinds of exceptions, invalid casts, missing info, etc..
// For eg:
bool active = data.GetField("active").Value<bool>();
// GetField() throws an exception if the field doesn't exist.
// Value<T>() throws an exception if it's an invalid cast, etc.
}
catch(Exception e)
{
// ..and those exceptions get caught and logged here.
Logger.LogError(e.ToString, this);
}
}
One of the benefits of catching all the exceptions in the objects Load method is that when 'LogError()' is called with the object as a parameter like shown, it will highlight the offending object in the IDE hierarchy that threw the error (whichever one it may be) making it very quick to find the object with the error and debug it's script or saved data.
Is this an appropriate usage of throwing and catching exceptions, or is there a better design pattern I should be implementing?
Thanks for your time,
Sam
There are always a lot of different but close opinions about catching the exceptions, but for your task the given approach is simple and viable. The only thing I'd recommend for you to do is to allow the exception to bubble up:
catch(Exception e)
{
// ..and those exceptions get caught and logged here.
Logger.LogError(e.ToString, this);
throw;
}
Logging is a good idea, but what should your program do if the loading fails? Just log it out and continue? It can be the case, but this load method looks like important and integral part of your program. It does not look like some background work-that-may-fail-or-work-I-don't-care. Well, its your program and I don't know the requirements or context - just an opinion of mine.
The main principle you should base your exception handling on is: to catch exception only when and where you can do something with them (retry, get some relevant current data in the method...), or otherwise catch them
as high in the call hierarchy as possible (in your main loop or global exception handler - the higher the better, it means less exception handling for you to duplicate). And if you can't do anything with exception that would guarantee the consistency of your program state - don't catch it.
Ideally all classes should be resilient to failure - if they fail, they either fail and don't do anything afterwards or restore their state to normal. And the most ideal solution is if they rolled back any action's side effects in case of exceptions - transaction-like behaviour. But in real life it is a difficult goal to achieve.
Also, if you don't like similar try-catch constructs for logging everywhere in your code (they are important , but they aren't doing any real job - their presence isn't necessary for the understanding of the main workflow), you may try some of the Aspect Oriented Programming technologies.
Your question still missing many basic things like what kind of object "data" is, is it a string , class or any other type.
Well catching exception is never good for performance as long as your code handle all possible exceptions that might occur.
There can still be a scenario where exception is thrown.
I would suggest to check for field instead of directly calling field with that name, e,g,
bool active = data.HasField("active") ? data.GetField("active").Value<bool>() : false;
Also, In catch as common scenario better to pass exception object rather than e.Tostring()
something like :
Logger.LogError(e, this);
To conclude it really depends on application to applications or rather requirement to requirements.
In web Application, I usually create HttpModule for logging exception so that I dont have to write catch block everywhere in my code.
public class ExceptionModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.Error += new EventHandler(OnError);
}
private void OnError(object sender, EventArgs e)
{
//write logging exception logic.
}
}

Best Practice way to indicate that a server request has failed?

I am writing an API that connects to a service which either returns a simple "Success" message or one of over 100 different flavors of failure.
Originally I thought to write the method that sends a request to this service such that if it succeeded the method returns nothing, but if it fails for whatever reason, it throws an exception.
I didn't mind this design very much, but on the other hand just today I was reading Joshua Bloch's "How to Design a Good API and Why it Matters", where he says "Throw Exceptions to indicate Exceptional Conditions...Don't force client to use exceptions for control flow." (and "Conversely, don't fail silently.")
On the other-other hand, I noticed that the HttpWebRequest I am using seems to throw an exception when the request fails, rather than returning a Response containing a "500 Internal Server Error" message.
What is the best pattern for reporting errors in this case? If I throw an exception on every failed request, am I in for massive pain at some point in the future?
Edit: Thank you very kindly for the responses so far. Some elaboration:
it's a DLL that will be given to the clients to reference in their application.
an analogous example of the usage would be ChargeCreditCard(CreditCardInfo i) - obviously when the ChargeCreditCard() method fails it's a huge deal; I'm just not 100% sure whether I should stop the presses or pass that responsibility on to the client.
Edit the Second:
Basically I'm not entirely convinced which of these two methods to use:
try {
ChargeCreditCard(cardNumber, expDate, hugeAmountOMoney);
} catch(ChargeFailException e) {
// client handles error depending on type of failure as specified by specific type of exception
}
or
var status = TryChargeCreditCard(cardNumber, expDate, hugeAmountOMoney);
if(!status.wasSuccessful) {
// client handles error depending on type of failure as specified in status
}
e.g. when a user tries to charge a credit card, is the card being declined really an exceptional circumstance? Am I going down too far in the rabbit hole by asking this question in the first place?
Here's a short list of things to consider. While not comprehensive, I believe these things can help you write better code. Bottom line: Don't necessarily perceive exception handling as evil. Instead, when writing them, ask yourself: How well do I really understand the problem I am solving? More often than not, this will help you become a better developer.
Will other developers be able to read this? Can it be reasonably understood by the average developer? Example: ServiceConnectionException vs. a confusing ServiceDisconnectedConnectionStatusException
In the case of throwing an exception, how exceptional is the circumstance? What does the caller have to do in order to implement the method?
Is this exception fatal? Can anything really be done with this exception if it is caught? Threads aborting, out of memory.. you can't do anything useful. Don't catch it.
Is the exception confusing? Let's say you have a method called Car GetCarFromBigString(string desc) that takes a string and returns a Car object. If the majority use-case for that method is to generate a Car object from that string, don't throw an exception when a Car couldn't be determined from the string. Instead, write a method like bool TryGetCarFromBigString(string desc, out Car).
Can this be easily prevented? Can I check something, let's say the size of an array or a variable being null?
For code readability's sake, let's potentially take a look at your context.
bool IsServiceAlive()
{
bool connected = false; //bool is always initialized to false, but for readability in this context
try
{
//Some check
Service.Connect();
connected = true;
}
catch (CouldNotConnectToSomeServiceException)
{
//Do what you need to do
}
return connected;
}
//or
void IsServiceAlive()
{
try
{
//Some check
Service.Connect();
}
catch (CouldNotConnectToSomeServiceException)
{
//Do what you need to do
throw;
}
}
static void Main(string[] args)
{
//sample 1
if (IsServiceAlive())
{
//do something
}
//sample 2
try
{
if (IsServiceAlive())
{
//do something
}
}
catch (CouldNotConnectToSomeServiceException)
{
//handle here
}
//sample 3
try
{
IsServiceAlive();
//work
}
catch (CouldNotConnectToSomeServiceException)
{
//handle here
}
}
You can see above, that catching the CouldNotConnectToSomeServiceException in sample 3 doesn't necessarily yield any better readability if the context is simply a binary test. However, both work. But is it really necessary? Is your program hosed if you can't connect? How critical is it really? These are all factors you will need to take in to account. It's hard to tell since we don't have access to all of your code.
Let's take a look at some other options that most likely lead to problems.
//how will the code look when you have to do 50 string comparisons? Not pretty or scalable.
public class ServiceConnectionStatus
{
public string Description { get; set; }
}
and
//how will your code look after adding 50 more of these?
public enum ServiceConnectionStatus
{
Success,
Failure,
LightningStormAtDataCenter,
UniverseExploded
}
I think you need to consider a few things in your design:
1) How will the API be accessed? If you are exposing it over web services, then throwing exceptions are probably not a good idea. If the API is in a DLL that you are providing for people to reference in their applications, then exceptions may be ok.
2) How much additional data needs to travel with the return value in order to make the failure response useful for the API consumer? If you need to provide usable information in your failure message (i.e. user id and login) as opposed to a string with that information embedded, then you could utilize either custom exceptions or an "ErrorEncountered" class that contains the error code and other usable information. If you just need to pass a code back, then an ENum indicating either success (0) or failure (any non-zero value) may be appropriate.
3) Forgot this in the original response: exceptions are expensive in the .Net framework. If your API will be called once in awhile, this doesn't need to factor in. However, if the API is called for every web page that is served in a high-traffic site, for example, you definitely do not want to be throwing exceptions to indicate a request failure.
So the short answer, is that it really does depend on the exact circumstances.
I really like the "Throw Exceptions to indicate Exceptional Conditions" idea. They must have that name for a reason.
In a regular application, you would use File.Exists() prior to a File.Open() to prevent an exception from being thrown. Expected errors as exceptions are hard to handle.
In a client-server environment though, you may want to prevent having to send two requests and create a FileOpenResponse class to send both status and data (such as a file handle, in this case).

Best practices for exception management in Java or C# [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I'm stuck deciding how to handle exceptions in my application.
Much if my issues with exceptions comes from 1) accessing data via a remote service or 2) deserializing a JSON object. Unfortunately I can't guarantee success for either of these tasks (cut network connection, malformed JSON object that is out of my control).
As a result, if I do encounter an exception I simply catch it within the function and return FALSE to the caller. My logic is that all the caller really cares about is if the task was successful, not why it is wasn't successful.
Here's some sample code (in JAVA) of a typical method)
public boolean doSomething(Object p_somthingToDoOn)
{
boolean result = false;
try{
// if dirty object then clean
doactualStuffOnObject(p_jsonObject);
//assume success (no exception thrown)
result = true;
}
catch(Exception Ex)
{
//don't care about exceptions
Ex.printStackTrace();
}
return result;
}
I think this approach is fine, but I'm really curious to know what the best practices are for managing exceptions (should I really bubble an exception all the way up a call stack?).
In summary of key questions:
Is it okay to just catch exceptions but not bubble them up or formally notifying the system (either via a log or a notification to the user)?
What best practices are there for exceptions that don't result in everything requiring a try/catch block?
Follow Up/Edit
Thanks for all the feedback, found some excellent sources on exception management online:
Best Practices for Exception Handling | O'Reilly Media
Exception Handling Best Practices in .NET
Best Practices: Exception Management (Article now points to archive.org copy)
Exception-Handling Antipatterns
It seems that exception management is one of those things that vary based on context. But most importantly, one should be consistent in how they manage exceptions within a system.
Additionally watch out for code-rot via excessive try/catches or not giving a exception its respect (an exception is warning the system, what else needs to be warned?).
Also, this is a pretty choice comment from m3rLinEz.
I tend to agree with Anders Hejlsberg and you that the most callers only
care if operation is successful or not.
From this comment it brings up some questions to think about when dealing with exceptions:
What is the point this exception being thrown?
How does it make sense to handle it?
Does the caller really care about the exception or do they just care if the call was successful?
Is forcing a caller to manage a potential exception graceful?
Are you being respectful to the idoms of the language?
Do you really need to return a success flag like boolean? Returning boolean (or an int) is more of a C mindset than a Java (in Java you would just handle the exception) one.
Follow the error management constructs associated with the language :) !
It seems odd to me that you want to catch exceptions and turn them into error codes. Why do you think the caller would prefer error codes over exceptions when the latter is the default in both Java and C#?
As for your questions:
You should only catch exceptions that you can actually handle. Just
catching exceptions is not the right thing to do in most cases.
There are a few exceptions (e.g. logging and marshalling exceptions
between threads) but even for those cases you should generally
rethrow the exceptions.
You should definitely not have a lot of try/catch statements in your
code. Again, the idea is to only catch exceptions you can handle.
You may include a topmost exception handler to turn any unhandled
exceptions into something somewhat useful for the end user but
otherwise you should not try to catch each and every exception in
every possible place.
This depends on the application and the situation. If your building a library component, you should bubble up exceptions, although they should be wrapped to be contextual with your component. For example if your building an Xml Database and let's say you are using the file system to store your data, and you are using file system permissions to secure the data. You wouldn't want to bubble up a FileIOAccessDenied exception as that leaks your implementation. Instead you would wrap the exception and throw an AccessDenied error. This is especially true if you distribute the component to third parties.
As for if it's okay to swallow exceptions. That depends on your system. If your application can handle the failure cases and there is no benefit from notifying the user why it failed then go ahead, although I highly recommend that your log the failure. I've always found it frustating being called to help troubleshoot an issue and find they were swallowing the exception (or replacing it and throwing a new one instead without setting the inner exception).
In general I use the following rules:
In my components & libraries I only catch an exception if I intend to handle it or do something based on it. Or if I want to provide additional contextual information in an exception.
I use a general try catch at the application entry point, or the highest level possible. If an exception gets here I just log it and let it fail. Ideally exceptions should never get here.
I find the following code to be a smell:
try
{
//do something
}
catch(Exception)
{
throw;
}
Code like this serves no point and should not be included.
I would like to recommend another good source on the topic. It's an interview with inventors of C# and Java, Anders Hejlsberg and James Gosling respectively, on the topic of Java's Checked Exception.
Failure and Exceptions
There are also great resources at the bottom of the page.
I tend to agree with Anders Hejlsberg and you that the most callers only care if operation is successful or not.
Bill Venners: You mentioned
scalability and versioning concerns
with respect to checked exceptions.
Could you clarify what you mean by
those two issues?
Anders Hejlsberg: Let's start with
versioning, because the issues are
pretty easy to see there. Let's say I
create a method foo that declares it
throws exceptions A, B, and C. In
version two of foo, I want to add a
bunch of features, and now foo might
throw exception D. It is a breaking
change for me to add D to the throws
clause of that method, because
existing caller of that method will
almost certainly not handle that
exception.
Adding a new exception to a throws
clause in a new version breaks client
code. It's like adding a method to an
interface. After you publish an
interface, it is for all practical
purposes immutable, because any
implementation of it might have the
methods that you want to add in the
next version. So you've got to create
a new interface instead. Similarly
with exceptions, you would either have
to create a whole new method called
foo2 that throws more exceptions, or
you would have to catch exception D in
the new foo, and transform the D into
an A, B, or C.
Bill Venners: But aren't you breaking
their code in that case anyway, even
in a language without checked
exceptions? If the new version of foo
is going to throw a new exception that
clients should think about handling,
isn't their code broken just by the
fact that they didn't expect that
exception when they wrote the code?
Anders Hejlsberg: No, because in a lot
of cases, people don't care. They're
not going to handle any of these
exceptions. There's a bottom level
exception handler around their message
loop. That handler is just going to
bring up a dialog that says what went
wrong and continue. The programmers
protect their code by writing try
finally's everywhere, so they'll back
out correctly if an exception occurs,
but they're not actually interested in
handling the exceptions.
The throws clause, at least the way
it's implemented in Java, doesn't
necessarily force you to handle the
exceptions, but if you don't handle
them, it forces you to acknowledge
precisely which exceptions might pass
through. It requires you to either
catch declared exceptions or put them
in your own throws clause. To work
around this requirement, people do
ridiculous things. For example, they
decorate every method with, "throws
Exception." That just completely
defeats the feature, and you just made
the programmer write more gobbledy
gunk. That doesn't help anybody.
EDIT: Added more details on the converstaion
Checked exceptions are a controversial issue in general, and in Java in particular (later on I'll try to find some examples for those in favor and opposed to them).
As rules of thumb, exception handling should be something around these guidelines, in no particular order:
For the sake of maintainability, always log exceptions so that when you start seeing bugs, the log will assist in pointing you to the place your bug has likely started. Never leave printStackTrace() or the likes of it, chances are one of your users will get one of those stack traces eventually, and have exactly zero knowledge as to what to do with it.
Catch exceptions you can handle, and only those, and handle them, don't just throw them up the stack.
Always catch a specific exception class, and generally you should never catch type Exception, you are very likely to swallow otherwise important exceptions.
Never (ever) catch Errors!!, meaning: Never catch Throwables as Errors are subclasses of the latter. Errors are problems you will most likely never be able to handle (e.g. OutOfMemory, or other JVM issues)
Regarding your specific case, make sure that any client calling your method will receive the proper return value. If something fails, a boolean-returning method might return false, but make sure the places you call that method are able to handle that.
You should only catch the exceptions you can deal with. For example, if you're dealing with reading over a network and the connection times out and you get an exception you can try again. However if you're reading over a network and get a IndexOutOfBounds exception, you really can't handle that because you don't (well, in this case you wont) know what caused it. If you're going to return false or -1 or null, make sure it's for specific exceptions. I don't want a library I'm using returning a false on a network read when the exception thrown is the heap is out of memory.
Exceptions are errors that are not part of normal program execution. Depending on what your program does and its uses (i.e. a word processor vs. a heart monitor) you will want to do different things when you encounter an exception. I have worked with code that uses exceptions as part of normal execution and it is definitely a code smell.
Ex.
try
{
sendMessage();
if(message == success)
{
doStuff();
}
else if(message == failed)
{
throw;
}
}
catch(Exception)
{
logAndRecover();
}
This code makes me barf. IMO you should not recover from exceptions unless its a critical program. If your throwing exceptions then bad things are happening.
All of the above seems reasonable, and often your workplace may have a policy. At our place we have defined to types of Exception: SystemException (unchecked) and ApplicationException (checked).
We have agreed that SystemExceptions are unlikely to be recoverable and will bve handled once at the top. To provide further context, our SystemExceptions are exteneded to indicate where they occurred, e.g. RepositoryException, ServiceEception, etc.
ApplicationExceptions could have business meaning like InsufficientFundsException and should be handled by client code.
Witohut a concrete example, it's difficult to comment on your implementation, but I would never use return codes, they're a maintenance issue. You might swallow an Exception, but you need to decide why, and always log the event and stacktrace. Lastly, as your method has no other processing it's fairly redundant (except for encapsulation?), so doactualStuffOnObject(p_jsonObject); could return a boolean!
After some thought and looking at your code it seems to me that you are simply rethrowing the exception as a boolean. You could just let the method pass this exception through (you don't even have to catch it) and deal with it in the caller, since that's the place where it matters. If the exception will cause the caller to retry this function, the caller should be the one catching the exception.
It can at times happen that the exception you are encountering will not make sense to the caller (i.e. it's a network exception), in which case you should wrap it in a domain specific exception.
If on the other hand, the exception signals an unrecoverable error in your program (i.e. the eventual result of this exception will be program termination) I personally like to make that explicit by catching it and throwing a runtime exception.
If you are going to use the code pattern in your example, call it TryDoSomething, and catch only specific exceptions.
Also consider using an Exception Filter when logging exceptions for diagnostic purposes. VB has language support for Exception filters. The link to Greggm's blog has an implementation that can be used from C#. Exception filters have better properties for debuggability over catch and rethrow. Specifically you can log the problem in the filter and let the exception continue to propagate. That method allows an attaching a JIT (Just in Time) debugger to have the full original stack. A rethrow cuts the stack off at the point it was rethrown.
The cases where TryXXXX makes sense are when you are wrapping a third party function that throws in cases that are not truly exceptional, or are simple difficult to test without calling the function. An example would be something like:
// throws NumberNotHexidecimalException
int ParseHexidecimal(string numberToParse);
bool TryParseHexidecimal(string numberToParse, out int parsedInt)
{
try
{
parsedInt = ParseHexidecimal(numberToParse);
return true;
}
catch(NumberNotHexidecimalException ex)
{
parsedInt = 0;
return false;
}
catch(Exception ex)
{
// Implement the error policy for unexpected exceptions:
// log a callstack, assert if a debugger is attached etc.
LogRetailAssert(ex);
// rethrow the exception
// The downside is that a JIT debugger will have the next
// line as the place that threw the exception, rather than
// the original location further down the stack.
throw;
// A better practice is to use an exception filter here.
// see the link to Exception Filter Inject above
// http://code.msdn.microsoft.com/ExceptionFilterInjct
}
}
Whether you use a pattern like TryXXX or not is more of a style question. The question of catching all exceptions and swallowing them is not a style issue. Make sure unexpected exceptions are allowed to propagate!
I suggest taking your cues from the standard library for the language you're using. I can't speak for C#, but let's look at Java.
For example java.lang.reflect.Array has a static set method:
static void set(Object array, int index, Object value);
The C way would be
static int set(Object array, int index, Object value);
... with the return value being a success indicator. But you're not in C world any more.
Once you embrace exceptions, you should find that it makes your code simpler and clearer, by moving your error handling code away from your core logic. Aim to have lots of statements in a single try block.
As others have noted - you should be as specific as possible in the kind of exception you catch.
If you're going to catch an Exception and return false, it should be a very specific exception. You're not doing that, you're catching all of them and returning false. If I get a MyCarIsOnFireException I want to know about it right away! The rest of the Exceptions I might not care about. So you should have a stack of Exception handlers that say "whoa whoa something is wrong here" for some exceptions (rethrow, or catch and rethrow a new exception that explains better what happened) and just return false for others.
If this is a product that you'll be launching you should be logging those exceptions somewhere, it will help you tune things up in the future.
Edit: As to the question of wrapping everything in a try/catch, I think the answer is yes. Exceptions should be so rare in your code that the code in the catch block executes so rarely that it doesn't hit performance at all. An exception should be a state where your state machine broke and doesn't know what to do. At least rethrow an exception that explains what was happening at the time and has the caught exception inside of it. "Exception in method doSomeStuff()" isn't very helpful for anyone who has to figure out why it broke while you're on vacation (or at a new job).
My strategy:
If the original function returned void I change it to return bool. If exception/error occurred return false, if everything was fine return true.
If the function should return something then when exception/error occurred return null, otherwise the returnable item.
Instead of bool a string could be returned containing the description of the error.
In every case before returning anything log the error.
Some excellent answers here. I would like to add, that if you do end up with something like you posted, at least print more than the stack trace. Say what you were doing at the time, and Ex.getMessage(), to give the developer a fighting chance.
try/catch blocks form a second set of logic embedded over the first (main) set, as such they are a great way to pound out unreadable, hard to debug spaghetti code.
Still, used reasonably they work wonders in readability, but you should just follow two simple rules:
use them (sparingly) at the low-level to catch library handling issues, and stream them back into the main logical flow. Most of the error handling we want, should be coming from the code itself, as part of the data itself. Why make special conditions, if the returning data isn't special?
use one big handler at the higher-level to manage any or all of the weird conditions arising in the code that aren't caught at a low-level. Do something useful with the errors (logs, restarts, recoveries, etc).
Other than these two types of error handling, all of the rest of the code in the middle should be free and clear of try/catch code and error objects. That way, it works simply and as expected no matter where you use it, or what you do with it.
Paul.
I may be a little late with the answer but error handling is something that we can always change and evolve along time. If you want to read something more about this subject I wrote a post in my new blog about it. http://taoofdevelopment.wordpress.com
Happy coding.

Categories

Resources