Related
Other than logging, what constitutes handling an exception? I ask as people say only catch an exception you can handle.
For example, I wrote a tool to interact with Active Directory. I run it on the domain controller. As I have intimate knowledge of AD, an otherwise-exceptional case I can handle (eg I can raise a prompt to ask for another domain name) and go from there. But if there is a problem with the domain on a production server so critical, would this not be exceptional?
So in this case, a problem with the environment should be exceptional (given that is production and AD etc), yet this is something I can handle. I think handling an exception depends on the program audience (agree)?
Anyway, the main question: to deduce if I can "handle" an exception, I need to know what handle entails - other than logging and presenting the user with another choice (in which case I avoid exceptions by using if file exists etc).
For the above case (AD), I structured my code as:
if (adIsAvailable)
// do whatever here
else
raise exception and ask for action
this is then caught in the gui
Any thoughts on the validity of that design?
Great question.
Remember that you can handle only specific types of exceptions and propagate the really critical ones up the stack and into oblivion.
One type of usage of exception handling is interacting with the user, of course, as you said, the best way is to check a precondition that if violated (file does not exist) will throw an exception, rather than performing the actual task and relying on the exception mechanism for notification.
Another usage of exception handling is retry. For example, you are sending a query to a DB and receive a TimeOutException, or another error that indicates that the connection is temporary unavailable. In this case you might want to wait a bit, and try another time. And only if you fail to reach the Db after, say, 3 times- propagate the exception to the upper layers.
Another way of handling an exception is adding data to the exceptionor changing its type.
You might want to catch a TimeOutException but throw a MyApplicationException that contains, for example, the SQL that you tried to execute (the original exception being the inner exception).
Furthermore, you might want to do the opposite- remove data from the exception, such as the stack- trace, this from security reasons (it is not wise to expose the inner workings of the applications to the malicious user)
In your case by the way, you might want to format a user friendly message that clearly states the nature of the problem, instead of presenting the user with a stack trace and an obscure message. This is another example for a transformation that can be done during exception handling.
Not long ago, I had an exception thrown from my app that rose from insufficient space in a table space on a DML operation. The user got a horrible exception with an error code. What I did is add a handler that inspected the exceptions thrown from the invocation of the command, and added special handling for this error code- it now tells the user exactly what the problem is!
You have a few different issues combined, here.
How to handle (and decide when to handle) exceptions that are thrown by underlying code
When to throw exceptions yourself
Whether production code should treat 'exceptional' situations differently from dev. code.
Regarding point (1):
This can be a bit messy and hard to decide - different APIs might use exceptions differently, even inside the same language.
In C#, for instance, I prefer to use int.TryParse() rather than int.Parse() and catching a FormatException if I expect my input to maybe fail parsing, and I want to write code to handle that case.
If I don't want to handle bad input, I will use int.Parse(), and let the exception propagate.
It depends on the situation, alas.
Regarding point (2):
Exceptions basically mean "I give up". They mean something went wrong, but you aren't going to handle it yourself right there.
Regarding point (3):
I think this is almost always a bad idea.
Aside:
I disagree with part of Vitality's answer, where it says:
the best way is to check a precondition that if violated (file does
not exist) will throw an exception, rather than performing the actual
task and relying on the exception mechanism for notification.
If you write code like:
if (file_exists(x))
{ /* do something */ }
else
{ /* whatever */ }
Then you open yourself up to race conditions.
Maybe the file was deleted in between the file_exists() check, so your code will throw an exception anyway.
Or maybe the file got created just after you entered the else section.
In a case like this, I think it is better to do what you are trying to do, and if something goes wrong, deal with the exception.
I've dealt with instances where I would throw/rethrow an exception knowing that the code surrounding it would catch the specific exception. But is there any time you would want to throw an exception, knowing that it wouldn't be caught?
Or at least, NOT catch an exception?
Exceptions immediately halt the application unless their handled right? So I guess I'm asking if you would ever want to purposely let your application die?
If your application is primarily going to be used by other clients and is not standalone, it generally makes sense to throw exceptions if a condition arises that you don't know how to (or don't want to) handle, and there's no sensible way for you to recover from it. Clients should be able to decide how they want to handle any exceptions that you might throw.
On the other hand, if your application is the endpoint, throwing an exception essentially becomes a notification mechanism to alert people that something has gone terribly wrong. In such cases, you need to consider a few things:
How important is the continued running of the application? Is this error really unrecoverable? Throwing an exception and terminating your program is not something you want to be doing on the space shuttle.
Are you using exceptions as a proxy for real logging? There's almost never a reason to do this; consider a real logging mechanism instead. Catch the exception and have the logger work out what happened.
What are you trying to convey by throwing the exception yourself? Ask yourself what the value in throwing a new exception is, and consider carefully whether there isn't a better way to do what you want.
Not catching an exception may leave resources in a bad state. If you don't gracefully exit, things are generally not cleaned up for you. Make sure you understand what you're doing if you need to do this -- and if you're not going to catch it, at least consider a try-finally block so you can do some tidying up.
There's a very good rule that I came across a while ago:
Throw an exception when a method can't do what its name says it does.
The idea is that an exception indicates that something has gone wrong. When you are implementing a method, it is not your responsibility to be aware of whether it will be used correctly or not. Whether the code using your method catches the exception or not is not your responsibility, but the responsibility of the person using your method.
Another rule to follow is:
Don't catch an exception unless you know what you want to do with it.
Obviously, you should include cleanup code in a try...finally block, but you should never just catch an exception just for the sake of catching it. And you should never swallow exceptions silently. While there are occasions when you may want to catch all exceptions (e.g. by doing catch (Exception ex) in C#), these are fairly uncommon and generally have a very specific technical reason. For example, when you are using threads in .NET 2.0 or later, if an exception escapes from your thread, it will cause the entire application domain to unload. In these cases, however, at the very minimum you should log the exception details as an error and provide an explanation in the comments.
Sure. For example, if you're trying to load some bytes into a string in Java:
try {
String myString = new String(byteArray, "UTF-8");
} catch (UnsupportedEncodingException e) {
// Platform doesn't support UTF-8? What is this, 1991?
throw new RuntimeExceptione(e);
}
In this case, there is no graceful degradation, the platform simply can't support the operation desired. You can check for this condition at initialization all you want, but the constructor for String still throws this exception, and you have to deal with it. Either that, or use Charset.forName() :)
Generally, and certainly in early iterations of your application, don't catch the exception. More often than not, the recovery from an exception will require a business rule of some sort, and, more often than not, those business rules are not defined for you. If you "handle" the exception instead of letting the application die then you will most likely be inventing business rules for your customer. Not good.
The general pattern of catching every exception just for the sake of catching it has caused me more headaches than I can count. It usually happens that someone puts some sort of generic exception handling code throughout the application, which inevitably ends up hiding a bug or creating some behavior that is unwanted. (incidentally, catching and then not rethrowing is even worse.)
So, I'd suggest that you ask instead: "When should I catch an exception?"
Here's the thing ... it is about "layers", or "encapsulation", or "low coupling". At some place in your codebase, you're writing a method to do something. Say it's a public method. Therefore, it should not assume much or anything about the caller ... rather, it should merely do the job it is supposed to do, regardless of who is calling it and what context the caller is in.
And if, for some reason, it cannot complete its job, then it needs to tell the caller "Sorry, I couldn't do that, and here's why". Exceptions are an excellent mechanism to let it tell the caller that (not the only mechanism, but the best mechanism I've ever seen for most cases).
So, when you throw the exception, you have no idea whether it will be caught or not ... because you're exposing a public method and you have no idea who might choose to call it and why.
The catching of the exception is the job of the "context". For example, say you're writing a library with public methods that might throw exceptions. Then, say you're using that library from a Windows Forms app. The Windows Forms app might catch exceptions and show a message box to the user.
But later, you might use the same library from a Windows Service. The Service would be more likely to catch the exception, log it, return an error to the original caller, but keep running so it can process further requests.
So the exception is like a contractual agreement between the caller and the provider. The provider says, "I'll either do the job or tell you why I can't. What you do from there is your own business." And the caller says, "OK, if you can't do the job, just tell me why, and I'll decide what to do in that case."
But is there any time you would want to throw an exception, knowing that it wouldn't be caught?
I would say that if you're manually throwing an exception, most of the time you don't know if it will be caught. If you knew it would be caught you could just handle it yourself rather than throwing the exception in the first place.
To be fair, I suppose that depends in part on the kind of programming you're doing, and sometimes the same programmer ends up building both the library and the code that consumes said library.
Would you ever NOT catch an exception?
If you didn't expect/weren't aware an exception could be thrown. But putting that aside and assuming you are aware of the exception, sometimes you know about it at one tier but know the next tier up is the more appropriate place to handle it.
It depends on the type of application. Web applications can continue running even after exceptions have bubbled up to the execution context.
It is common practice to 'throw/rethrow' an exception if you catch the exception at a level where it can't be dealt with. But, you would almost always add context to the issue, at the very least add some logging at the higher level to say that it was caught and rethrown.
for example
A calls B calls C (throws exception)
B catches/rethrows
A catches.
In this case, you would want B to add some logging so that you can differentiate between B generating and throwing an error, and C generating and throwing an error. That would allow you a greater ability to debug and fix problems later.
In general you will almost NEVER want an exception to kill your program. The best practice is to catch the except and exit gracefully. This allows you to save any currently open information and release resources that are being used so they don't become corrupted. If you intend to exit, you can create your own 'core-dump' information report that includes the things you were doing when you caught the fatal exception.
If you let the exception kill your process you are eliminating your chance to get custom tailored crash information, and you are also skipping the part where you provide the user with a friendly error message and then exit.
So, I would recommend ALWAYS catching exceptions, and never voluntarily letting them run amok in your program.
EDIT
If you are writing a library, you have to choose ahead of time whether your function will throw an exception, or be exception safe. In those cases, sometimes you will throw an exception and have no idea if the calling party will catch it. But in that case, catching it is not your responsibility, as long as the api declares that the function could throw exceptions.
(I'm looking for a word that means 'could possibly throw exception'... anyone know what it is? It's going to bug me all day.)
Firstly, there absolutely are situations where it is better to not catch an exception.
Sometimes, an exception can sometimes tell you that your program is in an unknown state. There are a number of exceptions where this is pretty much intrinsically true given the exception type. A NullReferenceException essentially tells you "there is a bug". And by catching such an exception, you may hide the bug, which sounds good in the short term, but in the long term you'd be happier to fix it. The product may not crash, but it certainly won't have the expected behaviour.
But this is also true for exception types we invent for ourselves. Sometimes, the fact that exception A has been thrown should be "impossible" - and yet it has happened, so there's a bug.
Also, something very important happens when you catch an exception: the finally blocks for the whole call stack inside the try block (and anything it calls) will be executed. What do those finally blocks do? Well, anything. And if the program is in an unknown state, I really do mean anything. They could erase valuable customer data from the disk. They could throw more exceptions. They could corrupt data in memory, making the bug impossible to diagnose.
So when an exception indicates an unknown state, you don't want to run any more code, so whatever you do, don't catch the exception. Let it fly past, and your program will terminate harmlessly, and Windows Error Reporting will be able to capture the state of the program as it was when the problem was originally detected. If you catch the exception, you will cause more code to execute, which will screw up the state of the program further.
Secondly, should you throw an exception knowing it won't be caught? I think that question misunderstands the nature of reusable methods. The whole idea of a method is that it has a "contract" that it follows: it accepts certain parameters and returns a certain value, plus also it throws certain exceptions under certain conditions. That's the contract - it's up to the caller what they do with it. For some callers, exception A might indicate a recoverable condition. For other callers, it might indicate a bug. And from what I said above, it should be clear that if an exception indicates a bug, it must not be caught.
And if you're wondering what this means for the Microsoft Enterprise Library's Exception Handling Block: yes, it's pretty broken. They tell you to catch (Exception x) and then decide whether to rethrow based on your policy; too late - the finally blocks have already executed by that point. Don't do that.
You probably wouldn't want an uncaught exception anywhere where the end-users can see it, but it is often acceptable to let clients of your API (other programmers) decide how to handle exceptions.
For example, suppose you are designing a Java class library. You expose a public method that takes in a String. In your application, a null input value would cause an error. Instead of handling the error yourself, it would be acceptable to check for a null value, then throw an IllegalArgumentException.
You must, of course, document that your method throws this exception in this circumstance. This behavior becomes part of your method's contract.
It depends on what you mean by 'being caught'. Something, somewhere eventually catches the exception whether it be the underlying OS or something else.
We have a workflow system that executes job plans comprised of individual jobs. Each job runs a unit of code. For some of the exceptions, we don't want to handle them in the code but throw it up the stack so that the external workflow system catches it (which happens completely outside of the thrower's process).
If you're writing the entire application, then your reasons are your own. I can think of a few situations where you might want to throw the exception and let the app die, most of them are not very good reasons though.
The best reason is usually when debugging. I frequently disable exceptions while debugging to allow me to know better where something is failing. You can also just turn on thrown exception breaks in the debugger if you're running it on a machine with the debugger.
Another possible reason is when continuing after an exception is thrown doesn't make sense or would result in possible irrecoverable data corruption or worse (think Robots with laser beams, but then you should be damn sure your applicaiton deals with these situations IMO, crashing the program is just the lazy way).
If you're writing API code, or Framework code that you won't use yourself, then you have no idea if someone will catch your exceptions.
Yup, it's my ONLY opportunity to slap the developer consuming the service/object to tell them "Ur dO1n it WrOnG!!!!".
That and getting rid of possibilities that you don't want to permit or are seemingly "impossible". Apps that catch all exceptions and continue are just a walled garden surrounded by chaos.
If I need a moderately large system that is somehow processing data in what I believe to be a consistent manner.
And
Somewhere along the line, I detect that the application's state has become inconsistent.
And
The system doesn't (yet) know how to fix the inconsistency and recover gracefully
Then, yes, I would throw an exception with as much detail as possible and cause the application to die as quickly as possible, to avoid doing any further harm to the data. If it can be recovered, it'd be important not to exacerbate the problem by trying feebly to cover up the mess.
Later along the line, once the chain of events that led to the inconsistency is better understood, I higher facility can catch that exception, repair the state, and continue with minimal interruption.
A library will often throw exceptions based on defensive programming checks, should a condition arise that shouldn't have been allowed to arise by the application code. Applications code will often be written such that most of those invalid conditions will never arise, and therefore the exceptions will never be thrown, so there's no point catching them.
Depending on language (I'm mostly thinking in terms of C++ rather than C#, and not that clear what the differences are) the effect of an uncaught exception actually being thrown is probably the same as what used to be done in the days before exceptions were invented. A common policy for defensive programming in C libraries, for example, was to terminate the program immediately with an error message.
The difference is that if the exception throw does turn out to be possible (hopefully this will be discovered through unit testing), it is often relatively easy to add an exception handler that can recover from the problem in a more constructive way. You don't have to rewrite the library, or add complex checks in application code to ensure the condition cannot arise before the exception-throwing call is made.
I have quite a few exception throws that are never caught. They are all for defensive purposes, and while being uncaught is bad for an exception that does happen, this only ever happens during development and testing, for error conditions I failed to consider in the application code so far. And when it happens, it is unusual for the fix to be awkward - no need for a large-scale refactoring, no need for the applications code to be massively complicated with error condition checks, just a catch clause with a relatively simple recovery or "I'm sorry, Dave, I'm afraid I can't do that." without failing out the whole app.
I keep hearing that
catch (Exception ex)
Is bad practise, however, I often use it in event handlers where an operation may for example go to network, allowing the possibility of many different types of failure. In this case, I catch all exceptions and display the error message to the user in a message box.
Is this considered bad practise? There's nothing more I can do with the exception: I don't want it to halt the application, the user needs to know what happened, and I'm at the top level of my code. What else should I be doing?
EDIT:
People are saying that I should look through the stack of calls and handle errors specifically, because for example a StackOverflow exception cannot be handled meaningfully. However, halting the process is the worst outcome, I want to prevent that at all costs. If I can't handle a StackOverflow, so be it - the outcome will be no worse than not catching exceptions at all, and in 99% of cases, informing the user is the least bad option as far as I'm concerned.
Also, despite my best efforts to work out all of the possible exceptions that can be thrown, in a large code-base it's likely that I would miss some. And for most of them the best defense is still to inform the user.
The bad practice is
catch (Exception ex){}
and variants:
catch (Exception ex){ return false; }
etc.
Catching all exceptions on the top-level and passing them on to the user (by either logging them or displaying them in a message-box, depending on whether you are writing a server- or a client-application), is exactly the right thing to do.
I find the arguments that generic catches are always bad to be overly dogmatic. They, like everything else, have a place.
That place is not your library code, nor the classes you custom-develop for your app. That place is, as many have mentioned, the very top level of the app, where if any exception is raised, it is most likely unexpected.
Here's my general rule (and like all rules, it's designed to be broken when appropriate):
I use classes and custom-built libraries for the majority of the lifting in an app. This is basic app architecture -- really basic, mind you. These guys try to handle as many exceptions as possible, and if they really can't continue, throw the most specific kind available back up to the UI.
At the UI, I tend to always catch all from event handlers. If there is a reasonable expectation of catching a specific exception, and I can do something about it, then I catch the specific exception and handle it gracefully. This must come before the catch all, however, as .NET will only use the very first exception handler which matches your exception. (Always order from most specific to most generic!)
If I can't do anything about the exception other than error out (say, the database is offline), or if the exception truly is unexpected, catch all will take it, log it, and fail safe quickly, with a general error message displayed to the user before dying. (Of course, there are certain classes of errors which will almost always fail ungracefully -- OutOfMemory, StackOverflow, etc. I'm fortunate enough to have not had to deal with those in prod-level code ... so far!)
Catch all has its place. That place is not to hide the exception, that place is not to try and recover (because if you don't know what you caught, how can you possibly recover), that place is not to prevent errors from showing to the user while allowing your app to continue executing in an unknown and bad state.
Catch all's place is to be a last resort, a trap to ensure that if anything makes it through your well-designed and well-guarded defenses, that at a minimum it's logged appropriately and a clean exit can be made. It is bad practice if you don't have well-designed and well-guarded defenses in place at lower levels, and it is very bad practice at lower levels, but done as a last resort it is (in my mind) not only acceptable, but often the right thing to do.
When I see
catch (Exception ex)
my hand starts to groping for a hammer. There are almost no excuses to catch base Exception. Only valid cases that come to my mind are:
1) 3rd party component throws Exception (be damned it's author)
2) Very top level exceptions handling (as a last resort) (for example handle "unhandled" exceptions in WinForms app)
If you find a case where many different types of exceptions can happen it's a good sign of bad design.
I would disagree with Armin Ronacher. How would you behave if StackOverflow exception raised? Trying to perform additional actions can lead to even worse consequences. Catch exception only if you can handle it in meaningful and safe way. Catching System.Exception to cover range of possible exceptions is terribly wrong. Even when you are re-throwing it.
It makes complete sense to catch the exception at the highest level in your code. Catching the base Exception type is fine as long as you don't need to do any different logic based on the exception's type.
Also, make sure you're displaying a friendly, general error message and not showing the actual exception's message. That may lead to security vulnerabilities.
Yes, it is fine to catch the base Execption at the top level of the application, which is what you are doing.
The strong reactions you are getting is probably because at any other level, its almost always wrong to catch the Base exception. Specifically in an a library it would be very bad practice.
It is bad practice in the sense that you shouldn't do it everywhere.
In this case, I would consider it the only reasonable solution as your exception could be truly anything. The only possible improvement would be to add extra handlers before your catch everything for specific error cases where you could do something about the exception.
It's perfectly okay if you re-raise exceptions you can't handle properly. If you just catch the exceptions you could hide bugs in the code you don't expect. If you catch exceptions to display them (and bypass the die-and-print-traceback-to-stderr behavior) that's perfectly acceptable.
I think the poster is referring to exception handling like this:
try {something} catch (SqlException) {do stuff} catch (Exception) {do other stuff}
The idea here is that you want to catch the more specific errors (like SqlException) first and handle them appropriately, rather than always relying on the catch-all general Exception.
The conventional wisdom says that this is the proper way to do exception handling (and that a solo Catch (Exception ex) is bad). In practice this approach doesn't always work, especially when you're working with components and libraries written by someone else.
These components will often throw a different type of exception in production than the one your code was expecting based on how the component behaved in your development environment, even though the underlying problem is the same in both environments. This is an amazingly common problem in ASP.NET, and has often led me to use a naked Catch (Exception ex) block, which doesn't care what type of exception is thrown.
Structured exception handling is a great idea in theory. In practice, it can still be a great idea within the code domain that you control. Once you introduce third party stuff, it sometimes doesn't work very well.
We use Catch ex as Exception (VB.Net variant) quite a bit. We log it, and examine our logs regularly. Track down the causes, and resolve.
I think Catch ex as Exception is completely acceptabile once you are dealing with production code, AND you have a general way to handle unknown exceptions gracefully. Personally I don't put the generic catch in until I've completed a module / new functionality and put in specialized handling for any exceptions I found in testing. That seems to be the best of both worlds.
No; in that case if you don't want to halt the program there's nothing else you can do and at the top level is the right place to do it, as long as you're logging properly and not hiding it away in hope grin
The important thing is to understand the path of exceptions through your application, and not just throw or catch them arbitrarily. For example, what if the exception you catch is Out-Of-Memory? Are you sure that your dialog box is going to display in that case? But it is certainly fine to define a last-ditch exception point and say that you never want errors to propagate past that point.
You should catch the exceptions related to what you are doing. If you look at the methods you call, you will see what exceptions they throw, and you want to stay more specific to those. You should have access to know what exceptions may be thrown by the methods you call, and handle them appropriately.
And... better than having one big try catch, do your try and catch where you need the catch.
try {
myThing.DoStuff();
}
catch (StuffGoneWrongException ex) {
//figure out what you need to do or bail
}
Maybe not quite this closely packed, but it depends on what you are doing. Remember, the job isn't just to compile it and put it on someones desktop, you want to know what breaks if something did and how to fix it. (Insert rant about tracing here)
a lot of times exception are catched to free resources, it' s not important if exception is (re)thrown. in these cases you can avoid try catch:
1) for Disposable object you can use "using" keyword:
using(SqlConnection conn = new SqlConnection(connStr))
{
//code
}
once you are out of the using scope (normally or by a return statement or by exception), Dispsose method is automatically called on object. in other word, it' s like try/finally construct.
2) in asp.net, you can intercept Error or UnLoad event of Page object to free your resource.
i hope i help you!
I'm responding to "However, halting the process is the worst outcome..."
If you can handle an exception by running different code (using try/catch as control flow), retrying, waiting and retrying, retrying with an different but equivalent technique (ie fallback method) then by all means do so.
It is also nice to do error message replacement and logging, unless it is that pseudo-polite-passive-aggressive "contact your administrator" (when you know there is no administrator and if there was the administrator can't do anything about it!) But after you do that, the application should end, i.e. same behavior you get with an unhandled exception.
On the other hand, if you intend to handle the exception by returning the user to a code thread that has potentially trashed its state, I'd say that is worse than ending the application and letting the user start over. Is it better for the user to have to restart at the beginning or better to let the user destroy data?
If I get an unexpected exception in the module that determines which accounts I can withdraw money from, do I really want to log and report an Exception and return the user to the withdraw money screen? For all we know we just granted him the right to withdraw money from all accounts!
This is all good of catching exceptions that you can handled. But sometimes it also happens that due to unstable environment or users just do the process correctly, the application runs into unexpected exception. Which you haven't been listed or handled in code. Is there a way that the unhandled exception is captured from app.config file and displays a common error?
Also puts that details exception message in a log file.
I've been working a fair bit with exceptions, and here's the implementation structure I'm currently following:
Dim everything to Nothing / String.Empty / 0 etc. outside of Try / Catch.
Initialise everything inside Try / Catch to desired values.
Catch the most specific exceptions first, e.g. FormatException but leave in base Exception handling as a last resort (you can have multiple catch blocks, remember)
Almost always Throw exceptions
Let Application_Error sub in global.asax handle errors gracefully, e.g. call a custom function to log the details of the error to a file and redirect to some error page
Kill all objects you Dim'd in a Finally block
One example where I thought it was acceptable to not process an exception 'properly' recently was working with a GUID string (strGuid) passed via HTTP GET to a page. I could have implemented a function to check the GUID string for validity before calling New Guid(strGuid), but it seemed fairly reasonable to:
Dim myGuid As Guid = Nothing
Try
myGuid = New Guid(strGuid)
'Some processing here...
Catch ex As FormatException
lblError.Text = "Invalid ID"
Catch ex As Exception
Throw
Finally
If myGuid IsNot Nothing Then
myGuid = Nothing
End If
End Try
We're reviewing one of the company's system's exception handling and found a couple of interesting things.
Most of the code blocks (if not all of them) are inside a try/catch block, and inside the catch block a new BaseApplicationException is being thrown - which seems to be coming from the Enterprise Libraries.
I'm in a bit of a trouble here as I don't see the benefits off doing this. (throwing another exception anytime one occurs)
One of the developers who's been using the system for a while said it's because that class's in charge of publishing the exception (sending emails and stuff like that) but he wasn't too sure about it.
After spending some time going through the code I'm quite confident to say, that's all it does is collecting information about the environment and than publishing it.
My question is:
- Is it reasonable to wrap all the code inside try { } catch { } blocks and than throw a new exception? And if it is, why? What's the benefit?
My personal opinion is that it would be much easier to use an HttpModule, sign up for the Error event of the Application event, and do what's necessary inside the module. If we'd go down this road, would we miss something? Any drawbacks?
Your opinion's much appreciated.
Never1 catch (Exception ex). Period2. There is no way you can handle all the different kinds of errors that you may catch.
Never3 catch an Exception-derived type if you can't handle it or provide additional information (to be used by subsequent exception handlers). Displaying an error message is not the same as handling the error.
A couple of reasons for this, from the top of my head:
Catching and rethrowing is expensive
You'll end up losing the stack trace
You'll have a low signal-to-noice ratio in your code
If you know how to handle a specific exception (and reset the application to pre-error state), catch it. (That's why it's called exception handling.)
To handle exceptions that are not caught, listen for the appropriate events. When doing WinForms, you'll need to listen for System.AppDomain.CurrentDomain.UnhandledException, and - if your doing Threading - System.Windows.Forms.Application.ThreadException. For web apps, there are similar mechanisms (System.Web.HttpApplication.Error).
As for wrapping framework exceptions in your application (non-)specific exceptions (i.e. throw new MyBaseException(ex);): Utterly pointless, and a bad smell.4
Edit
1 Never is a very harsh word, especially when it comes to engineering, as #Chris pointed out in the comments. I'll admit to being high on principles when I first wrote this answer.
2,3 See 1.
4 If you don't bring anything new to the table, I still stand by this. If you have caught Exception ex as part of a method that you know could fail in any number of ways, I believe that the current method should reflect that in it's signature. And as you know, exceptions is not part of the method signature.
If I am reading the question correctly, I would say that implementing a try / catch which intercept exceptions (you don't mention - is it catching all exceptions, or just a specific one?) and throws a different exception is generally a bad thing.
Disadvantages:
At the very least you will lose stack trace information - the stack you will see will only extend to the method in which the new exception is thrown - you potentially lose some good debug info here.
If you are catching Exception, you are running the risk of masking critical exceptions, like OutOfMemory or StackOverflow with a less critical exception, and thus leaving the process running, where perhaps it should have been torn down.
Possible Advantages:
In some very specific cases you could take an exception which doesn't have much debug value (like some exceptions coming back from a database) and wrap with an exception which adds more context, e.g id of the object you were dealing with.
However, in almost all cases this is a bad smell and should be used with caution.
Generally you should only catch an exception when there is something realistic that you can do in that location- ie recovering, rolling back, going to plan B etc. If there is nothing you can do about it, just allow it to pass up the chain. You should only catch and throw a new exception if there is specific and useful data available in that location which can augment the original exception and hence aid debugging.
I'm from the school of thought where try/ catch blocks should be used and exceptions not rethrown. If you have executing code which is likely to error then it should be handled, logged and something returned. Rethrowing the exception only serves the purpose to re-log later in the application life cycle.
Here's an interesting post on how to use a HttpModule to handle exceptions: http://blogs.msdn.com/rahulso/archive/2008/07/13/how-to-use-httpmodules-to-troubleshoot-your-asp-net-application.aspx and http://blogs.msdn.com/rahulso/archive/2008/07/18/asp-net-how-to-write-error-messages-into-a-text-file-using-a-simple-httpmodule.aspx
Check out ELMAH. It does what you're talking about. Very well.
When I create libraries I try to always provide a reduced number of exceptions for callers to handle. For example, think of a Repository component that connects to a sql database. There are TONS of exceptions, from sql client exceptions to invalid cast exceptions, that can theoretically be thrown. Many of these are clearly documented and can be accounted for at compile time. So, I catch as many of them as I can, place them in a single exception type, say a RepositoryException, and let that exception roll up the call stack.
The original exception is retained, so the original exception can be diagnosed. But my callers only need to worry about handling a single exception type rather than litter their code with tons of different catch blocks.
There are, of course, some issues with this. Most notably, if the caller can handle some of these exceptions, they have to root around in the RepositoryException and then switch on the type of the inner exception to handle it. Its less clean than having a single catch block for a single exception type. I don't think thats much of an issue, however.
Sounds like the exception that is thrown should not have been implemented as an exception.
Anyway, I would say that since this BaseApplicationException is a general all-purpose exception, it would be good to throw exceptions that are more context-specific. So when you are trying to retrieve an entity from a database, you might want an EntityNotFoundException. This way when you are debugging you do not have to search through inner exceptions and stack traces to find the real issue. If this BAseApplicationException is collecting information on the exception (like keeping track of the inner exception) then this should not be a problem.
I would use the HttpModule only when I could not get any closer to where the exceptions are actually happening in code. You do not really want an HttModule OnError event that is a giant switch statement depending on BaseApplicationexception's error information.
To conclude, it is worth it to throw different exceptions when you can give more specific exceptions that tell you the root of the problem right off the bat.
From my experience, catch the exception, add the error to the Server (?) object. This will allow .NET to do what ever it needs to do, then display your exception.
Unchecked exceptions are alright if you want to handle every failure the same way, for example by logging it and skipping to the next request, displaying a message to the user and handling the next event, etc. If this is my use case, all I have to do is catch some general exception type at a high level in my system, and handle everything the same way.
But I want to recover from specific problems, and I'm not sure the best way to approach it with unchecked exceptions. Here is a concrete example.
Suppose I have a web application, built using Struts2 and Hibernate. If an exception bubbles up to my "action", I log it, and display a pretty apology to the user. But one of the functions of my web application is creating new user accounts, that require a unique user name. If a user picks a name that already exists, Hibernate throws an org.hibernate.exception.ConstraintViolationException (an unchecked exception) down in the guts of my system. I'd really like to recover from this particular problem by asking the user to choose another user name, rather than giving them the same "we logged your problem but for now you're hosed" message.
Here are a few points to consider:
There a lot of people creating accounts simultaneously. I don't want to lock the whole user table between a "SELECT" to see if the name exists and an "INSERT" if it doesn't. In the case of relational databases, there might be some tricks to work around this, but what I'm really interested in is the general case where pre-checking for an exception won't work because of a fundamental race condition. Same thing could apply to looking for a file on the file system, etc.
Given my CTO's propensity for drive-by management induced by reading technology columns in "Inc.", I need a layer of indirection around the persistence mechanism so that I can throw out Hibernate and use Kodo, or whatever, without changing anything except the lowest layer of persistence code. As a matter of fact, there are several such layers of abstraction in my system. How can I prevent them from leaking in spite of unchecked exceptions?
One of the declaimed weaknesses of checked exceptions is having to "handle" them in every call on the stack—either by declaring that a calling method throws them, or by catching them and handling them. Handling them often means wrapping them in another checked exception of a type appropriate to the level of abstraction. So, for example, in checked-exception land, a file-system–based implementation of my UserRegistry might catch IOException, while a database implementation would catch SQLException, but both would throw a UserNotFoundException that hides the underlying implementation. How do I take advantage of unchecked exceptions, sparing myself of the burden of this wrapping at each layer, without leaking implementation details?
IMO, wrapping exceptions (checked or otherwise) has several benefits that are worth the cost:
1) It encourages you to think about the failure modes for the code you write. Basically, you have to consider the exceptions that the code you call may throw, and in turn you'll consider the exceptions you'll throw for the code that calls yours.
2) It gives you the opportunity to add additional debugging information into the exception chain. For instance, if you have a method that throws an exception on a duplicate username, you might wrap that exception with one that includes additional information about the circumstances of the failure (for example, the IP of the request that provided the dupe username) that wasn't available to the lower-level code. The cookie trail of exceptions may help you debug a complex problem (it certainly has for me).
3) It lets you become implementation-independent from the lower level code. If you're wrapping exceptions and need to swap out Hibernate for some other ORM, you only have to change your Hibernate-handling code. All the other layers of code will still be successfully using the wrapped exceptions and will interpret them in the same way, even though the underlying circumstances have changed. Note that this applies even if Hibernate changes in some way (ex: they switch exceptions in a new version); it's not just for wholesale technology replacement.
4) It encourages you use different classes of exceptions to represent different situations. For example, you may have a DuplicateUsernameException when the user tries to reuse a username, and a DatabaseFailureException when you can't check for dupe usernames due to a broken DB connection. This, in turn, lets you answer your question ("how do I recover?") in flexible and powerful ways. If you get a DuplicateUsernameException, you may decide to suggest a different username to the user. If you get a DatabaseFailureException, you may let it bubble up to the point where it displays a "down for maintenance" page to the user and send off a notification email to you. Once you have custom exceptions, you have customizeable responses -- and that's a good thing.
I like to repackage exceptions between the "tiers" of my application, so for example a DB-specific exception is repackaged inside of another exception which is meaningful in the context of my application (of course, I leave the original exception as a member so I don't clobber the stack trace).
That said, I think that a non-unique user name is not an "exceptional" enough situation to warrant a throw. I'd use a boolean return argument instead. Without knowing much about your architecture, it's hard for me to say anything more specific or applicable.
See Patterns for Generation, Handling and
Management of Errors
From the Split Domain and Technical Errors pattern
A technical error should never cause a
domain error to be generated (never
the twain should meet). When a
technical error must cause business
processing to fail, it should be
wrapped as a SystemError.
Domain errors should always start from a
domain problem and be handled by
domain code.
Domain errors should
pass "seamlessly" through technical
boundaries. It may be that such errors
must be serialized and re-constituted
for this to happen. Proxies and
facades should take responsibility for
doing this.
Technical errors should
be handled in particular points in the
application, such as boundaries (see
Log at Distribution Boundary).
The
amount of context information passed
back with the error will depend on how
useful this will be for subsequent
diagnosis and handling (figuring out
an alternative strategy). You need to
question whether the stack trace from
a remote machine is wholly useful to
the processing of a domain error
(although the code location of the
error and variable values at that time
may be useful)
So, wrap the hibernate exception at the boundary to hibernate with an unchecked domain exception such as a "UniqueUsernameException", and let that bubble up all the way to the handler of it. Make sure to javadoc the thrown exception even though it isn't a checked exception!
Since you're currently using hibernate the easiest thing to do is just check for that exception and wrap it in either a custom exception or in a custom result object you may have setup in your framework. If you want to ditch hibernate later just make sure you wrap this exception in only 1 place, the first place you catch the exception from hibernate, that's the code you'll probably have to change when you make a switch anyway, so if the catch is in one place then the additional overhead is almost zilch.
help?
I agree with Nick. Exception you described is not really "unexpected exception" so you should design you code accordingly taking possible exceptions into account.
Also I would recommend to take a look at documentation of Microsoft Enterprise Library Exception Handling Block it has a nice outline of error handling patterns.
The question is not really related to checked vs. unchecked debate, the same applies to both exception types.
Between the point where the ConstraintViolationException is thrown and the point, where we want to handle the violation by displaying a nice error message is a large number of method calls on the stack that should abort immediately and shouldn't care about the problem. That makes the exception mechanism the right choice as opposed to redesigning the code from exceptions to return values.
In fact, using an unchecked exception instead of a checked exception is a natural fit, since we really want all intermediate methods on the call stack to ignore the exception and not handle it .
If we want to handle the "unique name violation" only by displaying a nice error message (error page) to the user, there's not really a need for a specific DuplicateUsernameException. This will keep the number of exception classes low. Instead, we can create a MessageException that can be reused in many similar scenarios.
As soon as possible we catch the ConstraintViolationException and convert it to a MessageException with a nice message. It's important to convert it soon, when we can be sure, it's really the "unique user name constraint" that was violated and not some other constraint.
Somewhere close to the top level handler, just handle the MessageException in a different way. Instead of "we logged your problem but for now you're hosed" simply display the message contained in the MessageException, no stack trace.
The MessageException can take some additional constructor parameters, such as a detailed explanation of the problem, available next action (cancel, go to a different page), icon (error, warning)...
The code may look like this
// insert the user
try {
hibernateSession.save(user);
} catch (ConstraintViolationException e) {
throw new MessageException("Username " + user.getName() + " already exists. Please choose a different name.");
}
In a totally different place there's a top exception handler
try {
... render the page
} catch (MessageException e) {
... render a nice page with the message
} catch (Exception e) {
... render "we logged your problem but for now you're hosed" message
}
You can catch unchecked exceptions without needing to wrap them. For example, the following is valid Java.
try {
throw new IllegalArgumentException();
} catch (Exception e) {
System.out.println("boom");
}
So in your action/controller you can have a try-catch block around the logic where the Hibernate call is made. Depending on the exception you can render specific error messages.
But I guess in your today it could be Hibernate, and tomorrow SleepLongerDuringWinter framework. In this case you need to pretend to have your own little ORM framework that wraps around the third party framework. This will allow you to wrap any framework specific exceptions into more meaningful and/or checked exceptions that you know how to make better sense of.
#Jan Checked versus unchecked is a central issue here. I question your supposition (#3) that the exception should be ignored in intervening frames. If I do that, I will end up with an implementation-specific dependency in my high-level code. If I replace Hibernate, catch blocks throughout my application will have to be modified. Yet, at the same time, if I catch the exception at a lower level, I'm not receiving much benefit from using an unchecked exception.
Also, the scenario here is that I want to catch a specific logical error and change the flow of the application by re-prompting the user for a different ID. Simply changing the displayed message is not good enough, and the ability to map to different messages based on exception type is built into Servlets already.
#erikson
Just to add food to your thoughts:
Checked versus unchecked is also debated here
The usage of unchecked exceptions is compliant with the fact they are used IMO for exception caused by the caller of the function (and the caller can be several layers above that function, hence the necessity for other frames to ignore the exception)
Regarding your specific issue, you should catch the unchecked exception at high level, and encapsulate it, as said by #Kanook in your own exception, without displaying the callstack (as mentionned by #Jan Soltis )
That being said, if the underlying technology changes, that will indeed have an impact on those catch() already present in your code, and that does not answer your latest scenario.