Back when we put together Validat, one of the topics of discussion was whether validation should occur at the object level or at the data level (i.e. a collection of user submitted data). This topic came up again last week on Ben Nadel’s blog with his postings regarding his class experience with Hal Helms. The comment Ben made that really got me thinking again was ….
An object can only ever exist in a valid state. An object should never be created or allowed to enter a state that is not valid within the domain.
While his discussion of Human and Vehicle objects is nice and illustrates the point fairly well, most times with web applications, we are dealing with a much more “data centric” scenario for lack of a better word. A lot of the functionality we are building is fairly basic CRUD … reading and writing data. So, lets take a shopping cart for example. A shopping cart has a Product object and that Product object is fairly simple containing basic data like a name, description, picture, etc. From the administration interface when the shop owner is creating and editing products, they have a simple form to enter this data. They submit the form and then what? Obviously the submitted data needs validating, but how?
To slip off topic for a second, Ben’s posting seems to hint that he and/or Hal are advocating putting the form level validation into the controller of the application. This is one of those areas where it is probably more personal opinion rather than right vs. wrong, but I am still of the belief that the controller layer of an application should merely be the traffic cop in the intersection guiding bits of information from point A to point B and not really doing anything more.
In one of the projects we are currently working on, the top most service layer has a saveProduct() method on it to keep with our example. This method simply takes a collection of data and then using Validat, validates that collection of data against a set of rules to see if it represents a valid object. At no point have we created a business object to do this validation. If the data collection is valid, then the business object is populated and passed on to various functions within the application model for processing. If the data collection is invalid, then a collection of errors is returned to the controller and thus the controller simply has to check the result of the saveProduct() method call and based upon that result, redisplay the form and display a save confirmation message to the user.
So, to bring this back to the question at hand, even though we put it into Validat, I still see no reason why you would ever want to stuff potentially invalid data into a business object. Not only does this potentially not represent a valid business object, but it requires you to do away with some of the basic type and validation checking of arguments on your get/set methods in order to allow any data to be put into that business object. It just seems much cleaner to validate the user submitted data at the top most service layer (not the controller) and then if valid, create and populate the business object.