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.

Possible Duplicate:
Defensive Programming vs Exception Handling?

I don't know, that this question fit better on this site, or Stack Overflow, but because my question is connected rather to practices, that some specified problem.

So, consider an object that does something. And this something can (but should not!) can go wrong. So, this situation can be resolved in two way:

first, with exceptions:

DoSomethingClass exampleObject = new DoSomethingClass();
try
{
     exampleObject.DoSomething();
}
catch (ThisCanGoWrongException ex)
{
     [...]
}

And second, with if statement:

DoSomethingClass exampleObject = new DoSomethingClass();
if(!exampleObject.DoSomething())
{
     [...]
}

Second case in more sophisticated way:

DoSomethingClass exampleObject = new DoSomethingClass();
ErrorHandler error = exampleObject.DoSomething();
if (error.HasError)
{
     if(error.ErrorType == ErrorType.DivideByPotato)
     {
         [...]
     }
}

which way is better? On one hand, I heard that exceptions should be used only for real unexpected situations, and if programmer knows that something may happen, they should use if/else. On the other hand, Robert C. Martin in his book Clean Code wrote that exceptions are far more object oriented, and more simple to keep clean.

share|improve this question

marked as duplicate by jmquigley, Jarrod Roberson, gnat, Walter, Yannis Rizos Mar 27 '12 at 7:04

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

11  
It depends. If the error is exceptional then use exceptions, if it could be frequent then trap it with if tests - these are less expensive. –  ChrisF Mar 26 '12 at 12:29
    
Using exceptions for control flow is like using goto for loops or setjmp/longjmp for nested returns. Sure, it can be done but you feel a little dirty at the end of the day =) IMO –  Patrick Hughes Mar 26 '12 at 18:55
3  
Have you seen this Article-- "Cleaner, more elegant, and harder to recognize" The author is a pretty well recognised authority on programming and has some pretty good points here. –  Vaibhav Garg Mar 27 '12 at 6:26

9 Answers 9

up vote 25 down vote accepted

Typically, I tend to use exceptions for exceptional cases - the instance where nothing should go wrong, and if it does go wrong, that's a big problem. An example might be a missing configuration file that ships with the software or a missing hardware driver. If these things happen, that's a huge problem. I will perform checks on things like user input or optional instances where there's a good chance that I'll be given invalid information.

However, it should also be noted that some languages appear to favor exceptions. For example, I've noticed that the use of exceptions for even minor problems is much more common in Python. In the Python community, this is known as EAFP - "Easier to ask forgiveness than permission".

share|improve this answer
3  
    
