Nov 7 2007

Validat: Why it doesn't meet my needs

Posted by Joe Rinehart at 12:36 PM
7 comments
- Categories: ColdFusion MX

Validat is a new open-source framework from the Alagadians focused on simplifying data validation. At present, I'm not sure what advantages it provides me over my current architecture, and that's why I'm writing this post. It's not a flame. It started as an e-mail to Doug and Jeff, but turned into a post when I wanted to outline how I accomplish the same architectural goals as Validat without a framework.

Disclaimer: I told both Doug (Alagad owner) and Jeff Chastain (Validat author) both that I was writing this post. It's definitely a "cause thought" post for both ColdFusion developers and Validat's authors/owners. Validat's purpose is to provide a reusable set of validation components that can be arranged and configured to create reusable validation rules. It provides a series of simple validation classes ("validateDate") that all implement a validator interface. By arranging these validators into rules (using xml) and defining data sets (also using xml), you can request for a data structure (a ColdFusion structure) or a CFC to bean validated against the associated rules. When you ask Validat to validate something as a data set, it extracts your data to a ColdFusion structure then applies the validation for the associated data set to the structure.

Points where I'm stuck with Validat include:

1. Validation involving domain logic doesn't seem to be supported.

I worked with an event scheduler a while ago. My validation went a good ways beyond "Is event name filled out, simple, and 50 characters or less?" My domain model was rich, and part of its validation routines were questions into the domain model (e.g. event.hasConflicts() ), where an event knew how to check itself for conflicts with other events.

Because Validat extracts all of my data to raw ColdFusion structures, I'm not sure how I'd be able to build a validation rule that'd check this.

Basically, I need to create validation rules that can use business logic in my domain model, and I don't see any way to do it. Maybe I'm just missing something?

2. I don't see an advantage of Validat over a simplish factory setup that I already use.

I've long been an advocate of separating validation logic of domain objects in decent-sized applications to classes outside the objects. It's quite often that you'll have different sets of validation rules for different contexts. A Contact may only need a first name to save, but may need a valid e-mail address to be sent an e-mail message: that'd require two different validation rules.

Validat seems to be of the same opinion, but that's where our implementations start to differ.

Validat uses a combination of extensible simple validator CFCs (defined in code), validation rules (configured in XML) and data sets (configured in XML) to create what's basically a factory for validation rules.

I've accomplished the same architectural end for a while, using no framework. I'm not sure what I'm missing that Validat provides. Instead of a scheme that necessarily requires XML configuration, I use a series of CFCs that may or may not be externally configured (I use ColdSpring when needed).

Aside: Borrowing from Simon Horwith's playbook, this isn't a "framework" or anything easily releasable. It's just a set of CFCs that I copy then modify on a per-project basis.

Basically, I'll typically have a ValidationRuleFactory that has two methods:

createRule(thingToValidate:any, ruleName:String=null) invokeRule(thingToValidate:any, ruleName:String=null)

CreateRule just creates something implementing an interface (IValidationRule, for the sake of argument). If ruleName is defined, it'll explicit create a rule from an internal dictionary of ruleName:IValidationRule mappings (often passed into the factory's constructor via ColdSpring). If there's no rulename, I assert that I'm validating a component, and I'll look up a default validator for the component (by component metadata name) in a similar dictionary. Rules are cached, and therefore are stateless singletons.

InvokeRule just does createRule and calls IValidationRule.validate(thingToValidate:any, errorCollection:ErrorCollection):ErrorCollection. I normally use the validation error collection that's part of Model-Glue as the return type of validate().

I have a number of small IValidationRule implementations, similar to Validat's, such as DateRule. They normally require bits for their constructures, but I try to set defaults for all. DateRule needs things like isRequired, minDate, maxDate, etc.

If I want to validate a contact for persistence, I'll probably write a rule called ContactValidForPersistence, and I'll compose it of a bunch of other little rules: it'll probably have a firstNameRule that's an instance of StringRule checking for requiredness, length, etc.

As a summary of my approach:

I use composition of smaller IValidationRule instances to build big, domain-specific IValidationRule instances, which is functionality Validat seems to spread across its <validationRules> (small rules) and <dataSets> (domain-specific rules) configuration blocks.

Then, I use a ValidationRuleFactory that first allows me to map both components to default IValidationRule implementations and to create rules-on-demand by name.

It's simple and lets me build very complex rules that can be changed elegantly.

