Related
Should I catch exceptions in my method for "purely documenting" purposes, thus encapsulating the error-documentation inside the method itself, or is that responsibility of the caller?
Suppose I call numerous other methods in my EncryptPackage() method, including the framework ones, which potentially throw numerous exceptions. I wrap everything in using blocks, so no need to catch exceptions for cleanup (or I use try/finally for cleanup). Should I catch the exception anyway, and provide the details about the context of that method, or is it the responsibility of caller method?
Here is the case one:
[Serializable]
class TestClassException : Exception
{
public TestClassException() : base() { }
public TestClassException(string message) : base(message) { }
public TestClassException(string message, Exception innerException) : base(message, innerException) { }
}
class TestClass
{
public TestClass() { }
public void EncryptPackage()
{
try
{
DoSomething();
DoAnotherThing();
}
catch (Exception ex)
{
throw new TestClassException("Error occurred during package encryption", ex);
}
}
}
class ConsumerExample
{
public ConsumerExample() { }
public void DoSomeStuff()
{
TestClass testClass = new TestClass();
try
{
testClass.EncryptPackage();
}
catch (TestClassException ex)
{
System.Windows.Forms.MessageBox.Show(ex.ToString());
}
}
}
In this code, notice how the EncryptPackage() method catches all possible exceptions, just to "decorate the error text", with a "Error occurred during package encryption" text. EncryptPackage() here encapsulates the error-description logic.
And here is another technique:
class TestClass2
{
public TestClass2() { }
public void EncryptPackage()
{
DoSomething();
DoAnotherThing();
}
}
class ConsumerExample2
{
public ConsumerExample2() { }
public void DoSomeStuff()
{
TestClass testClass = new TestClass();
try
{
testClass.EncryptPackage();
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("Error occurred during package encryption.\r\n\r\n" + ex.ToString());
}
}
}
In this example, EncryptPackage() does not catch anything, because the caller documents the error case anyway with "Error occurred during package encryption.\r\n\r\n" message.
Please note that this is a very simplified example, in real world there will be numerous hierarchical classes, and exceptions will be propagating through the long call stack, so which method of catching exceptions is preferred? Second approach seems "cleaner", because the exception is handled in a layer where some "actual handling" (e.g. displaying to user) is going to take place. Call stack information would be preserved in exception object, so technically it will be possible to find out where exactly the exception was thrown. But... that does not seem as "well-documenting" as the first approach, where each level of abstraction adds its own description to the error, preserving the previous exception in an innerException member. In this case, when the execution leaves the TestClass layer, it already contains detailed description of the error that happened within this class. So this feels to be the better encapsulation of error-handling logic.
Which one to use?
There is a chapter on this in Effective Java:
Higher layers should catch lower-level exceptions and, in their place,
throw exceptions that can be explained in terms of the higher-level
abstraction. This idiom is known as exception translation.
I prefer your second example, mainly because it can signicantly reduce the amount of error handling code you have to write, especially if you are writing custom exceptions - with the first example you could end up with a lot of custom exception classes which do not give much benefit (you already have the call stack to tell you where the exception came from).
You might think it is nice to have a more descriptive error message, but who benefits from this? The end-user? Should you even be displaying exception messages to your user (and what language are you going to use)? A lot of the time the user just needs to know that there has been an internal error, and they should give up (restart), or try again. Do you the developer benefit? You are probably going to end up examining the call stack anyway with the source code in front of you, so you don't really need a more descriptive message, you can see for yourself what the code is doing at that point.
This is not a hard and fast rule. Most of the time I only catch exceptions at the top level, where I log them and report an error to the user. If you are reporting the exception directly to the user, then often the original exception does not benefit from translation, e.g., if you try to open a non-existent file, then the System.IO.FileNotFoundException is descriptive enough so why translate it to something else? Do you really want to make the same judgement call ("I know better than the library author so I am going to translate their carefully crafted exceptions") for all of the gazillions of exceptions out there? I only catch exceptions lower down if I want to recover from them (generally not possible), or, very rarely, I want to translate them to a more descriptive exception.
In a layered architecture, it can make sense to translate exceptions between the layers, e.g., catch exceptions coming out of the data access layer to a form suitable for the application layer, and similarly between the application layer and the user interface, but I don't know if you are working on that type of system.
If you want to document your exceptions, you should use the exception tag in the xml documentation for the method. This can then be used to general help files from the documentation, e.g., using SandCastle.
As per #Sjoerd above, translate exceptions so they are in the same level of abstraction. In your case EncryptPackage should translate any lower-level exceptions itself, NOT the caller.
Say the lower-level exceptions were from a DB layer (say DBException). Would the caller expect to understand DBException? The answer is NO: the caller wants to encrpt a package, not a DBException. The lower-level exceptions should be chained INSIDE the higher-level exception for debugging purposes.
Finally, I know TestClassException is an example, but make sure the exception class describes the problem clearly: I, personally, don't like bland, generic exception classes (except to make a common base-class for other exceptions).
You should try/catch in few, easily distinguished situations:
any method that can be invoked "externally", such as your app's entry point, UI events, multi-threaded calls and others. Put some log output or message on each and every catch you have. This will prevent your app from crashing (for the most part) as well as provide you or the user with some feedback on how to fix the problem.
when you can really handle the exception. This means your app can, for example, opt for a secondary database or server URL, apply a different processing etc.
when you want to prevent something optional from ruining the main workflow, for example failing to delete your temp file shouldn't cause your process to fail.
there are probably some other places where you'll need a try/catch but these should be rare
Always combine error handling with a decent way of logging and/or messaging the user, don't let any exceptions info disappear because that's how you get apps and don't behave well for "no apparent reason" - at least the reason should be made apparent.
Also - don't use exceptions to control your workflow. There really shouldn't be any "throw"s unless there's absolutely no other way of doing something.
When we wrap a bunch of statements in a try/catch and one of these issues an exception, within the catch we have no way of knowing which of the statements caused the exception (the ex.stacktrace shows our current method (doit), its caller, its caller's caller, etc. but neither do1 or do2):
function doit() {
try {
do1();
do2();
[...]
}
catch (Exception ex) {
// what failed?
}
}
generally I've taken to wrapping all statements and rethrowing, sort of like:
private void do1() {
try {
// do whatever
} catch(Exception e) {
// write to my error log
throw new Exception("do1: " + e.Message, e.InnerException);
}
}
which leaves a trail of breadcrumbs in my log and makes the chain available for the upstream. The problem, of course, is that I have to wrap every method I write with this kind of code.
something tells me I'm being dumb about it. what is the right approach?
Ok, this is hard to get right because exception handling is a really really touchy subject and in the past people have fought religious wars over how to do this right.
First off: neither use an empty catch (try { ... } catch { ... }), nor catch(Exception ex).
The sole purpose of Exception-derived classes is to give you rich information about the kind of exception which occured so you can do something meaningful in your exception handler (if a thread crashed restart it, if a db connection failed non-permanently try again, then fail, etc).
People tend to use a catch-all handler for the outermost part of their code to log uncaught exceptions and this is kind of OK, but in any case you should either prompt the user or rethrow the exception (using throw, not throw ex - there is a ton of discussion about this as well).
Basically you do not programmatically care about where the Exception occured at all.
You can either handle it or you can't. If you can't handle it then you don't catch it.
Addendum: The most important reason for this "if you can do something about it, do so, otherwise dont you dare touch that exception" philosophy is that silently caught exceptions (whether logged or not) can lead to really hard-to-find bugs. Just pushing them out to a logfile might not be enough because in a live system you may not get the fully annotated stack trace (with line numbers and everything).
Addendum 2: Take for instance a textbox which expects an integer input. If the user supplies a string you cannot meaningfully process the input, maybe a conversion exception gets thrown, you catch that specific exception and reset the textbox to its old value and maybe inform the user about the erroneous input. Alternatively your program might either just die with an exception (bad design, you could recover from that exception) or silently go on showing the erroneous input, but still using the old value (bad design, the program is misleading).
If you are really sold on doing this (others have stated why this is bad already), use an Aspect Oriented Programming approach. This will make your life significantly easier and reduce the amount of code you end up writing and maintaining.
Take a look at PostSharp, it gives you a framework that allows you to decorate methods, classes, or namespaces with attributes that will generate this boilerplate error handling for you.
#Branko nailed it in the comments: the exception's stack trace shows the point where the exception was thrown, not where it was caught.
+1 for #ChaosPandion's comment: this is a very, very, very bad idea.
try and catch seem to me to be probably the single worst designed modern programming mechanism. We no longer have the ability to handle errors as we go; we must fail the entire procedure if a single exception occurs, unless we do something horrifying like try every statement individually. There is no longer the option of recovering, only failing as gracefully as possible.
The best pattern for this I have found so far is to wrap every user event in a try/catch (using a method, not an explicit try every time). Ex:
public static class Defines
{
public static bool TryAction(Action pAction)
{
try { pAction(); return true; }
catch(Exception exception) { PostException(exception); return false; }
}
}
...
private void DoSomething(int pValue)
{
...
}
private void MyControl_MyEvent(object pSender, MyEventArgs pEventArgs)
{
Defines.TryAction(() => DoSomething(pEventArgs.Data));
}
Beyond that, just try to write exception-less code. Only use explicit trys when you are very likely to get an exception and want to do a little more than just fail gracefully.
I know you're not suppose to write code that caches all exception types like this.
try
{
//code that can throw an exception
}
catch
{
//what? I don't see no
}
Instead you're suppose to do something more like the code below allowing any other exception that you didn't expect to bubble up.
try
{
//code that can throw an exception
}
catch(TypeAException)
{
//TypeA specific code
}
catch(TypeBException)
{
//TypeB specific code
}
But is it ok to catch all exception types if you are wrapping them with another exception?
Consider this Save() method below I am writing as part of a Catalog class. Is there anything wrong with me catching all exception types and returning a single custom CatalogIOException with the original exception as the inner exception?
Basically I don't want any calling code to have to know anything about all the specific exceptions that could be thrown inside of the Save() method. They only need to know if they tried to save a read only catalog (CatalogReadOnlyException), the catalog could not be serialized (CatalogSerializationException), or if there was some problem writing to the file (CatalogIOException).
Is this a good or bad way to handle exceptions?
/// <summary>
/// Saves the catalog
/// </summary>
/// <exception cref="CatalogReadOnlyException"></exception>
/// <exception cref="CatalogIOException"></exception>
/// <exception cref="CatalogSerializingExeption"></exception>
public void Save()
{
if (!this.ReadOnly)
{
try
{
System.Xml.Serialization.XmlSerializer serializer = new XmlSerializer(typeof(Catalog));
this._catfileStream.SetLength(0); //clears the file stream
serializer.Serialize(this._catfileStream, this);
}
catch (InvalidOperationException exp)
{
throw new CatalogSerializationException("There was a problem serializing the catalog", exp);
}
catch (Exception exp)
{
throw new CatalogIOException("There was a problem accessing the catalog file", exp);
}
}
else
{
throw new CatalogReadOnlyException();
}
}
Update 1
Thanks for all the responses so far. It sounds like the consensus is I shouldn't be doing this, and I should only be catching exceptions if I actually have something to do with them. In the case of this Save() method there really isn't any exception that may be thrown that I want to handle in the Save() method itself. Mostly I just want to notify the user why they were not able to save.
I think my real problem is I'm using exceptions as a way to notify the user of problems, and I'm letting this inform how I am creating and handling exceptions a little too much. So instead should it sounds like it would be better to not catch any exceptions and let the UI layer figure out how to notify the user, and or crash. Is this correct? Consider the Save Menu event handler below.
private void saveCatalogToolStripMenuItem_Click(object sender, EventArgs e)
{
//Check if the catalog is read only
if (this.Catalog.ReadOnly)
{
MessageBox.Show("The currently opened catalog is readonly and can not be saved");
return;
}
//attempts to save
try
{
//Save method doesn't catch anything it can't deal with directly
this.Catalog.Save();
}
catch (System.IO.FileNotFoundException)
{
MessageBox.Show("The catalog file could not be found");
}
catch (InvalidOperationException exp)
{
MessageBox.Show("There was a problem serializing the catalog for saving: " + exp.Message);
}
catch (System.IO.IOException exp)
{
MessageBox.Show("There was a problem accessing the catalog file: " + exp.Message);
}
catch (Exception exp)
{
MessageBox.Show("There was a problem saving the catalog:" + exp.Message);
}
}
Update 2
One more thing. Would the answer change at all if the Save() method was part of a public API vs internal code? For example if it was part of a public API then I'd have to figure out and document all the possible exceptions that Save() may throw. This would be a lot easier if knew that Save() could only possibly throw one of my three custom exceptions.
Also if Save() was part of a public API wouldn't security also be a concern? Maybe I would want to let the consumer of the API know that the save wasn't successful, but I don't want expose anything about how Save() works by letting them get at the exceptions that may have been generated.
Doing a generic catch-all and rethrowing as a new type of exception does not really solve your problem and does not give you anything.
What you really need to do is to catch the exceptions that you can handle and then handle them (at the appropriate level - this is where rethrowing may be useful). All other exceptions either need to be logged so you can debug why they happened, or shouldn't be happening in the first place (for example - make sure you validate user input, etc.). If you catch all exceptions, you'll never really know why you're getting the exceptions you're getting and, thus, cannot fix them.
Updated Response
In response to the update of your question (particularly in how you want to handle the save case), my question to you would be - why are you using exceptions as a means of determine the path your program takes? For example, let's take the "FileNotFoundException." Obviously that can happen at times. But, instead of letting a problem happen and notifying the user about it, before saving (or doing whatever) with the file, why not check first that the file can be found. You still get the same effect, but you aren't using exceptions to control program flow.
I hope this all makes sense. Let me know if you have any additional questions.
When you re-throw with the original exception as inner exception, you lose the original stack trace, which is valuable debugging information.
I will sometimes do what you are suggesting, but I always log the original exception first to preserve the stack trace.
I don't see a problem with what you are doing. The reason for wrapping exceptions in a custom exception types is to create an abstraction between layers of code -- to translate lower-level errors into a higher-level context. Doing this relieves the calling code from having to know too much the implementation details of what Save does.
Your update #1 is an example of the calling code having to know way too much about the implementation details of Save(). In response to your second update, I agree 100%
PS
I'm not saying to do this in every scenario where you encounter exceptions. Only when the benefit outweighs the cost (usually at module boundaries).
Example scenarios for when this is especially useful: you are wrapping a 3rd party library, you don't yet know all the underlying exceptions that might be thrown, you don't have the source code or any documentation, and so on.
Also, he is wrapping the underlying exception and no information is lost. The exception can still be logged appropriately (though you'll need to recursion your way through the InnerExceptions).
I favor wrapping exceptions, from the standpoint that a custom exception hierarchy can divide exceptions into much more useful classifications than the default hierarchy. Suppose one tries to open a document and gets an ArgumentException or an InvalidOperationException. Does the type of the exception really contain any useful information whatsoever? Suppose, however, one instead got a CodecNotFoundException, a PrerenderFingFailureException, or a FontLoadFailureException. One can imagine the system catching some of those exceptions and attempting to do something about it (e.g. allow the user to search for a CODEC, retry rendering with lower-resolution settings, or allow substitution of fonts after warning the user). Much more useful than the default exceptions, many of which say nothing about what's really wrong or what can be done about it.
From a hierarchical standpoint, what's really needed is a means of distinguishing exceptions which indicate that the method throwing the exception was unable to perform its task, but the system state is similar to what it was before the method was started, and those which indicate that the system state is corrupt in a fashion beyond that implied by the method's failure. The normal exception hierarchy is completely useless for that; if one wraps exceptions one may be able to improve the situation slightly (though not as well as if the hierarchy were better designed to start with). An exception which forces a transaction to be unwound is not nearly as bad as one which occurs while committing or unwinding a transaction. In the former case, the state of the system is known; in the latter case, it isn't.
While one should probably avoid catching certain really bad exceptions (StackOverflowException, OutOfMemoryException, ThreadAbortException) I'm not sure it really matters. If the system is going to crash and burn, it's going to do so whether one catches the exception or not. In vb.net, it may be worthwhile to "Catch Ex As Exception When IsNotHorribleException(Ex)" but C# has no such construct, nor even a way to exclude certain exceptions from being caught.
Parting note: in some cases, one operation may generate multiple exceptions that are worthy of logging. Only by wrapping exceptions in a custom exception which holds a list of other exceptions can that really be accomplished.
I don't think its a good idea.
You should only add you own type of exception, if you have anything to add.
And furthermore, you should only catch exceptions that you expect, and that you are able to handle - all other exceptions should be allowed to bubble up.
As a developer I must say, I get angry if you try to "hide" exceptions from me, by swallowing or wrapping them.
For some more info on why catch(exception) is bad check out this article: http://blogs.msdn.com/clrteam/archive/2009/02/19/why-catch-exception-empty-catch-is-bad.aspx
Essentially catching 'Exception' is like saying 'if anything goes wrong I dont care carry on' and catching 'Exception' and wrapping it is like saying 'if anything goes wrong treat them as if they all went wrong for the exact same reason'.
This cannot be correct either you handle it because you semi-expected it or you totally don't think it should ever happen EVER (or didn't know it would). In this case you'd want some kind of app level logging to point you to an issue that you had never expected - not just a one size fits all solution.
My own rule of thumb is to catch and wrap Exception only if I have some useful context I can add, like the file name I was trying to access, or the connection string, etc. If an InvalidOperationException pops up in your UI with no other information attached, you're going to have a hell of a time tracking down the bug.
I catch specific exception types only if the context or message I want to add can be made more useful for that exception compared to what I would say for Exception generally.
Otherwise, I let the exception bubble up to another method that might have something useful to add. What I don't want to do is tie myself in knots trying to catch and declare and handle every possible exception type, especially since you never know when the runtime might throw a sneaky ThreadAbortException or OutOfMemoryException.
So, in your example, I would do something like this:
try
{
System.Xml.Serialization.XmlSerializer serializer =
new XmlSerializer(typeof(Catalog));
this._catfileStream.SetLength(0); //clears the file stream
serializer.Serialize(this._catfileStream, this);
}
// catch (InvalidOperationException exp)
// Don't catch this because I have nothing specific to add that
// I wouldn't also say for all exceptions.
catch (Exception exp)
{
throw new CatalogIOException(
string.Format("There was a problem accessing catalog file '{0}'. ({1})",
_catfileStream.Name, exp.Message), exp);
}
Consider adding the inner exception's message to your wrapper exception so that if a user just sends you a screenshot of the error dialog, you at least have all the messages, not just the top one; and if you can, write the whole ex.ToString() to a log file somewhere.
In this particular case exceptions should be rare enough that wrapping it shouldn't be a useful thing and will likely just get in the way of error handling down the line. There are plenty of examples within the .Net framework where a specific exception that I can handle is wrapped in a more general one and it makes it much more difficult (though not impossible) for me to handle the specific case.
I have written an article on this very topic before. In it I reiterate the importance of capturing as much data about the exception as is possible. Here's the URL to the article:
http://it.toolbox.com/blogs/paytonbyrd/improve-exception-handling-with-reflection-and-generics-8718
What benefit does the user get from being told "There was a problem serializing the catalog"? I suppose your problem domain might be an extraordinary case, but every group of users I've ever programmed for would respond the same way when reading that message: "The program blew up. Something about the catalog."
I don't mean to be condescending towards my users; I'm not. It's just that generally speaking my users have better things to do with their attention than squander it constructing a fine-grained mental model of what's going on inside my software. There have been times when my users have had to build that kind of an understanding in order to use a program I've written, and I can tell you that the experience was not salutary for them or for me.
I think your time would be much better spent on figuring out how to reliably log exceptions and relevant application state in a form that you can access when your users tell you that something broke than in coming up with an elaborate structure for producing error messages that people are unlikely to understand.
To answer this question, you need to understand why catching System.Exception is a bad idea, and understand your own motivations for doing what your propose.
It's a bad idea because it makes the statement that anything that could have gone wrong is okay, and that the application is in a good state to keep running afterwards. That's a very bold statement to make.
So the question is: Is what you are proposing equivalent to catching System.Exception? Does it give the consumer of your API any more knowledge to make a better judgement? Does it simply encourage them to catch YourWrappedException, which is then the moral equivalent of catching System.Exception, except for not triggering FXCop warnings?
In most cases, if you know there's a rule against doing something, and want to know if something similar is "okay", you should start with understanding the rationale for the original rule.
This is a standard practice in .NET and how exceptions should be handled, especially for exceptions that are recoverable from.
Edit: I really have no idea why I'm being downvoted perhaps I read more into the authors intent than everyone else. But the way I read the code the fact he is wrapping those exceptions into his custom exception implies that the consumer of this method is equiped to handle those exceptions and that it is a responsibility of the consumer to deal with the error processing.
Not a single person that DV'd actually left any form of actual dispute. I stand by my answer that this is perfectly acceptable because the consumer should be aware of the potential exceptions this could throw and be equipped to handle them which is shown by the explicit wrapping of the exception. This also preserves the original exception so the stack trace is available and underlying exception accessible.
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.
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.