C# – Business Objects, Validation And Exceptions

business-objectscexceptionvalidation

I’ve been reading a few questions and answers regarding exceptions and their use. Seems to be a strong opinion that exceptions should be raised only for exception, unhandled cases. So that lead me to wondering how validation works with business objects.

Lets say I have a business object with getters/setters for the properties on the object. Let’s say I need to validate that the value is between 10 and 20. This is a business rule so it belongs in my business object. So that seems to imply to me that the validation code goes in my setter. Now I have my UI databound to the properties of the data object. The user enters 5, so the rule needs to fail and the user is not allowed to move out of the textbox. . The UI is databound to the property so the setter is going to be called, rule checked and failed. If I raised an exception from my business object to say the rule failed, the UI would pick that up. But that seems to go against the preferred usage for exceptions. Given that it’s a setter, you aren’t really going to have a ‘result’ for the setter. If I set another flag on the object then that would imply the UI has to check that flag after each UI interaction.

So how should the validation work?

Edit: I've probably used an over-simplified example here. Something like the range check above could be handled easily by the UI but what if the valdation was more complicated, e.g. the business object calculates a number based on the input and if that calculated number is out of range it should be recjected. This is more complicated logic that should not be in th UI.

There is also the consideration of further data entered based on a field already entered. e.g.I have to enter an item on the order to get certain informaion like stock on hand, current cost, etc. The user may require this information to make decisions on further entry (liek how many units to order) or it may be required in order for further validation to be done. Should a user be able to enter other fields if the item isn't valid? What would be the point?

Best Answer

You want to delve a bit in the remarkable work of Paul Stovell concerning data validation. He summed up his ideas at one time in this article. I happen to share his point of view on the matter, which I implemented in my own libraries.

Here are, in Paul's words, the cons to throwing exceptions in the setters (based on a sample where a Name property should not be empty) :

  • There may be times where you actually need to have an empty name. For example, as the default value for a "Create an account" form.
  • If you're relying on this to validate any data before saving, you'll miss the cases where the data is already invalid. By that, I mean, if you load an account from the database with an empty name and don't change it, you might not ever know it was invalid.
  • If you aren't using data binding, you have to write a lot of code with try/catch blocks to show these errors to the user. Trying to show errors on the form as the user is filling it out becomes very difficult.
  • I don't like throwing exceptions for non-exceptional things. A user setting the name of an account to "Supercalafragilisticexpialadocious" isn't an exception, it's an error. This is, of course, a personal thing.
  • It makes it very difficult to get a list of all the rules that have been broken. For example, on some websites, you'll see validation messages such as "Name must be entered. Address must be entered. Email must be entered". To display that, you're going to need a lot of try/catch blocks.

And here are basic rules for an alternative solution :

  1. There is nothing wrong with having an invalid business object, so long as you don't try to persist it.
  2. Any and all broken rules should be retrievable from the business object, so that data binding, as well as your own code, can see if there are errors and handle them appropriately.