Greg's Blog

helping me remember what I figure out

A Few CFC Best Practices

| Comments

A rather innocent post about a CFC best practice doc caused a veritable deluge of e-mails and discussions on the CFCDev list yesterday. The discussion ranged from whether to set OUTPUT=”false” in your CFCs, to invoking CFCs and of course the ever returning discussion over the CFC variable scopes. Admittedly quite a bit of it went over my head but there were a few tidbits that sunk in, which I have attempted to summarise as follows.

The following two implementations of CFC invocation are thread safe. The first is known as the semaphore:

<cflock scope=”application” type=”readonly” timeout=”10”>
<cfset reload_app_vars = NOT structKeyExists(application, “app_vars_loaded”) />
</cflock>
<cfif reload_app_vars>
<cflock scope=”application” type=”exclusive” timeout=”10”>
<cfif NOT structKeyExists(application, “app_vars_loaded”)>
<cfset application.foo = createObject(“component”, “foo”) />
<cfset application.foo.init() />
<cfset application.app_vars_loaded = true />
</cfif>
</cflock>
</cfif>

As would this one, which is known as method chaining:

<cfif not structKeyExists(application,”foo”)>
<cflock name=”myApplication_foo” type=”exclusive”>
<cfif structKeyExists(application,”foo”)>
<cfset application.foo = createObject(“component”,”com.acme.foo”).init() />
</cfif>
</cflock>
</cfif>

Sean Corfield also gave this explanation as to why these would be the correct way of doing it:

“Why? Because the code checks for the *existence* of application.foo, not whether application.foo is initialized. By doing create-and-initialization in one expression, you avoid getting into the state where you have a created-but-not-initialized object.”

And for completeness here is an example that isn’t, just so you can see how not to do it:

<cfif not structKeyExists(application,”foo”)>
<cflock name=”myApplication_foo” type=”exclusive”>
<cfif structKeyExists(application,”foo”)>
<cfset application.foo = createObject(“component”,”com.acme.foo”) />
<cfset application.foo.init() />
</cfif>
</cflock>
</cfif>

The thread safety was an interesting part and lead to the proposition of [or started because of, I really can’t remember at this stage] another best practice, using the init() method as your constructor since CFCs don’t have them. A key thing I took from it was that whatever I set in my constructor method, in the end I should make it to this: <cfreturn this />.