RE: Help with CFC and recursion?

2003-05-27 Thread Shawn Grover
Thanks for the tips Sean, Raymond, et al

I had tried using the VAR bit before, but the code choked.  I didn't even
think of doing it in CFSET tags.  (And, I learned that a CFTRY tag is
interpreted as executable code.)  The function is working now.

As for my use of the CFPROPERTY tags, I know they are kinda useless in the
manner I'm using them, EXCEPT for documentation.  If you pull up the CFC in
a browser directly (i.e. http://myserver/mydir/mycfc.cfc), then you get a
very nicely formated page documenting everything there is to know about the
component.  If you don't use the CFPROPERTY tag, then the properties section
is empty.  We are intending to print these screens to document our classes,
so having the properties listed is an added bonus.  Also, some of our
components will likely become web services in the near future - we're still
getting the core code into place so we can proceed with the presentation
layer.

Thanks for the input on recursion, and some tips on CFProperty - on which I
have not been able to find any great details.

Shawn

-Original Message-
From: Sean A Corfield [mailto:[EMAIL PROTECTED]
Sent: Monday, May 26, 2003 8:07 PM
To: CF-Talk
Subject: Re: Help with CFC and recursion?


On Monday, May 26, 2003, at 17:41 US/Pacific, Shawn Grover wrote:
 I've tried a number of combinations for the code, and always seem to 
 get a
 similar result.

You need to use 'var' to declare your variables local - otherwise they 
are just instance variables and get overwritten by each recursive call.

 cfcomponent
   cfproperty name=Category type=caa.intranet.cfc.data.category

Why bother with this if it isn't a Web Service? cfproperty has no 
useful purpose except for type-checking Web Service returns.

   cfscript
   this.Category = createObject(component,
 caa.intranet.cfc.data.category);
   this.Category.Clear();
   this.List = this.Category.List();   
   /cfscript

   cffunction name=BuildTree access=public returntype=string 
   cfset qRoot = getChildren(0)

cfset var qRoot = getChildren(0)

   cfset sTree = 

cfset var sTree = 

   cfloop query=qRoot
   cfset sTree = sTree  AddNode(qRoot.Category_ID,
 qRoot.Category_Name)
   /cfloop
   
   cfreturn sTree
   /cffunction
   
   cffunction name=AddNode access=private returntype=string
 output=no
   cfargument name=CategoryID type=numeric required=Yes
   cfargument name=CategoryName type=string
 required=Yes

cfset var sChild = 
cfset var qChildren = 

   cfscript
   sChild = [#JSStringFormat(Arguments.CategoryName)#,
 'javascript:node_clicked(#Arguments.CategoryID#);', null;
   
   qChildren = getChildren(Arguments.CategoryID);
   for (x=1; x lte qChildren.RecordCount; x=x+1) {
   sChild = sChild 
 AddNode(qChildren.Category_ID[x], qChildren.Category_Name[x]);
   }
   
   sChild = sChild   ], ;
   
   /cfscript 
   
   cfreturn sChild
   /cffunction
   
   cffunction name=getChildren access=public returntype=query 
   cfargument name=ParentID type=numeric required=Yes

cfset var qTemp = this.List
cfset var qChildList = 0

   cfdump var=#Arguments#
   cfset qTemp = this.List

You can delete this line ^^^

   cfquery name=qChildList dbtype=query
   Select *
   From qTemp
   Where Parent_ID = #Arguments.ParentID#;
   /cfquery
   
   cfreturn qChildList
   /cffunction
 /cfcomponent


~|
Archives: http://www.houseoffusion.com/cf_lists/index.cfm?forumid=4
Subscription: 
http://www.houseoffusion.com/cf_lists/index.cfm?method=subscribeforumid=4
FAQ: http://www.thenetprofits.co.uk/coldfusion/faq

Signup for the Fusion Authority news alert and keep up with the latest news in 
ColdFusion and related topics. 
http://www.fusionauthority.com/signup.cfm

Unsubscribe: 
http://www.houseoffusion.com/cf_lists/unsubscribe.cfm?user=89.70.4



Re: Help with CFC and recursion?

2003-05-27 Thread Sean A Corfield
On Tuesday, May 27, 2003, at 13:14 US/Pacific, Shawn Grover wrote:
 As for my use of the CFPROPERTY tags, I know they are kinda useless in 
 the
 manner I'm using them, EXCEPT for documentation.

And of course it all depends on whether you want to use public data 
members - this scope - which you might want to document with 
cfproperty or non-public data members - unnamed scope - which you would 
not want to document with cfproperty (since the documentation is of the 
public interface).

Are other folks relying on cfproperty for auto-documenting public data 
members? How do you deal with keeping the cfproperty tags in sync with 
what you actually do with this scope variables?

Sean A Corfield -- http://www.corfield.org/blog/

If you're not annoying somebody, you're not really alive.
-- Margaret Atwood

~|
Archives: http://www.houseoffusion.com/cf_lists/index.cfm?forumid=4
Subscription: 
http://www.houseoffusion.com/cf_lists/index.cfm?method=subscribeforumid=4
FAQ: http://www.thenetprofits.co.uk/coldfusion/faq

This list and all House of Fusion resources hosted by CFHosting.com. The place for 
dependable ColdFusion Hosting.
http://www.cfhosting.com

Unsubscribe: 
http://www.houseoffusion.com/cf_lists/unsubscribe.cfm?user=89.70.4



RE: Help with CFC and recursion?

2003-05-27 Thread Shawn Grover
We're declaring a Clear function which initializes the THIS properties to a
valid, known state.  Our procedure is to ensure the clear function matches
the CFPROPERTY declarations, and we call the Clear function when the CFC is
initialized.

-Original Message-
From: Sean A Corfield [mailto:[EMAIL PROTECTED]
Sent: Tuesday, May 27, 2003 4:10 PM
To: CF-Talk
Subject: Re: Help with CFC and recursion?

snip/

Are other folks relying on cfproperty for auto-documenting public data 
members? How do you deal with keeping the cfproperty tags in sync with 
what you actually do with this scope variables?

Sean A Corfield -- http://www.corfield.org/blog/

If you're not annoying somebody, you're not really alive.
-- Margaret Atwood


~|
Archives: http://www.houseoffusion.com/cf_lists/index.cfm?forumid=4
Subscription: 
http://www.houseoffusion.com/cf_lists/index.cfm?method=subscribeforumid=4
FAQ: http://www.thenetprofits.co.uk/coldfusion/faq

Get the mailserver that powers this list at 
http://www.coolfusion.com

Unsubscribe: 
http://www.houseoffusion.com/cf_lists/unsubscribe.cfm?user=89.70.4



Re: Help with CFC and recursion?

2003-05-27 Thread Sean A Corfield
On Tuesday, May 27, 2003, at 16:20 US/Pacific, Shawn Grover wrote:
 We're declaring a Clear function which initializes the THIS properties 
 to a
 valid, known state.  Our procedure is to ensure the clear function 
 matches
 the CFPROPERTY declarations, and we call the Clear function when the 
 CFC is
 initialized.

And what's to stop some arbitrary method just setting this.foo to some 
value? (or, worse, some client code that instantiates a CFC and then 
sets the public data)

foo.cfc:
cfcomponent
cfproperty name=bar type=numeric/
cffunction name=clear
cfset this.bar = 0/
/cffunction
...
/cfcomponent

bogus.cfm:
cfset foo = createObject(component,foo)/
cfset foo.clear()/
cfset foo.bar = Hah! I'm a STRING now!/

Sean A Corfield -- http://www.corfield.org/blog/

If you're not annoying somebody, you're not really alive.
-- Margaret Atwood

~|
Archives: http://www.houseoffusion.com/cf_lists/index.cfm?forumid=4
Subscription: 
http://www.houseoffusion.com/cf_lists/index.cfm?method=subscribeforumid=4
FAQ: http://www.thenetprofits.co.uk/coldfusion/faq

Host with the leader in ColdFusion hosting. 
Voted #1 ColdFusion host by CF Developers. 
Offering shared and dedicated hosting options. 
www.cfxhosting.com/default.cfm?redirect=10481

Unsubscribe: 
http://www.houseoffusion.com/cf_lists/unsubscribe.cfm?user=89.70.4



RE: Help with CFC and recursion?

2003-05-27 Thread Shawn Grover
This falls under the black box concept, in that the component isn't
supposed to know about the environement is getting used in.  We don't care
if some arbitrary code changes the properties.  However, we do care about
having valid data before it is placed into the database.  So, our components
(data access components at least) have an isValid() function which is
public, and is also called internally when a save is done.

When I first started exploring components in detail (all of 3 weeks ago),
this was the first issue we ran into - you can't really type cast your
properties, then enforce that type casting (at least not when using a CFC as
a component - I understand this may be different when used as a web
service).  We were initially going to create get and set methods for member
variables (not in the THIS scope), but quickly realized this was
meaningless, because I was free to set variables on the object willy-nilly.
For example, a component might have two official properties - say x and
y.  I can freely create my own properties by assigning a value to them
(like javascript)...  :

cfscript
oPos = createObject(component, myposition);
oPos.x = 5;
oPos.y = 6;
oPos.z = 15;//This is not an officially supported property
oPos.MyOwnProperty = Hi ya Bob;  //another unofficial property
/cfscript

If you do a cfdump of the oPos object, it DOES reflect the two additional
properties, even though they were not defined in the CFC.  So, doing get's
and set's to enforce data type becomes meaningless - instead of saying
oObj.getProperty(); a user could do oObj.Property = 1;, and x =
oObj.Property;, bypassing the functions.  We decided it was easiest to
simply validate the properties before saves, and allow the calling code to
call the isValid method as well.

k, I've rambled on long enough...  hope this helps someone out there.

Shawn

-Original Message-
From: Sean A Corfield [mailto:[EMAIL PROTECTED]
Sent: Tuesday, May 27, 2003 5:30 PM
To: CF-Talk
Subject: Re: Help with CFC and recursion?


On Tuesday, May 27, 2003, at 16:20 US/Pacific, Shawn Grover wrote:
 We're declaring a Clear function which initializes the THIS properties 
 to a
 valid, known state.  Our procedure is to ensure the clear function 
 matches
 the CFPROPERTY declarations, and we call the Clear function when the 
 CFC is
 initialized.

And what's to stop some arbitrary method just setting this.foo to some 
value? (or, worse, some client code that instantiates a CFC and then 
sets the public data)

foo.cfc:
cfcomponent
cfproperty name=bar type=numeric/
cffunction name=clear
cfset this.bar = 0/
/cffunction
...
/cfcomponent

bogus.cfm:
cfset foo = createObject(component,foo)/
cfset foo.clear()/
cfset foo.bar = Hah! I'm a STRING now!/

Sean A Corfield -- http://www.corfield.org/blog/

If you're not annoying somebody, you're not really alive.
-- Margaret Atwood


~|
Archives: http://www.houseoffusion.com/cf_lists/index.cfm?forumid=4
Subscription: 
http://www.houseoffusion.com/cf_lists/index.cfm?method=subscribeforumid=4
FAQ: http://www.thenetprofits.co.uk/coldfusion/faq

Get the mailserver that powers this list at 
http://www.coolfusion.com

Unsubscribe: 
http://www.houseoffusion.com/cf_lists/unsubscribe.cfm?user=89.70.4



Re: Help with CFC and recursion?

2003-05-27 Thread Sean A Corfield
On Tuesday, May 27, 2003, at 17:30 US/Pacific, Shawn Grover wrote:
 We were initially going to create get and set methods for member
 variables (not in the THIS scope), but quickly realized this was
 meaningless, because I was free to set variables on the object 
 willy-nilly.

But the variables you set on the object are in this scope which you 
can ignore inside the CFC and only use the unnamed scope.

 cfscript
   oPos = createObject(component, myposition);
   oPos.x = 5;
   oPos.y = 6;
   oPos.z = 15;//This is not an officially supported property
   oPos.MyOwnProperty = Hi ya Bob;  //another unofficial property
 /cfscript

 If you do a cfdump of the oPos object, it DOES reflect the two 
 additional
 properties, even though they were not defined in the CFC.

Correct. But cfdump does not show any non-public data that the CFC has 
set itself, which is the key point.

 So, doing get's
 and set's to enforce data type becomes meaningless - instead of saying
 oObj.getProperty(); a user could do oObj.Property = 1;, and x =
 oObj.Property;, bypassing the functions.

Consider this:

foo.cfc:
cfcomponent
cffunction name=getFoo returntype=string
cfreturn foo/
cffunction
cffunction name=setFoo
cfargument name=newFoo type=string/
cfset foo = arguments.newFoo/
/cffunction
cfcomponent

rogue.cfc:
cfset foo = createObject(component,foo)/
cfset foo.setFoo(hello)/
cfoutput#foo.getFoo()#/cfoutput
cfset foo.foo = goodbye/
cfoutput#foo.getFoo()#/cfoutput

You will see that using the unnamed scope instead of this scope 
protects your data - the foo.foo = goodbye has no effect on 'foo' 
inside the CFC (because it sets 'this.foo' instead).

A common idiom folks seem to have adopted is actually this:

foo.cfc:
cfcomponent
cfset instance = structNew()/
cffunction name=getFoo returntype=string
cfreturn instance.foo/
cffunction
cffunction name=setFoo
cfargument name=foo type=string/
cfset instance.foo = arguments.foo/
/cffunction
cfcomponent

This creates a non-public (and therefore protected) instance variable 
(called 'instance') which acts like a scope for all your instance data 
- and also allows your setXxx() method to use the same name for its 
argument as for the instance variable itself (which is not possible 
using the unnamed scope).

In theory, you ought to be able to use variables scope instead of the 
instance 'scope' shown above but, right now, there's a bug in CFMX 
which makes variables scope break in CFCs (which will get fixed in 
due course).

Hope that helps explain how to use get/set to encapsulate your data and 
avoid 'malicious' code outside the object from messing with it.

Sean A Corfield -- http://www.corfield.org/blog/

If you're not annoying somebody, you're not really alive.
-- Margaret Atwood

~|
Archives: http://www.houseoffusion.com/cf_lists/index.cfm?forumid=4
Subscription: 
http://www.houseoffusion.com/cf_lists/index.cfm?method=subscribeforumid=4
FAQ: http://www.thenetprofits.co.uk/coldfusion/faq

Get the mailserver that powers this list at 
http://www.coolfusion.com

Unsubscribe: 
http://www.houseoffusion.com/cf_lists/unsubscribe.cfm?user=89.70.4