I do see one thing that Validat buys me that my bits have an issue with: Validat could validate both FORM contents and a CFC instance against the same dataSet definition because it extracts data to raw structures. My rules would be looking for either beans (getting data via Getter functions) or a struct. If I've got a struct and a bean whose data structure are so identical where I could use the same dataSet, though, why wouldn't I just validate either the bean or the structure?

Summary

I'm not sure what Validat buys me other than being able to validate a bean and a like-structure structure as the same data set, a situation in which I've never found myself. I also don't see how to perform validation that involves my domain model.

That's not to say I think the framework isn't without a use or potential: being able to abstract rules from their implementation could have great use, and it's something I can't get out of my validation rule factory / composed rule setup.

If there was a way to transform the rules defined in Validat's XML (not just the rules but the datasets) into Javascript validation or SQL constraints, letting me define all this validation in one place and generate it across all sorts of application tiers, I'd be very inclined to start using it!

Further, having a domain-specific language for defining validation (Validat's XML file) makes it handy for non-programmers to express their validation needs.

Update

Anyone want me to commit ValidationRuleFactory to RIAForge? I'd be happy to work with some others on fleshing out a good library of simple rules and some examples of building large rules.

Comments

Robb

Robb wrote on 11/07/07 3:08 PM

Please go ahead and commit ValidationRuleFactory to RIAForge, as I think it would very helpful for us MG'ers. I have noticed that the validation topic and how/where it fits into the various patterns has stirred some difference of opinion in other blog posts. It seems that your ValidationRuleFactory is in a utils/validation layer??
Brian Kotek

Brian Kotek wrote on 11/07/07 11:56 PM

I've been kicking around my own validation engine that would allow you to generate client side JavaScript validation in addition to handling server-side validation. In effect, you'd define the rules once and be able to perform client- and server-side validation from the same rule definitions. I'm not sure how Flex does validation, but I wonder if it could call the same validation engine on the server to get back the appropriate ActionScript code to validate forms within Flex. Something to consider?
Mark M

Mark M wrote on 11/08/07 8:43 AM

I've been doing that for a couple years now, but more procedurally through the use of custom tags that output form fields then generate either qform client side script or more recently jquery-based form validation. When I was looking at Validat, my first thought was &quot;now how could I generate some client side validation with this&quot;!
Brian Kotek

Brian Kotek wrote on 11/08/07 12:01 PM

Mark, what I'm saying is that the same validation engine could do both. For example, when you render the HTML page you could call user.getClientValidation() or something, and it would output the necessary JavaScript. But on the server, you could call user.validate() and the same validation rules that generated the JavaScript (plus any others that don't apply to the client side) would be run though a CF validator. I just have always hated having to keep my validation rules in two places (one for JS validation and one for CF validation).

Obviously the JS generation would be modular, so that the specific validation implementation would be separated out (I was using the Bridge pattern), so that you could swap out JS validation implementations without having to change the rest of the code. I would assume the same could be done for Flex if there is a way to &quot;pull in&quot; ActionScript generated on the server and execute it within the Flex app (I assume evaluate() but there is probably a more elegant way).

I approached it as a set of XML rules for the object that included generic rules (required, unique, etc.) but also allowed for custom rules. So you could write a custom validation function to do more complex things (including calling other domain objects or the service layer). This applies to both server- and client-side validation.

Anyway I know the idea is somewhat ambitious and may not even be feasible, but I thought it might be worth thinking about.
Mark M

Mark M wrote on 11/08/07 2:11 PM

Brian, I totally agree with you. That's what I would like to do, but haven't had time to sit down and work through a general solution to this problem. To this point it's been setting up both the client and server validation separately--what a pain! That's why I was interested in ways I could use the Validat &quot;framework&quot; to create the client-side validation in addition to the server using the same rules.

So now the question is--Joe is putting ValidationRuleFactory out there, Brian has something already (maybe he would like to share?), and others (like me) have re-invented the wheel over-and-over (Validation.cfc and validatorCFC projects on RIAForge) -- where do we go from here? Which one is the most extensible for the most needs? I can see a repository of validation routines for the (1 or 2?) most extensible frameworks that the community could submit. Thoughts? Maybe I'm thinking too large...
Ryan Wood

Ryan Wood wrote on 11/12/07 4:42 PM

Please do add ValidationRuleFactory to RIAForge. I'd love to work through it.
Ted

Ted wrote on 04/01/08 9:26 AM

very interesting ! has ValidationRuleFactory been committed to RIAForge? thanks

Write your comment



(it will not be displayed)