Related
I'm trying to understand the correct structures of a program here to facilitate everything. Basically where to "put" things.
For example:
You have 2 classes.
Class 1 is your main.
Both classes have many methods.
Class 1 calls for an instance of Class 2 and runs a method. This method is supposed to return a value.
Question 1:
Should I have a try/catch block INSIDE this method (in Class 2)?
Question 2:
Should the try/catch block be where I call the method (in Class 1)?
try
method();
catch
...
Question 3:
When executing the method that is in Class 2, when it comes to returning a value, should I ever return "an error code" and then deal with this code in the calling class?
Question 4:
When an error happens and I need to "halt" the program, should I use if/else statements so the code only moves forward if the correct conditions are met or should I use the keyword "break" more often?
Question 5:
The possibilities for errors could be endless, specially if you have medium to large programs. How do you guys deal with unknowable errors which you might encounter while the user is running your program?
Exceptions are just that: exceptional. You shouldn't be using exceptions for regular program flow. (If you say, "Oh yeah, I expected that", it probably shouldn't be an exception.)
Handle the exception where it needs handling. If you can survive the function without that try-catch block succeeding, then you should handle it there. Similarly, if you need to wrap some things up, you can also add a finally block (using is similar to finally in C#- it compiles down to try-finally, but is not as robust as writing it yourself. It simply calls .Dispose() on the disposable object you specified).
But if you need to bail out of that function, or you're running a string of functions that need to all succeed in your main class, it might be better to do the handling in your Class 1.
Caveat: There are exceptions (ha!) to every rule. As you program more, you can get an intuitive sense of where error handling should be done- but often there will be more than one option and it may not be clear cut.
In general, the answer to all those questions is "it depends". Clearly what you need to do depends on the specific circumstances of the situation and the application it contains.
From a practices point of view, I generally follow a couple rules:
1. Use exception handling instead of error codes
2. Only use try/catch when I know how to handle an exception
Clearly no one can tell you whether you need a try/catch within a method without knowing what that method does and whether or not you can handle any exceptions.
Whether or not an error code is really applicable is up to you. I generally view it as not applicable; but, sometimes it might be. In those cases I only view it as applicable if the caller will always use the code and not pass it on. "GetErrorCode" might be a good example of a case where an error code may be applicable.
You can't possibly "handle" (i.e. compensate for) "unknown" errors. The recommended practice is the not handle the exception and let the handle terminate gracefully because it's in an unknown state.
Catching exceptions and returning error codes/bools leads to "arrow" code like so:
if(Func1())
{
if (Func2())
{
if (Func3())
{
}
}
}
I unfortunately maintain a complex project where exceptions are treated like Ebola and are contained as soon as they sprout up. It really just makes the code harder to understand and maintain.
It depends on how you visualize and structure your application. Are classes 1 & 2 part of the same module or are they in different modules? In general, a module provides "API" and the caller of the "API" needs to catch errors and exceptions. Have a look at Defensive Programming.
Question 1: Should I have a try/catch block INSIDE this method (in Class 2)?
If Class 2 is a separate module and you do not want to propagate the exceptions to the caller module, then yes. If you want to, then no. The exceptions thrown from this Class/Module then need to be documented.
If Class 1 & 2 are in same module, then again it depends if you want to handle the exceptions within the internal classes or not.
Question 2: Should the try/catch block be where I call the method (in Class 1)?
If you want to safeguard to ensure Class 1 does not throw further exceptions, then yes.
Question 3: When executing the method that is in Class 2, when it comes to returning a value, should I ever return "an error code" and then deal with this code in the calling class?
If you want to throw exception of return an error code, is again a design/implementation decision.
Question 4: When an error happens and I need to "halt" the program, should I use if/else statements so the code only moves forward if the correct conditions are met or should I use the keyword "break" more often?
To use break you will need a loop in the caller.
Question 5: The possibilities for errors could be endless, specially if you have medium to large programs. How do you guys deal with unknowable errors which you might encounter while the user is running your program?
Large programs are divided into modules and could be coded by different developers. So the design and interface contract becomes essential here.
I in general agree w/ David and Peter... The one thing I would add is to be careful about exceptions you catch when you catch them... Richter has a very interesting chapter on exception handling and how exceptions were SUPPOSED to be inherited versus how they have actually been implemented... But even still, it's (IMO) lazy or at least ill-thought-out if you find yourself consistently catching the generic Exception class...
If you're doing file reading/writing, you may very well want to catch appropriate IO exceptions, but to consistently catch the most generic Exception class can lead you to problems if say, a NullReferenceException gets thrown and your try/catch was only protecting against IO Exceptions... Your catch block would try to fix (what it assumed was) an IO exception and it could put your code in a horribly unstable state.
Additionally, be very careful about continuing to re-throw the original error unless you're convinced you TRULY handled it appropriately... If you wrote a library and published it and swallowed all the errors because you thought you were doing the best thing, then someone that consumed your library would have no way to debug what was going on... Exceptions also get thrown into the servers logs, so a swallowed error would never make it there.
The one place that I would advocate catching the generic error is right at the UI layer where you obviously don't want to show the user a YSOD, but even then your catch should likely do some logging or something to help you debug later.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
When to use try/catch blocks?
Main method code entirely inside try/catch: Is it bad practice?
When to use Try Catch blocks
Exceptions can occur about anywhere, so this made me think: should I always wrap my code in try..catch blocks?
This is for C#.
(I might be missing something fundamental here, as I'm still a newbie)
EDIT: It appears that this was indeed not a very smart question. The only thing we have learnt at school is to use try...catch to prevent crashes. What we did with the exception was showing a MessageBox to tell the user that 'something went wrong when writing this file'.
Exceptions can occur about anywhere, so this made me think: should I always wrap my code in try..catch blocks?
Good question. Here's a related question:
Axe-wielding maniacs can be just about anywhere, so: should I wear axe-resistant body armor 24 hours a day?
I am fortunate to live in a neighborhood where the number of axe-wielding maniacs is sufficiently low that I don't wear armor when I leave the house. But suppose I did not. Is the right solution to wear the armor all the time or to jail the maniacs?
If your programs throw so many exceptions that you need to be handling those exceptions everywhere, then you have a big problem. The solution to that problem is not to armor up and put exception handling everywhere. The solution to that problem is to eliminate the code that is throwing the exceptions, and if you cannot eliminate it, then isolate it to a tiny region of code that does use exception handling.
Absolutely not. Here's a great CodeProject article on working with exceptions to get you going.
But more to your point in the OP, Exceptions should only be handled where they need to be handled. This means that a well-implemented application will have a few points in the app (depending on scope of course) where a number of specific, Exception-derived exceptions will be handled and even fewer places (one per thread per a number of best practice suggesttions) where the generic Exception will be handled.
When working with exceptions, don't think in terms of a function returning error information. Exceptions greatly alleviate the tedium of percolating an error condition through your call chain.
No, you should not wrap all of your code in a try-catch. I answered a similar question here on dba.stackexchange.com - how much overhead an error in RDBMS has.
Generally you should only use exception handling if there's something specific that you want to do with the error message, or if the code that failed produces results that aren't used anywhere else. If the application is user-facing, you obviously don't want them seeing raw exception messages either. In all these cases, you should be logging the failure...no sense in trapping for an exception that you don't plan on handling (empty catch = bad). But otherwise, you will want an exception to be thrown.
For instance, you make a database call and it fails with a SQL Exception. The next part of your code is designed to process that result, so you will want an exception to be thrown and program execution to be halted.
If your code is regularly producing exceptions (and driving logic off of that), you should probably rethink your approach.
This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
Do try/catch blocks hurt performance when exceptions are not thrown?
Hey everyone,
Just a quick question about try..catch blocks. I've heard they're expensive to use and shouldn't be used as part of a program's flow. However, in order to validate email addresses, I'm using the following code.
try
{
MailAddress checkEmail = new MailAddress(testEmail);
return true;
}
catch
{
return false;
}
Due to prior validation, I don't many exceptions to be caught unless it's an attempt to bypass validation. My question is, are Try...Catch blocks only expensive if an exception is caught, or is it always expensive regardless of whether any exception is thrown?
Thanks
EDIT : Thanks for all the replies. I've decided that since the checking (in C#) isn't very expensive, I'll stick with this method. It's mainly because an actual exception being thrown is rare since there are prior validation steps that ensure no one accidentally enters an invalid email address.
In general, in today's implementations, entering a try block is not expensive at all (this was not always true). However, throwing and handling an exception is usually a relatively expensive operation. So, exceptions should normally be used for exceptional events, not normal flow control.
Performance is only one factor to consider, though, especially in the modern world. If (for instance) you're doing something once in response to a user action, it probably doesn't matter from a performance standpoint whether you use an exception even when you could have done a proactive check instead, provided the exception happens quickly enough the user isn't jolted.¹ But if you're doing something in a tight loop that's going to run hundreds of thousands of times, or you're writing a web application that may need to handle a huge load, you'd probably want to avoid using an exception for a normal case.
¹ More than a decade ago I was responsible for enhancements to a .Net 1.1 "no touch deployment" application in which the first exception thrown took fully three seconds. This was a sufficient problem in one use case involving opening a file the user had asked for which might reasonably not be there that I had to add a check for file existence prior to trying to open the file, which is normally poor programming practice (just try to open the file and handle the exception if that fails), purely because the user experience waiting for that exception to get built was so poor. But that's probably not the world we live in now.
They are pretty cheap unless there is an exception. So you should avoid them when an exception is expected, as in your example above.
I think exceptions on bad user input are generally unwise. Exceptions on out of memory or other unexpected failures are fine.
Just to play devils advocate - I have found a great use for using Exceptions for flow control: The 'cancel' button.
If you have a function running on some service that may take 10-120 minutes, which is doing a bunch of different things, I've found that doing if(hasCanceled) throw new JobCancelledException() inside of my Log() function (which logs at each step that I'm at) to work just friggan awesome. It bails out of the current execution of code and stops running the job - exactly what I need. I'm sure there's some better way to do it, maybe somehow using events - but for my case it works great (especially since jobs are not regularly cancelled).
Other then that though - I'm 100% in agreement that Exceptions should never be used as a flow control tool..
#Kornel - I have two words for that post... Holy $hit =)
here's a simple pseudo code sample:
Class Job
{
Public Run(param1,param2,etc...)
{
Try
{
Log("Doing Something")
DoSomething()
Log("Doing Another")
DoAnother()
Log("This keeps going, etc, inside of these function we make the same Log calls where it makes sense")
Etc()
}
Catch(JobCancelledException)
{
status="Cancelled"
}
}
Private Log(ByVal str As String)
{
MessateToUser(str)
if(hasCancelled)
throw new JobCancelledException
}
private SomeEvent_WhenUserPushesCancelButton()
{
hasCancelled=True
}
}
Exceptions are only expensive if an exception is thrown. I'm sure there is some very minimal cost to setting up up a Try..Catch block but it is by far outweighed by the cost of not catching the exception at all and having your program crash. As others have pointed out, Try..Catch blocks should only be used for exceptional circumstances.
The overhead of the try block is very low, so if no exception is thrown then there should be no noticeable penalty. The main overhead that occurs when an exception is thrown is the stack walk that takes place looking for a handler - since you are caching the exception so close to the source, I doubt there will be much of a performance issue. Ideally though you would be able to validate your inputs properly beforehand, but email validation is fairly complicated so it may well not be worth it in this case.
It's only expensive if the exception is thrown, but that's not an excuse to use exceptions as normal flow control.
If you can pre-validate something to avoid an exception occurring in the first place, then do so. E.g. instead of what you posted, something like this would be preferable:
string invalidAddress = "notvalid######lolzors.bomb";
return MailAddressValidator.IsValid(invalidAddress ); // doesn't cause exception
The exception to the rule is when you'd have to roll your own version of a complicated method (e.g. something found in the base class library that doesn't have a TryParse method) just to avoid an exception that, in the grand scheme of things, just doesn't matter.
If you are unsure, profile using representative data. If it's a user entering data in a client app form every other second, it won't matter. However, if it's a service for processing batches of thousands of email addresses that could come from anywhere, you ought to be sure of your assumptions.
try..catch blocks should never be used as a tool for program flow control.
Read this thread if you're unconvinced.
In general, modern compilers impose only a minimal cost on try blocks unless an exception is thrown. They still shouldn't be used for program flow control, as they aren't as obvious as standard flow constructs. An exception is essentially equivalent to a COME FROM statement.
While it is true that you should never use try..catch for program flow control, I am not aware of any performance issues IF no exceptions are actually thrown in the code
This is language-dependent, but as far as I know in Java, if no exception is thrown, there is next to no performance cost to having a try/catch.
So in your example of using pre-validated email addresses, what you have is fine.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Do you prefer checked exception handling like in Java or unchecked exception handling like in C# and why?
I think checked exceptions are a failed experiment. The original goal of exception was to eliminate the need to validate every function call return, which was resulting in programs programs that are difficult to read, and probably inefficient as well, thus discouraging programmers from signaling and handling exceptions.
While great on paper, in practice the checked exceptions reintroduced the very same problem exception were supposed to eliminate in the first place. They add a tightly coupling between the layers of application. They make it impossible for libraries to change their implementation in subsequent versions. The link posted by crausher goes into details and explain the problems much better than I ever could.
Meh.
Checked exceptions are a great thing when used properly, but more often than not they lead to stuff like:
doSomething();
try
{
somethingThrowsCheckedException();
}
catch(ThatCheckedException)
{ }
doSomethingElse();
And, frankly, that's just wrong. You should let exceptions you don't handle bubble up.
Checked exceptions used properly can be good. But very frequently, the result of doing checked exceptions properly is method signatures like this:
public void itMightThrow() throws Exception1, Exception2, Exception3, Exception4, // ...
Exception12, Exception13, /* ... */ Exception4499379874
{
// body
}
Am I exaggerating? Only slightly.
Edit:
That said, one thing I prefer about C# over Java when it comes to exception handling has nothing to do with checked exceptions (I can get that if I go with Spec# anyway). No, what I like is that the stack trace in C# is populated when you throw an exception, rather than when you instantiate one as it is in Java.
Edit 2: This is for the commenters #Yishai, #Eddie, #Bill K:
First, you should check out this thread for information on how to get a stack trace without instantiating an exception. Keep in mind that walking the stack is a heavy process and should not be done on a regular basis.
Second, the reason I like C#'s exception stack trace being populated at throwal rather than at instantiation is that you can do things like this:
private MyException NewException(string message)
{
MyException e = new MyException(message);
Logger.LogException(message, e);
return e;
}
// and elsewhere...
if(mustThrow)
{
throw NewException("WHOOOOPSIEE!");
}
That's a trick you can't do in Java without having the NewException method included in the stack trace.
I prefer checked exceptions for things that can go wrong that you cannot predict ahead of time. For example, IOException, or SQLException. It tells the programmer that they have to account for something unpredictable going wrong, they cannot write robust code that will not throw an exception, no matter how much they try.
Too many times programmers view a checked exception as a language thing to handle. It isn't (or won't be in a well designed API) - it is an indication that there is unpredictable behavior inherent in the operation, and you should rely on a deterministic result of the operation always working the same given the same inputs.
That being said, in practice checked exceptions suffered from two things:
Not all applications written in Java need that robustness. A compiler-level flag to turn off checked exceptions would be nice - although that could lead to APIs abusing checked exceptions when their developers work with the flag set to turn them off. After thinking about a better comprimise here, my current thinking is that a compiler warning is the best ballance here. If checked exceptions were compiler warnings, including a compiler warning if one was ignored several layers down (so the fact that one was ignored would be compiled into the class), so that the caller would at least know to catch Exception even if he couldn't know which one, then those who don't care would ignore the compiler warning, and those who do would not, without anyone being forced to write error handling code they don't care about to get their code to compile.
Exception chaining took much too long (version 1.4) to introduce. The lack of exception chaining caused a lot of bad habits to develop early, instead of everyone just doing:
throw new RuntimeException(e);
when they didn't know what to do.
Also, a checked exception is another API design element to potentially get wrong, and the users of the API have to suffer with the design flaw.
EDIT: Another answer points to two issues that motivated the C# design decision of no checked exceptions. To my mind, both of those arguments are very bad, so I thought they were worth addressing/counter balancing.
Versioning. The argument is that if you change your API implementation and want to add additional checked exceptions, then you break existing client code.
Scallability. Before you know it you have a method that throws 15 checked exceptions.
I think both versions suffer from the unaddressed point that when those remarks were made it was already accepted that the proper way to deal with a checked exception moving up to the next level would be by wrapping a different checked exception appropriate to the abstraction of your API. For example, if you have a storage API that could deal with IOException, SQLException, or XML related exceptions, a properly desgined API would hide those differences behind a general PersistanceException or something like that.
Besides that general design guidance, in the specific the arguments really lead to a lot of questions about the alternatives:
Versioning. So a developer developed against your database API, thinking that they caught and handled the relevant exceptions (say DatabaseException) and then you decide in the next version to add a NetworkException to capture network level communication issues with the database. Now you just broke all compatability with existing code, and the compiler won't even complain about it. Everyone gets to discover it in regression testing, if they are lucky.
Scalability. In the C# solution, if three API levels down there is a potential for access to a volatile resource, you are relying entirely on the API documentation, because the compiler won't tell you that.
That is a great design for web apps where dying and showing the user a nice error 500 page is about all anyone bothers doing (since transactions are handled by the container anyway). But not all applications are built with such requirements in mind.
The argument ends up boiling down (to me anyway): Don't worry about exceptions, anything can go wrong and just build a catch-all.
OK. That is the core difference between a checked and unchecked exception approach. The checked exception alerts the programmer to volatile unpredictable calls. The unchecked exception approach just assumes that all error conditions are of the same class, they just have different names, and they are made unchecked so that no one goes around catching them.
Now the arguments do have merit at the CLR level. I agree that all checked exceptions should be at the compiler level, not the runtime level.
I have never used Java, but since I read
Why doesn't C# have exception specifications?
Does Java need Checked Exceptions?
The Trouble with Checked Exceptions
I am quite sure I don't like checked exceptions (in the current implementation).
The two main points mentioned are the following.
Versionability
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.
Scalability
Anders Hejlsberg: The scalability issue is somewhat related to the versionability issue. In the small, checked exceptions are very enticing. With a little example, you can show that you've actually checked that you caught the FileNotFoundException, and isn't that great? Well, that's fine when you're just calling one API. The trouble begins when you start building big systems where you're talking to four or five different subsystems. Each subsystem throws four to ten exceptions. Now, each time you walk up the ladder of aggregation, you have this exponential hierarchy below you of exceptions you have to deal with. You end up having to declare 40 exceptions that you might throw. And once you aggregate that with another subsystem you've got 80 exceptions in your throws clause. It just balloons out of control.
In the large, checked exceptions become such an irritation that people completely circumvent the feature. They either say, "throws Exception," everywhere; or—and I can't tell you how many times I've seen this—they say, "try, da da da da da, catch curly curly." They think, "Oh I'll come back and deal with these empty catch clauses later," and then of course they never do. In those situations, checked exceptions have actually degraded the quality of the system in the large.
OK, I wasn't going to reply, but this is taking too long to get closed and got many answers on one side of the fence, so I feel the need to weigh in on the other side.
I support checked exceptions -- when properly used -- and believe that they are a Good Thing. I've heard all of the arguments above many times, and there is some merit in some of the arguments against checked exceptions. But on net, I think they are positive. Having programmed in C# and Java, both, I find C# programs are more difficult to make stable against Exceptions. The great thing about checked exceptions is that the JavaDoc is guaranteed to tell you that the Exceptions can be thrown from that method. With C#, you rely on the coder to remember to tell you what exceptions may be thrown from any given method, and also what exceptions may be thrown from any method called by that method, and so on.
If you want to create 5-9's reliable code, you need to know what exceptions can be thrown from code that you call, so you can reason about what can be recovered from and what must cause you to abandon what you are doing. If C#, you can do this, but it involves a lot of trial and error until you have seen all of the possible exceptions that can be thrown. Or you just catch Exception and do your best.
There are pros and cons to both approaches, that of Java and C#. Reasoned arguments can be made in favor of both, and against both. Again, on net, I prefer the approach chosen by Java, but were I to re-write Java today, I would change the APIs to change some checked exceptions into runtime exceptions. The Java API is not consistent in its use of checked exceptions. And as someone else said, it took far too long for Exception chaining to appear as a standard API feature and a part of the JVM.
However, the charges that are lain at the feet of checked exceptions too often fall into the category of, "lazy programmers misuse this language feature." That's true. But that's true of many languages and their features. The "lazy programmer" argument is a weak one.
Let's address the main complaints that don't fall into the "lazy programmer" bucket:
Versionability - yes, throwing a new Exception in a new version of your code will break compilation for clients who blindly drop in your new JAR file. IMO, this is a good thing (as long as you have a good reason for throwing an additional checked exception), because the clients of your library have to reason about what they need to do with this behavior change. If everything is unchecked, then your clients don't necessarily have any clue (until an Exception occurs) that your behavior has changed. If you are changing the behavior of your code, then it's reasonable for your clients to have to know about this. Have you ever updated to a new version of a 3rd party library only to find its behavior has invisibly changed and now your program is broken? If you make a breaking behavior change in your library, you should break automatic compatibility with clients using earlier versions of your library.
Scalability - If you handle checked exceptions properly by translating them to a specific checked (or unchecked) exception appropriate to your layer of the API, this becomes a non-issue. That is, if you code properly, this problem disappears. And doing so, you properly hide your implementation details, which your callers shouldn't care about anyway.
Too often, this is simply a religious issue with people, and that's why I get (unnecessarily, I know) irritated. If you have a religious aversion to checked exceptions, that's OK. If you have a reasoned argument against checked exceptions, that's OK. I've seen good reasoned arguments (that I mostly don't agree with, but still...). But mostly I see bad arguments against checked exceptions, including arguments which were fair and reasonable when talking about Java 1.0, but which are no longer applicable given modern releases of Java.
In practice it is better to use checked exception handling as it allows for more detailed information when your app begins flooding error logs at 2AM and you get a call to do some debugging...
In my opinion there exist cases where checked exceptions are appropriate. There are probably features that could be done differently in Java to better support them. It isn't without difficulties (for instance, in some situations you might want an exception checked, in others not). Java does, of course, support unchecked exception types as well.
The sort of exceptions that are suitable to be checked should generally be documented. The best place to document is in the code. The populist approach is just to botch it and only consider the happy case.
Checked exceptions are great as long as they are recoverable or not due to programming errors like an invalid index acces to a ResultSet. Otherwise they tend to pollute code layers and APIs by forcing the coder to declare things like IOException in many method signatures and giving nothing really useful to the client code.
I think in most cases checked exception are a waste of time. They entrap to things like the antipattern mentioned by randolpho or extensive creation of custom exceptions to decouple your implementation from used libraries.
Beeing rid of this 'feature' lets you focus on what you want to do.
The only thing I'dd like the compiler to check for me is whether a function throws exceptions or not. What specific exceptions that can be thrown doesn't matter. The thing is that in my experience, there are a lot functions that don't throw anything, and it would be nice if this was documented in the function specification. For these functions you don't have to worry about exception handling.
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.