Is it a good or bad idea throwing Exceptions when validating data?

ValidationException

Validation Problem Overview


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

Note: I don't 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("Failed 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?

Validation Solutions


Solution 1 - Validation

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?

Solution 2 - Validation

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

Solution 3 - Validation

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).

Solution 4 - Validation

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.

Solution 5 - Validation

In the title you call it "validating" data. That can happen on several levels. In (near) the GUI where you are checking user entered data, you should be expecting errors and have ways to report the errors back. Exceptions are inappropriate in this case.

But Data Validation can also happen at other boundaries, say between business-rule classes. There, errors in the data are uncommon and unexpected. You should throw when you detect one.

Solution 6 - Validation

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.

Solution 7 - Validation

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.

Solution 8 - Validation

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.

Solution 9 - Validation

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.

Solution 10 - Validation

I would suggest that using exceptions as described in the question (for flow control within a function) is wrong not usually the best idea. I'd go further and saying validation throwing exceptions isn't the best approach; instead return a Boolean and store a list of validation error messages that can be accessed. An accompanying save method could/should throw an exception if it is called on an invalid object.

Thus if validate fails validation error messages can be displayed to the user (logged, returned. whatever). If validation passes then you can call save. If you call save on an invalid object then get get an appropriate exception.

Another potential problem with your example code (depending on requirements of course) is it only throws the first validation error that occurs. Imagine this from a users POV:

  • Click save
  • Get an error message
  • Correct error
  • Click save again
  • Get a different error message. Annoying.

As a user I'd prefer to get all validation errors returned at once so I can correct them all before trying again.

Solution 11 - Validation

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 http://diveintopython.net/file_handling/index.html#d0e14344">Using Exceptions For Other Purposes, for example.

Solution 12 - Validation

When you go to the grocery and ask the seller if he's got cheese, and the seller replies with no, would that be an unexpected or exceptional response? What about if you do the same but the seller just looks at you and does not respond!

Another example, you are talking to your friend and ask if there is something wrong, you may get 2 responses:

  • They tell you that they are sad because of something.
  • Or they just look at you and say nothing, turn their back and walk away and you are sure that this means you're in deep trouble :)

Same way with exceptions, unexpected behavior is an exception, but an invalid but expected response should not - IMHO - throw exceptions.

Solution 13 - Validation

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" :)

Solution 14 - Validation

This question is still interesting, mainly because of the answers.

When it comes to exception, there is a lot of arguments involved. We can defend a point to any direction we want to, from performance to exception philosophy. And they all sounds right to me.

But sometimes we have to stick to a direction. In this case, I think it's the validation itself.

When we want to validate something we also want to know (to log, or to show the user) whats wrong when the parameter is invalid. Even thought there are layers of validation such as Business Validation mixed with User Input validations.

For instance, when dealing with user input, a lot of weird cases can happen. A pasted data from a website full of hidden char (\t \n etc), typos, and a really huge kinds of cases that a specific exception could allow further analysis or message to the uses much more precisely than a simple "false" return.

Solution 15 - Validation

Well, i know it's an old question. But i'll let my opinion here for the googler's who falled here like me:

  1. If you are using a language with a bad try/catch support AVOID THROWING exceptions for data validation;
  2. DO NOT THROW a exception that will not be handled by the caller or alserwhere;
  3. DO NOT THROW a exception if you need to validate the rest of the received data;
  4. You can THROW a exception in cases where the code block cannot continue without the invalid data; And if you do not interrupt the process you can get a unhandled exception;

An example:

/*
 * Here it's a common problem i have: Someone pass a list of products i need to
 * retrieve from the database and update some information;
 */

//This is a class to represent the product
function Product(id, name, price) {
	this.id = id;
	this.name = name;
	this.price = price;
}

//This is an example function to retrieve the product from the database
function findProductInDatabase(productId) {

	//If the product exists on the database, the function will return it
	if (productId == 12) {
		var product = new Product(12, "Book", 20.5);
		return product;
	}
	
	//If the product do not exists, it will return null
	return null;
}

