I also like the idea of just having an isValid() method type solution. I did a 1 day spike on our Well class to look at implementing our validation as separate business rule objects. This way, you can easily validate based on a given context, so you could have different rules be applicable during creation vs during an update (as an example).This comment made me think about the command pattern and its applicability to different problems. The basic idea of the command pattern is to convert a function into a full-blown class. You can read more about it here on wikipedia. I've used the command pattern in a number of projects in the past. Here are a couple of examples: On one of my projects, users were able to choose from a number of batch processes they wanted to run, either to load data or to do diagnostics on large recordsets all at once. In general there were several hundred thousand records processed by each such batch job. Another developer started off by writing code that implemented each process as a function in a large class. This was an oil and gas application, so he had functions like loadWells(), loadPools(), etc... all in one class. There was a lot of duplication from one function to another and the code was messy, so one of the first things I did was to refactor it into the command pattern. I turned each loading process into a class that implemented a single method, execute. For example, I had a WellLoader class, and a PoolLoader class that both extended a BatchProcess abstract base class which exposed an abstract execute method. The base class also exposed some protected methods that permitted, among other things, a progress indicator during batch processing (since each batch job generally took several hours). When users selected which batch processes they wanted to run, the system would create an instance of each job and add them all to a list, then successively called the execute method on each one. Whatever the details of implementation of each batch process, its only public interface consisted of the methods in the BatchProcess class, primarily the execute method. Another case where I used the command pattern was an embedded system in the scada world that did scheduled polling of sensors. In this case I took advantage of the command pattern to schedule and execute different kinds of polls and alarms. I set up each poll or alarm one as a different class. The scheduler class would loop through each process in its queue and if it was time to run that process, it would call its send method.
I was particulary inspired by this post:
In Domain Driven Design, Eric Evans shows how the command pattern can be used to create specification objects. Such objects can be chained together to validate constraints, create objects, or filter lists. I think the example Jeff presents above falls into this general category. It's an interesting idea, but I think some caution is warranted, because the goal of patterns is to simplify code and reduce duplication. If validation rules can re-used or need to be chained together and executed in different combinations at different times, then it makes sense to use the command pattern. However, if validation rules are always applicable to a given domain object and are not re-used between different classes, then maybe the less flashy approach of just making each validation a method in a Validator class is more readable and good enough.
On a quick final note, I recently read Jamie Mcilroy's post about JSF validation. It seems as though JSF binds the gui directly to a domain object and invokes validation separately for each form field. I don't know how much I like that. I think I'd rather JSF invoked validation on the whole domain object in one call and used keys to determine which form fields had errors. Anyway, given the way it seems to work, that might be a good opportunity to take advantage of Jeff's idea of making each validation a separate class. That way, each attribute validation can easily be invoked from JSF but still be indepedent from the JSF framework itself.