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]

Reply via email to