Skip to main content
Mihai Baboi
Known Participant
February 28, 2009
Answered

CFC best practices

  • February 28, 2009
  • 3 replies
  • 1410 views
Hello. Please help me out with a little issue I have. I've recently started working with CFC's and there is something that I want to get clear. I have seen two different ways to write CFC's (although I'm sure that there are many others). Let me get to the point. The first method uses an init() function that acts as a constructor.
The second way does not use the init() function. It just has the set and get methods and uses "This" to refer to them. I will attach both code snippets at the end. My question is. What is the best way (if there is any)? Are there advantages to one of the methods? if there is anything I left out that would make my question more clear please let me know. Thank you for your time.

This topic has been closed for replies.
Correct answer -__cfSearching__-
> You've got this <cfscript> block, but you stick the return
> statement outside it. Why not do this:

> variables.attributes.cityId = 0;
> return this;
> </cfscript>
> </cffunction>

My preference is to put return statements outside of cfscript blocks. To me it emphasizes the exit point of a function and I am less likely to overlook it. But technically either option is valid. So I think it is more of a stylistic preference. I am sure some might find the reverse more readable.

> Are there advantages to one of the methods?

One difference I see is that option #1 sets default values for each of the components properties (id, name, etcetera). Whereas option #2 does not. So an error might occur if you were to call one of the getX() functions too soon, because the properties are not defined yet inside the component.

<cfscript>
personDTO = createObject("component", "PersonDTO");
id = personDTO.getID();
</cfscript>

That said, I completely agree with Adam's comments about using the THIS scope. I rarely use it either.

3 replies

-__cfSearching__-Correct answer
Inspiring
February 28, 2009
> You've got this <cfscript> block, but you stick the return
> statement outside it. Why not do this:

> variables.attributes.cityId = 0;
> return this;
> </cfscript>
> </cffunction>

My preference is to put return statements outside of cfscript blocks. To me it emphasizes the exit point of a function and I am less likely to overlook it. But technically either option is valid. So I think it is more of a stylistic preference. I am sure some might find the reverse more readable.

> Are there advantages to one of the methods?

One difference I see is that option #1 sets default values for each of the components properties (id, name, etcetera). Whereas option #2 does not. So an error might occur if you were to call one of the getX() functions too soon, because the properties are not defined yet inside the component.

<cfscript>
personDTO = createObject("component", "PersonDTO");
id = personDTO.getID();
</cfscript>

That said, I completely agree with Adam's comments about using the THIS scope. I rarely use it either.

Mihai Baboi
Known Participant
March 1, 2009
Thank you for all your to the point answers. I come from php so "This.id" came more natural to me as it resembled very much "$this->id". I understand now that the variables scope is the way to go for what I'm trying to achieve here. As for the <cfreturn>, I didn't pay much attention to it. I guess, as -==cfSearching==- said, it's a matter of preference. Me, that's the way I found the code in the book that I'm using to learn and it suited me just fine.
Inspiring
March 1, 2009
quote:

Originally posted by: Mihai Baboi
Thank you for all your to the point answers. I come from php so "This.id" came more natural to me as it resembled very much "$this->id". I understand now that the variables scope is the way to go for what I'm trying to achieve here.

Maybe, maybe not. I'll have to try this myself on Monday when I get back to work.

<cfcomponent name="abc">
<cfset x = 2>
<cffunction name="xyx">
<cfreturn true>
</cffunction>
</cfcomponent>

calling template.
<cfset x = 1>
<cfinvoke component="abc" method = "xyz" returnvariable = "def">
<cfdump var="#x#>

If you see 2, you had better reconsider that variables scope.

I don't actually know. I've never tried it.
Inspiring
February 28, 2009
> Hello. Please help me out with a little issue I have. I've recently started
> working with CFC's and there is something that I want to get clear. I have seen
> two different ways to write CFC's (although I'm sure that there are many
> others). Let me get to the point. The first method uses an init() function that
> acts as a constructor.

Good question!


> <cffunction name="init">
> <cfscript>
> variables.attributes = structNew();

One thing you could do with your init() method is to have optional
arguments for each of your object properties here too. This allows the
calling code to init() the object and set some properties in one hit,
rather than having to init() then set().


> variables.attributes.cityId = 0;
> </cfscript>
> <cfreturn this>
> </cffunction>

Here's a question for you. I see a lot of people doing this, and I just
don't get it. You've got this <cfscript> block, but you stick the return
statement outside it. Why not do this:

variables.attributes.cityId = 0;
return this;
</cfscript>
</cffunction>

It's a very trivial thing, but it piques my interest.


> <cffunction access="public" name="getId" returntype="numeric">
> <cfreturn This.id>
> </cffunction>
> </cfcomponent>

I would say with properties exposed in the THIS scope, one would not
necessarily bother with getters. The whole point of THIS-scoped variables
is that they're accessible directly. Using your example code, one would
just do personDTO.id in the calling code.

That said, I would almost never store my object's properties in the THIS
scope, I'd keep them safely locked away in the VARIABLES scope.

--
Adam
Inspiring
February 28, 2009
I don't normally do that type of work so I don't write those types of cfc's. Looking at your example, I'd do neither.

I'd use the property scope for the name, id, etc instead of the this scope. The property scope is available to all the functions, but not to the calling template. I would also have a single init function that sets all the values. It would return true, not this.

But then again, it depends on what you intend to do with your object after you have created it.