Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Is catching an error with try ... catch a better practice than catching an error with proper analysis/error check? For instance, removing from an empty list: Does surround with a try catch clause considered as a more efficient way than testing if the list is empty beforehand?Or is it the same? Thanks.

P.S: If a similar question was previously asked on the forum please feel free to refer it.

share|improve this question
    
I think contrasting exception handling with "proper analysis/error check" might possibly be seen as just a tiny bit slanted. –  Jerry Coffin Apr 10 '12 at 6:03
    
Well, there are cases where there is no comparison between the two, but I can think of some cases where they converge. For instance, let's take an illegal casting in java, I can either let it fail and catch the exception or I can check whether the element I'm about to cast is an instance of the casting class. Now, which solution appears to be better practice. –  fabricemarcelin Apr 10 '12 at 6:11
    
possible duplicate of if/else statements or exceptions –  vartec Apr 10 '12 at 11:21
1  
@fabricemarcelin: It depends: If in your worflow the object has to have a certain type and nothing else, then an exception is appropriate. If your code permits other types, do the check and don't wait for the exception. I prefer coding styles that avoid exceptions generally, by layouting a good program flow. That makes for a robust program and less headaches. –  Falcon Apr 10 '12 at 11:30
add comment

6 Answers 6

up vote 4 down vote accepted

You should not handle the normal program flow via Exceptions. Exceptions should only be handled if you want to do something with it. If removing an element of an empty list should throw an exception, you should let it throw. If you want to return a new empty list from this method, you should do that.

There is not 1 absolute answer on this matter, you should check it per use-case.

Of course, it never hurts to do some defensive programming and making sure users don't see too much exceptions in the use of the application. In the example you mentioned, I would probably do a null-check and depending on the method, maybe throw a new ArgumentNullException. A try-catch in this situation just feels a little 'dirty' in my opinion, but in a bigger scenario it might make more sense.

Back in the days I've learned throwing exceptions is an expensive operation (random link, check bottom of the page), so avoid them if possible.

Another thing which I don't really like about catching errors is, if you don't narrow them down enough, you could potentially catch an error which doesn't have anything to do with the piece of code you really want to check. For example, if your application is 6-layers and you are calling some method like:

try
{
  otherlayer.Method1();
}
catch(IOException ioEx)
{
  //DoSomething
}

It is possible this IOException catches something which you didn't expect at first, so you will probably handle it wrong. (could happen if someone decides to change the other layers without your knowledge).

In summary: I would advice against using a lot of try...catch blocks in your code, only when they are really necessary and they are adding something usefull, or make sure your program flow will continue to operate.

share|improve this answer
    
+1: good answer but -1: Exceptions are not actually expensive! Constructing them is mildly expensive (but not expensive if compared to any code in an interpreted lang), and throwing them is cheap. –  sparkleshy Apr 10 '12 at 17:53
    
@sparkleshy: OK, I actually measured this once in C#. Using int.Parse vs. int.TryParse in C#. The first one wrapped in try-catch, the latter in an if-statement. The latter was by a major factor (I remember something like 10000x for the number of testruns) faster. So exceptions aren't that cheap and should be avoided in performance critical code on some platforms. –  Falcon Apr 10 '12 at 20:02
    
@Falcon: That's because it constructs an exception. To be fair, there are very few situations where you would actually want to throw a pre-built exception... but exceptions can be reasonably fast. –  sparkleshy Apr 10 '12 at 21:20
    
@sparkleshy: And why is construction expensive in a real world scenario? In C# you cannot even reuse an exception object. So what kind of argument is that? For further information: blogs.msdn.com/b/ricom/archive/2006/09/25/771142.aspx –  Falcon Apr 10 '12 at 21:28
    
Doesn't an exception always need to be constructed for it to be able to be thrown? I would expect null * 1 or throw new NullReferenceException() to be both expensive. I don't see how you can work with exceptions without them to be constructed (somehow). You've got an example (or link) perhaps? –  Jan_V Apr 11 '12 at 9:16
add comment

When to Check in Code

standard things like removing from an empty list, etc.

When to use Try...Catch

  • external access to networks
  • external access to file-system
  • external access to databases
  • etc
share|improve this answer
add comment

Correct me if I get it wrong and I will edit my answer.

You are asking whether if adding an if clause for your code is a better option than a try .. catch.

I believe a try .. catch is better.

