Although I haven't (yet) converted the system to CFCs we use a published assertion model for some of this (specifically for a system allowing trusted access across different applications).
In effect you defined a list of assertions for the component (or, in our case, the application). Ours contain: 1) The name of the variable. 2) Whether it's required or optional (and if the latter what the default value would be - which could be nothing). All variables will be defined after assertions are checked (this prevents the implementing app from going crazy with "IsDefined()" checks). 3) Any tests that the value must pass. As we wanted to make this cross-application accessible (CF, JavaScript, JSP, ASP, etc) we defined a simple set of our own. If you're just worried about CF you could even pass full functions in here. We store the assertions in a language specific data structure (a struct in CF) but publish them as a WDDX packet. An English example might be: ProfileID: Numeric| Required| Name: String| Required| Len < 50, Len > 1 Rank: String| Optional: "Newbie"| List: "Newbie, Novice, Expert, Guru" The variable names are keys in our struct and the assertions are parsed by a custom parser. In the above example if you passed a packet it would have to contain "ProfileID" (which needs to be numeric) and "Name" (which needs to be a string greater than 1 character and less than 50). "Rank" would be optional - if it doesn't exist the value "Newbie" is used. If it did exist it would have to be one of the listed values. These assertions are published, in our case to a specific URL. In your case you could just make them available upon request of a CFC method or WebService call. We also date the assertions so that we can cache them (when an application fetches assertions it saves them, when an error occurs it first checks to see if there are updated assertions before throwing the error). There's a lot of upfront work: in your case you might create an Assertion.CFC for CF that can parse and test the assertions (the number and kind of tests are up to you). You may also want to make a JavaScript object to do that same thing. This JS code would create the testing functions for your implementers to call. But once that's done you can reuse the same component for everything. You business components would have a "getAssertions()" method (which may be available as a webservice) that returned an XML packet of all the tests. Although in our case we're testing the whole packet you could choose to test only specific variables on demand. Since the component is defining and published its own assertions you can make changes to it later without breaking (well, if it's written right) client code. Also any client code that test the assertions can, from then on, be blissfully unaware: variables will be there and be of certain types/parameters without further checking. The end result is that you're both standardzing parameter checking, encapsulating it into a single place, and exposing it to any application that wants to implement it. It's been working really well for us... although we're still stuck on CF 4.5 at the office. I plan to implement it as a CFC in MX 6.1 just for the fun of it (and because I think it could be wicked useful) when I get the time. I'd be happy to share some of the documentation with you. I hope some of this made sense... although we've really come to appreciate the elegance of the system it's often hard to understand at first blush. Jim Davis > -----Original Message----- > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf > Of Jon Gunnip > Sent: Friday, November 28, 2003 5:03 PM > To: [EMAIL PROTECTED] > Subject: RE: [CFCDev] Exposing Validation rules for a component > > > Nando, > > My Validate() routine in my components looks very similar to what you > posted in your email. > > The issue is that I want to expose my validation *outside* of my component > so that the UI can do some simple validation by creating the approriate > size input text boxes and creating some simple JavaScript to do some > checking before a form can submit. > > Then, the UI can catch the simplest validation errors which it wouldn't > seem appropriate to have to go all the way to the component to throw a > validation error. For example, if a name can be at most 50 characters, I > want some easy way for my GUI to make sure the name input text box has an > attribute size="50". > > I then also run the Validate() routine inside of the component to ensure > that the data that was passed in is valid. There is some duplication > here, but the Validate() routine is much more thorough. > > My question is: What is the best way to expose the most basic validation > logic to my UI? It doesn't seem appropriate to have it locked away just > in the component. > > Jon > > >>> [EMAIL PROTECTED] 11/28/03 02:42PM >>> > Have you seen Sean Corfields validation examples in the article.cfc on his > site? It is a bit of work to set up for the first component but then it's > pretty fast to duplicate and modify to suit different objects. You might > save yourself some work in this example if you just ask for the birthdate > and calculate age. A few things i've read recently point out that it makes > much more sense to calculate age, as age changes over time. > > Also, IMO, i don't think you need to place these values in variables > (MaxNameLength) - just set them as var's in your validation method if you > don't need them available anywhere else. That will also help to reduce the > bloat. > > Modified from Sean's article.cfc example: > > cfset var maxNameLength = 50 > > <cfif NOT structKeyExists(variables.instance,"name") OR > Len(variables.instance.name) GT maxNameLength OR > Len(variables.instance.name) EQ 0> > <cfset valid = false /> > <cfset variables.invalidFields = > listAppend(variables.invalidFields,"name") /> > </cfif> > > You could do something similar for birthdate between Now() and 120 years > ago > and you'd be all set with only 2 if statements. But no need to set these > values in the variables scope unless they are really needed by other > functions in the component. That'll just create unnecessary clutter. > > I'm having fun with the validation routines i have working. It's cool how > clean it is once you have it set up. > > > -----Original Message----- > > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] > > Behalf Of Jon Gunnip > > Sent: Friday, November 28, 2003 9:05 PM > > To: [EMAIL PROTECTED] > > Subject: [CFCDev] Exposing Validation rules for a component > > > > > > > > Hello All, > > > > I am wondering how/whether I should expose data validation > > information for arguments passed into my components. > > > > Let us assume that I have a Person component that stores a name > > and age. At the top of the component I am defining: > > > > Variables.MinNameLength = 1; > > Variables.MaxNameLength = 50; > > Variables.MinAge = 0; > > Variables.MaxAge = 120; > > > > These variables are used in a Validate() routine inside the > > component to make sure the instance values passed to a > > Person.Create() or Person.Update() are in a valid range. > > > > I also have public functions in the Person component such as > > GetMinNameLength(), GetMaxNameLength(), GetMinAge(), GetMaxAge() > > that return the appropriate values. The idea is that the web > > pages that accept input for a call to Person.Create() or > > Person.Age() can easily call these GetMin(), GetMax() functions > > to create things like JavaScript validation or to set the size > > attribute of text input fields. Thus, bad input data can be > > caught before it is passed to the Person component. > > > > If the valid length of an allowable name changes, I then need to > > change the validation variables at the top of my component (and > > probably the size of a database field), but not the web forms > > that use the component. > > > > Does this seem like a good model? Is it too granular? > > > > It is definitely adding a lot of functions (and coding time) to > > my components! > > > > Thanks, > > Jon > > > > ---------------------------------------------------------- > > You are subscribed to cfcdev. To unsubscribe, send an email > > to [EMAIL PROTECTED] with the word 'unsubscribe cfcdev' > > in the message of the email. > > > > CFCDev is run by CFCZone (www.cfczone.org) and supported > > by Mindtool, Corporation (www.mindtool.com). > > > > An archive of the CFCDev list is available at > www.mail-archive.com/[EMAIL PROTECTED] > > > ---------------------------------------------------------- > You are subscribed to cfcdev. To unsubscribe, send an email > to [EMAIL PROTECTED] with the word 'unsubscribe cfcdev' > in the message of the email. > > CFCDev is run by CFCZone (www.cfczone.org) and supported > by Mindtool, Corporation (www.mindtool.com). > > An archive of the CFCDev list is available at www.mail- > archive.com/[EMAIL PROTECTED] > ---------------------------------------------------------- > You are subscribed to cfcdev. To unsubscribe, send an email > to [EMAIL PROTECTED] with the word 'unsubscribe cfcdev' > in the message of the email. > > CFCDev is run by CFCZone (www.cfczone.org) and supported > by Mindtool, Corporation (www.mindtool.com). > > An archive of the CFCDev list is available at www.mail- > archive.com/[EMAIL PROTECTED] ---------------------------------------------------------- You are subscribed to cfcdev. To unsubscribe, send an email to [EMAIL PROTECTED] with the word 'unsubscribe cfcdev' in the message of the email. CFCDev is run by CFCZone (www.cfczone.org) and supported by Mindtool, Corporation (www.mindtool.com). An archive of the CFCDev list is available at www.mail-archive.com/[EMAIL PROTECTED]