The usual examples for Python can be generalized into: 1) Duck typing, which needs to be supported by the language to easily use it, and 2) tight race conditions that should be using try/catch regardless of the language (checking if a file exists before reading it, for example. It may get deleted in the interim, or may actually be a directory for some reason, and you didn't check for it!) –  Izkata Mar 26 '12 at 18:13

If exampleObject.DoSomething(); SHOULD NEVER cause a problem, use exceptions.

If there are valid, expected business cases where exampleObject.DoSomething() will cause an error, use if/then/else and use comments to describe cases when this might cause a problem.

Example:

Thing thing = findThingInDatabase();

//if a thing was found in the database (we EXPECT thing to not be found sometimes, hence if stmt as opposed to exception)
if (thing != null){
    thing.doStuff();
}
share|improve this answer
    
This argument is a common one but I find it hard to use as a good rule of thumb. IN the really tricky case its hard to decide whether something is "rare" or not. –  hugomg Mar 26 '12 at 13:18
    
@missingno I think: "If there are valid, expected business cases where exampleObject.DoSomething() will cause an error" is pretty easy to follow, assuming you can find a business expert to ask... –  Joshua Drake Mar 26 '12 at 18:02

Take in account that in case of if/else you're going to perform that check every time, regardless if execution was successful or not. Thus if error case is occurring rarely or practically never under normal circumstances, then exception handling is way more efficient, as on successful execution you're not evaluating any additional conditions.

Another advantage of exceptions over checking in case of multithreading or distributed systems is avoiding race conditions resulting from TOCTTOU (time of check to time of use) problem. You check condition first, then execute code assuming that condition holds. Without assuring atomicity with locks/mutex or so, at time of executing code condition might already been changed by another thread/process.

share|improve this answer
5  
This sounds a lot like "premature optimization". Checking the return code for true/false hardly ever causes a measurable performance penalty. TOCTTOU is not an issue here, either. –  user281377 Mar 26 '12 at 13:00
2  
@ammoQ: TOCTTOU may not be a problem in example used in question, but I've seen TOCTTOU way to often in distributed systems. In code written by experienced programmers, so it isn't just a newbie issue. –  vartec Mar 26 '12 at 13:12

Usual way of error handling is this :

  • if you can solve the problem locally, then use if statement (or if the function throw an exception, handle that exception)
  • if you can not solve the problem locally, then throw an exception (or if the function throw an exception, let it propagate further), and handle it where you know what to do about it
share|improve this answer

I've used exceptions for their information carrying ability. In C++, a function return code is usually a single value. In contrast, you can throw exceptions of any class type containing any information that you want.

I used an exception to return the specific piece of a query that was not found. It seemed the lesser evil than to add a mostly unused pointer or reference to each function call in a 7-deep call stack.

share|improve this answer

You Use Exceptions for Exceptional situations where if else block couldn't handle, like connecting to a database, if the database is not available, what will you do? would you connect to another database? or just abort the operation? and other situations like these are the ones where you should use exceptions.

But you should always keep in mind that don't over used Exceptions, like having an index Out of bounds index error, then you'll use exception for that.

share|improve this answer
X x;
try
{
     x = exampleObject.DoSomething ();
}
catch (ThisCanGoWrongException ex)

If doSomething returns something, it can't meanwhile return an error, except there is enough room in the result Space. A well known instance of this phenomenon is a C-library, which reads a byte and returns an int. While bytes are considered unsigned, the error-case is/was a -1.

But now you have to do an ugly cast to do.

What do you do, if the result space does not give you room for results, meaning "invalid"? Well, you can use a Wrapper, which returns, instead of an T an Either[Error, T]. The right result usually means an result which is alright, and left is left to mean a kind of error.

Instead of the Error as special kind of value, the user of your library is - in statically typed languages - informed beforehand, that there is something which might go wrong.

In contrast, for

  String ips = getIP ("programmers.se.com");
  // returns "err.or.in.DNS" in errorcase - but programmer 
  // forgot to check 
  for (String b : ips.split (".")) {
       Integer.parseInt (b); // crash here

Sometimes, methods get called for their side effect, and the return value isn't inspected at all. Then an error can slip through undetected.

  user.setAge (-42); 

Maybe the class returns a "false" or a message "Invalid age, must be >= 0". But many languages allow to ignore the returned result. An exception would be preferred here.

A problem with exceptions and wrapped result is, that they sometimes clutter the code, and make it harder to follow the healthy case. Maybe we will see improvements there in the future - Java is for example trying to simplify the handling of exceptions recently. IDEs could probably hide or fold exception code on demand.

In some cases, it might be reasonable to return a special Null object. Think about searching a special User in the Database. If something goes wrong, you could return null.

    println (null.getName ()); // crash: NPE

An often seen solution is, to return a List with one Element in the normal case, and zero values in the defect case.

    users = db.get ("Zappa");
    for (User u : users) {
         u.doSomething ();

This will work with one or none Element, and Languages like Haskell or Scala have a special purpose class for this, a Maybe or an Option.

Option is a parametrized class. An Option[T] is either a Some (T) or a None. The user still has to check the result, but can't forget it that easily.

This is similar to the result of an empty List, and might not be appropriate everywhere, but often it is.

share|improve this answer

Another thing to consider is that when exceptions occur there is a performance penalty or a cost associated with that exception.

For example, run X/Y in a loop.

One way is to use an if statement. Example:

if (Y != 0) 
{ 
   result = X/Y;
}

Another way is to use a try/catch.

try
{
  result = X/Y;
}
catch (DevideByZeroException zeroEx)
{
  //Log Error
}

If you run this in a loop (million times) you will find the if statement runs a lot faster over the try catch when Y = 0.

So, when coding ask yourself, will I hit this condition alot. In this example, how often will Y be zero? 1% or 50% of the time? If 50% then use an if. If just occasionally use a try. If there are 500,000 excpetions occurring, then that is not really an exception to the rule, it is the rule. You want to avoid that.

That's why I tend to think exceptions are for cases that don't happen that frequently. If you have popular use cases that are handled via exception logic, then they should probably be converted to use logic statements (ifs) versus exceptions. And as a bonus your code will speed up as well.

share|improve this answer
2  
Just to be clear: there is a performance penalty when the exception is thrown, as of course there must be as there is a lot of information in an exception and gathering that information takes time. Depending upon your language, there may be little to no penalty when an exception is not thrown - which goes to show that exceptions should be exceptional. –  jmoreno Mar 26 '12 at 20:46
    
@JMoreno - Correct. Hopefully my example is clear. There is no penalty for having a try/catch. I've update my answer slightly based on your feedback. –  Jon Raynor Mar 27 '12 at 14:10

Exceptions handle exceptional cases; that is, cases that do not fall into the "happy path" of normal program execution. Given this very important caveat, it is generally acceptable, and in fact expected, to use try/catch in cases where (a) something can fail, and (b) you know what to do when it does.

The primary situation in which you would not use try-catch is when knowing the success or failure of a method is at least as important as the actual result of the operation. An example is string parsing; many times, it's at least as useful to know if a string consists of a number or not, than what the number actually is. .NET thus provides "TryParse" flavors of the Parse functions built into the primitive types. They allow you to structure your code with a simple decision at the beginning of an if/else fork, that then determines entry into one or the other of the code blocks.

For instance, say DoSomething()'s success determines whether to print "Yes" or "No" to the console. Both are "normal" things for the program to do. You could write it like this:

try
{
   DoSomething();
   Console.WriteLine("Yes");
}
catch(Exception)
{
   Console.WriteLine("No");
}

... but there are a couple of problems; first, from a design standpoint, it's not obvious without comments that DoSomething() is a decision being made. Second, DoSomething() may not be the only thing in the try block that could throw an exception. Let's say another developer added some additional code that they need to run when DoSomething succeeds:

try
{
   DoSomething();
   Console.WriteLine("Yes");
   DoSomethingElse();
}
catch(Exception)
{
   Console.WriteLine("No");
}

Now, you have a scenario in which DoSomethingElse() could fail after DoSomething() succeeded, and the result to the end user from one input would be the very confusing:

Yes
No

Instead, consider this:

if(TryDoSomething()) //a "non-throwing" variant that returns success or failure
{
   Console.WriteLine("Yes");
   DoSomethingElse();
}
else
{
   Console.WriteLine("No");
}

The concept that DoSomething is the criteria of a decision between two "normal" execution paths is much clearer in the above code. And, your desired logic flow is enforced no matter what; If DoSomething() succeeds, the user will never see "No" displayed on screen no matter what DoSomethingElse() does.

In most other cases, try-catch is preferred, for one or more of the following reasons:

  • try-catch allows you to use the return value of a method for what is was conceptually designed to do; return the result of the operation, instead of a status code indicating whether a valid result is contained in an output or reference parameter that is the REAL product of the method.
  • try-catch allows for more object-oriented error-handling, as was mentioned, by avoiding the use of "magic numbers"; you don't have to know that return code -2 of this method is an error that an argument was null, you just catch an ArgumentNullException. And, you can catch that same ArgumentNullException thrown from any method that cares whether one of its passed parameters was null, instead of having to know that this method would return -2 and another method returns -3 in the same situation.
  • By that token, try-catch helps to standardize the expected behavior in a particular exceptional case. If you pass a null parameter to a method that requires that parameter to not be null, you will get an ArgumentNullException, and it is usually bad practice to throw any other exception or to assume some base case that equates null with a discrete value.
  • try-catch isn't limited to calling methods; you can "try" a possible division-by-zero operation inline in your code and catch the exception thrown by the runtime should it occur.
  • try-catch isn't limited to one method at a time; you can, with minimal additional code, handle exceptions from a series of several methods, and abort processing, without having to examine the most recent return code of each method you call.
share|improve this answer

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