Here is why:

  • You can easily group your type of errors in one single kind. Let me give you an example based on Java. I can use a try .. catch for IOException. That is telling your code "Hey! If you get any problems with those I/O guys, please do this!". Notice you don't care what the I/O error is. Someone has already coded many many possible problems with I/O you would never imagine and gives it to you as an IOException. You are reusing their code which will cover much more than what you might believe would be an I/O problem. Benefits? I would say the first and biggest one is having much higher coverage of possible errors.

  • It keeps your code more readable. Imagine a coworker of yours reading your code. Suddenly he sees a sea of conditions and starts wondering what the heck it's for. If he sees an IOException instead (this is just one of them by the way!) he doesn't need to think twice: it is an error you are trying to catch. He can easily understand your thoughts about what your program should do, and thoughts about what the problem should do in case something goes wrong. You don't need to write a huge log of comments on the method regarding your concerns about what could go wrong; it is written there, as an exception. Simple, clean and legible.

  • You are reusing code. I mentioned this in the previous point, but I want to emphasize this. Reuse. Reusing code is a very good practice. Software Product Lines are the best example of that! If there is something already done for you, why go through the trouble of recreating it? The reused code has been there for a while, being used constantly by many people. Most likely they've already come across any possible problem you would think of and they've encapsulated them in e.g., IOException. This principle in a sense underlines open source. Everyone sees it, everyone is using it, most likely it will be fixed soon. I may be stretching the analogy but I hope you get the main point!

  • You can propagate your exceptions and make it easier to understand what went wrong. Imagine a situation where that method catches an exception (let's use IOException again). He doesn't knows what to do with it. What does he do? Tell the method that called him and say: "Hey, I don't know how to deal with this, but I can't go on this way, please do something about it!". Then the caller can do the same until it gets to your main method. If at this point the main method doesn't deal with the exception, the program will crash and dump the exception stacktrace (I'm using Java as my example here), so you know that when something goes wrong what sort of exception caused it. You've probably already come across that NullPointerException that always scream at us for doing something silly! Simple enough, it state its name which, assuming good use of semantics, should be self explanatory. Try imagining yourself writing a message for every error condition: "There was an error with my array, there was a problem with my I/O, etc". This wouldn't scale up to larger systems, right? You can then go and add more refined exceptions too so you get better output about the problem and handle it appropriately. Do also notice that by propagating errors, you don't need to use a try .. catch on every single method that deals with the array. Just do it once on the first method, and let it propagate up to the caller that knows how to handle it. This is not a rule, but might be useful depending on your situation. Also note that some method will need to know what to do with errors, so in a sense you are concentrating all the decisions in a single place. You might want to spread your exception handling around to avoid too much code in a single method!

  • If you deal with the exception, your program goes on despite the problem; it won't stop.

share|improve this answer
    
@Mike Partridge thank you for the editing! –  Oeufcoque Penteano Apr 10 '12 at 17:58
    
No problem. I hope I maintained your intent. –  Mike Partridge Apr 10 '12 at 18:45
    
@OeufcoquePenteano Thanks for the insight. –  fabricemarcelin Apr 10 '12 at 18:51
    
@fabricemarcelin no problem! :) –  Oeufcoque Penteano Apr 10 '12 at 18:56
2  
I have to say that this answer is outright dangerous. You should prevent exceptions from occuring by prior checks wherever possible and adjust your program flow accordingly. For example, in most use cases it's better to check if a file exists and whether you can read/write it before you just try to open it and rely on the exception. Design your program flow in a way that minimizes the amount of exceptions that can occur. This will increase performance, readability and maintainability and lead to robust code. It will also help you to spot possible errors in advance and react accordingly. –  Falcon Apr 10 '12 at 19:38
show 6 more comments

Much of what exception handling helps with is larger systems. In particular, code that detects an error may be several layers away (and written entirely separately from) the code that knows how to react to that error.

For a typical example, let's consider code for opening a file that's buried in some library. Just for simplicity, let's assume it's opening a file for logging. If the log can't be opened, that library code doesn't (and mostly shouldn't) know what to do. It should certainly detect the problem, but it has no idea whether (for example) you want to send out an email, display a MessageBox or NSAlert, etc. By throwing an exception, it let's the code that uses it to make the decision about how the problem is communicated to the user.

As for using an if statement and (for example) return value instead, we run into a similar problem. If we go this route, every layer from deep in the library where the file is opened, on up to the point that we display something to the user, has to cooperate in checking the error code and transmitting it up to a higher level if it something it can't handle itself. Unfortunately, in most cases, it's easier to do the wrong thing (make the call without even checking the return value) than the right one. Just for grins, let's say there are six layers of code between where the problem is detected and where the problem should be communicated to the user. Let's further assume there's a 90% of the programmer doing the right thing at each level. In that case, we get .96 = .53, or only a 53% chance that the error will actually be handled correctly. Even with (in my estimation) above average coding practices (I think 70-80% is probably closer to average) the chances of it being handled correctly are barely better than 50:50.

By contrast, with exceptions, code at intermediate levels doesn't have to do anything for the exception to be transmitted on up to where it can be handled (well, unless you're using Java checked exceptions, but if you do that, you deserve all the problems you get). Exceptions propagate by default instead of being "eaten" by default. We can simplify all the intermediate layers of code because the right thing happens by default.

share|improve this answer
    
Damn right. Exceptions are loved by most and hated by many for their ability to carry data and error information to the place where they should be handled without the need for global error lists or endless "pass errorcode"-cascades. In the empty list example, however, I firmly believe that the exception should be avoided in almost all use cases from occuring by doing a check beforehand. That's also the reason why I didn't upvote your post. You didn't really answer the questions in terms of good coding style etc. and when exceptions are appropriate. –  Falcon Apr 10 '12 at 11:25
add comment

Simple answer: Don't use try-catch for situations where you can check the failure condition in code.

Try-catch should not be used for controlling program flow.

See Vexing Exceptions - it's focussed on C# but is applicable to exception handling in all languages.

share|improve this answer
add comment

Is catching an error with try ... catch a better practice than catching an error with proper analysis/error check?

In 99.9% of cases, the shortest, simplest code is the best.

For instance, removing from an empty list...

If you are attempting to remove a specific item from a list, the item is either there or not there. There is nothing special about an empty list. Checking for an empty list is redundant, just as this if statement is redundant:

if (n > 0) {
  for (int i = 0; i < n; ++i) ...

If you test for the presence of the item, you will be duplicating the work about to be done by the 'remove' call. Don't do it. If the library function throws when the item is not present, go ahead and use try-catch. Consider extracting a new try_remove function that returns true when the item was removed and false otherwise.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.