views:

377

answers:

10

Hi,

When validating data, I've gotten into a habit of doing the following

*Note: i dont really have individual booleans for each check. This is just for the example.

*Another Note: any error handling during the tests are done properly. The ONLY exceptions thrown in the try-catch are my own.

Try
{

  if(validCheckOne = false)
  { throw new Exception("Check one is bad"); }

  if(validCheckTwo = false)
  { throw new Exception("Fail'D because of check2"); }

  if(validCheckTen = false)
  { throw new Exception("Yet another failure on your part: check10."); }

}
catch(Exception e)
{
  MessageBox.Show("Your stupid data is wrong! See for yourself: " + e.Message);
}

Is this bad practice? Does throwing Exceptions slow the program's execution or is inadvisable?

+14  A: 

I'm going to repeat the mantra here: throwing exceptions should be done in exceptional circumstances. Invalid entered data is really not that exceptional.

MusiGenesis
+1 I totally agree.
KLE
Likewise agreeing. Having a program halt, or otherwise bog down because of bad data is a bad idea: skip it and move on. Mind you, it's good to let the user know that there was bad data found; maybe generate a report or pipe it to STDOUT or something something.
Satanicpuppy
Typical StackOverflow: work your butt off answering difficult, interesting questions, and then get most of your rep points from being the first person to rattle off some simplistic rule. Sigh.
MusiGenesis
what if .. your validation is deeply nested and spread over several classes?
Blauohr
I never agreed with this mantra, especially in a language like Java with checked exceptions (where you can force the caller to handle your exception). The alternative would be to return an error and roll an error handler into the caller. Why would you choose to implement a custom error handler over getting a well implemented one for free in the language that not only likely better than what you would do, but gives you (in a language with checked exceptions) compiler enforcement
Falaina
+3  A: 

This is bad behavior. Exceptions are for Exceptional conditions. They take resources to generate the stack etc. Exceptions should not be used to dictate process flow.

akf
+4  A: 

It depends - if you are expecting the data to be there and NOT having the data is unexpected, then throwing an exception is OK. Throwing an exception is very expensive (slow) but is the best way to handle unexpected circumstances.

TLiebe
+6  A: 

I support MusiGenesis's answer.

Additionally...


The performance of throwing an exception is a thousand instructions. It's nothing compared to end-user time, but in inner code it is slow.

An additional problem is that, using Exceptions, your validation is limited to reporting the first failure (and you will have to do it all again next time to find the next failure).

KLE
+2  A: 

In general it is inadvisable to use Exceptions to implement conditional flow. It would be better to do something like this

  error = false;
  while(true) {
    if(validCheckOne == false) { 
       msg = "Check one is bad"; 
       error = true;
       break;
    }

    if(validCheckTwo == false) { 
       msg = "Check two is bad"; 
       error = true;
       break;
    }
    ...
    break;
  }
  if (error) {
     ..
  }

You should throw an exception when there is a situation you can't do nothing about it. Higher layers of software would have a chance to catch the exception and do something about it - even if that is simply crashing the application.

kgiannakakis
Why is there a while loop? If there are no errors this will spin forever.
Philip Davis
I guess the loop is used to easily break the validation once an error has been detected. But you are right, when there are no errors, a final break in the while loop is needed. Maybe it would be better to put the checks into an own method which returns the error message. Apart from these issues I would vote for this answer.
Oben Sonne
@Philip Davis: You are right about the infinite loop. I forgot a break at the end.
kgiannakakis
A: 

It really only matters if your data validation is in a tight loop. For most cases, it doesn't matter what you choose as long as you are consistent in your code.

If you have a lot of code that looks like your sample above then you might want to clean it up by introducing a helper method to throw...

private void throwIf( bool condition, String message )
{
    if( condition )
        throw new ApplicationException( message );
}

(also, doing this will help zero in on errors such as "validCheckOne = false" versus "validCheckOne == false" :)

Philip Davis
+3  A: 

In addition to the oft-repeated statement that "exceptions are for exceptional circumstances", here's an additionally clarifying rule I've come to like:

If the user caused it, it's not exceptional.

Exceptions are for system-side things (servers going down, resources being unavailable), not for the user doing odd things, because all users do odd things.

Dominic Rodger
+1 for "because all users do odd things"
Matt
+2  A: 

Personally I like throwing Exceptions for business rule validation (not so much for user input validation) because it forces the problem to be handled upstream. If my business objects returned some kind of validation result, it could be ignored by the caller. Call me a cowboy if you wish :)

Everyone here is repeating the phrase "exceptions are for exceptional circumstances", but that really doesn't give any understanding of why its bad to use them for unexceptional circumstances. I need more than that. Is the performance hit of throwing exceptions really that bad? Are there any benchmarks available?

JonoW
This best marks what i originally intended. 'Exceptional circumstances in the business rules' being apart from simple data validation (startDate before endDate and whatnot), forcing execution upstream.My problem is that i got into the habit of doing this for *all* my validation (granted, i need to correct this).Apart from the 'exceptional circumstances' argument, Can anyone show that throwing an exception has a bad effect on the stack? more memory usage or slower execution for example?
MoSlo
A: 

I generally agree with the "exceptions should be exceptional" rule, but I might make an exception (ha!) for Python, where it can be both efficient and considered good practice to use try ... except to control flow.

See Using Exceptions For Other Purposes, for example.

mavnn
+1  A: 

So maybe in some languages exception throwing and catching is "costly" but in other languages, throwing and catching exceptions is exactly what's called for.

In Smalltalk, for example, one could quickly build a multi-tiered exception catching solution. The validation pass could collect up any number of exceptions representing EVERYTHING that's wrong with a particular input data set. Then it would throw them ALL up to a higher-level catcher, responsible for formatting up a human-readable explanation of, again, EVERYTHING that was wrong with the input. In turn it would throw a single exception further up the chain, along with that formatted explanation.

So... I guess what I'm saying is, exceptions are only bad to throw if you've got no exception handling architecture supporting catching them and doing reasonable things with them, and all your catcher is going to do is EXIT or do something else equally inappropriate.

pbr
I completely agree. Another example is OCaml. Ocaml supports very light weight exceptions, foregoing things like generating stack traces, thus making it perfectly acceptable (and commonplace) to use as a control-flow mechanism.
Falaina