//This is a function that will receive the productID and will update the received parameters
function updateProduct(productId, newProductName, newProductPrice) {

	var productFromDatabase = null;
	var errorMessage = "";
	
	//Retrieve the product
	productFromDatabase = findProductInDatabase(productId);

	//If the product do not exist, i need to interrupt de method imediatily and alert the caller
	if (!productFromDatabase) {
		throw "Product not found";
	}
	
	//Validate the other parameters, but in this case	i can validate all the parameters
	if (newProductPrice < 10) {
		errorMessage += "the price is too low";
	}
	
	if (newProductName.includes("<")) {
		
		//If already has a error message in the variable i append " and " to the message make sense
		if (errorMessage) {
			errorMessage += " and ";
		}
		
		errorMessage += "the new name has invalid characters";
	}
	
	if (errorMessage) {
		//if theres any error, i will throw a exception with the messages
		throw errorMessage;
	}
}

//This parte is where the method id called;
try {
	updateProduct(9, "Book", 10.5);
} catch (exception) {
	console.log("Case 1: " + exception);
}
try {
	updateProduct(12, "<Book", 9);
} catch (exception) {
	console.log("Case 2: " + exception);
}

Solution 16 - Validation

I often write similar code for validation, especially in express.js, and similar request/response loop style applications. When something is invalid, I throw a ValidationError, it's caught by the top level error handler, which knows to send a 422 response with the additional information that's attached to the ValidationError.

It's a very convenient way to handle validation. You don't have to pass around an error object (potentially up through a dozen stack frames, in some cases). And it's a simple and consistent way to trigger an invalid input response. I haven't experienced any serious problems with this approach.

I've thought about the "don't use exceptions for flow control" maxim in relation to this practice, and decided the benefits outweigh any disadvantages. I would say if you understand the reasoning behind "don't use exceptions for flow control", but you determine that it's a good idea anyway in a certain case, then go ahead and do it. We don't need to be too dogmatic about these things.

Throwing exceptions is relatively slow, but that will only matter if you're doing it repeatedly in a loop.

Solution 17 - Validation

In test, sure, but in a live environment, you'd hope they're never raised. You'd hope to refactor your code to the extent that all data into your system are validated at source, and either the user, or the system that generated the input to your system, is notified of the issue. Exceptions should occur if you've missed something and should be a fallback that is handled gracefully. You could store anything that's causing these exceptions separately, so that they don't make it into your system without being checked over first. You don't want, e.g. an invalid value that falls outside a range of values to skew your results.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMoSloView Question on Stackoverflow
Solution 1 - ValidationJonoWView Answer on Stackoverflow
Solution 2 - ValidationMusiGenesisView Answer on Stackoverflow
Solution 3 - ValidationKLEView Answer on Stackoverflow
Solution 4 - ValidationDominic RodgerView Answer on Stackoverflow
Solution 5 - ValidationHenk HoltermanView Answer on Stackoverflow
Solution 6 - ValidationTLiebeView Answer on Stackoverflow
Solution 7 - ValidationpbrView Answer on Stackoverflow
Solution 8 - ValidationakfView Answer on Stackoverflow
Solution 9 - ValidationkgiannakakisView Answer on Stackoverflow
Solution 10 - ValidationmattumotuView Answer on Stackoverflow
Solution 11 - ValidationmavnnView Answer on Stackoverflow
Solution 12 - Validationyoseph ehabView Answer on Stackoverflow
Solution 13 - ValidationPhilip DavisView Answer on Stackoverflow
Solution 14 - ValidationggoncalvesView Answer on Stackoverflow
Solution 15 - ValidationMichael WallaceView Answer on Stackoverflow
Solution 16 - ValidationAurastView Answer on Stackoverflow
Solution 17 - ValidationmuirisOGView Answer on Stackoverflow