Avoid the Instant Gratification Trap. Trust your Instinct and Ask Questions.

2007 September 18
tags: ColdFusion · Learning
by Paul Marcotte
Ben Nadel's recent post, Code Assertively, really struck home for me today. In it, he discusses the use of non-assertive methods, like Evaluate() and IsDefined(). I definitely prefer to use StructKeyExists() over IsDefined() as a test for variable existence, but a large portion of my code for the scaffolds in my transfer based "generic admin" made liberal use of Evaluate(). I found it ironic that I could code "assertively" in one regard and be very dogmatic about it, but could also justify stooping to hacked solutions . At the time that I was implementing my Evaluate() hack, I had that uneasy feeling that there was a better way, but my desire to make it work urged me to forget best practices in favor of the instant gratification of being able to say "voila!". Looking back at the code for that series, there were three specific places where I could improve things. One, I knew how to fix. The other two I will have to thank Mark Mandel for hipping me to some things I had forgotten or wasn't even aware of...Fix number one. The generic getProperty() method on a TransferObject Decorator. Using Evaluate(): <cffunction name="getProperty" access="public" returntype="any" output="false">
<cfargument name="name" type="string" required="true">
<cfreturn Evaluate("get#arguments.name#()") />
</cffunction>
Using the TransferObject memento: <cffunction name="getProperty" access="public" returntype="any" output="false">
<cfargument name="name" type="string" required="true">
<cfset var memento = getMemento() />
<cfreturn memento[#arguments.name#] />
</cffunction>
Fix Number two for looping over the columns in a generic query named "variables.q". Using Evaluate(): <cfset variables.propertyIterator = variables.objectMetadata.getPropertyIterator() />
<cfloop condition="#variables.propertyIterator.hasNext()#">
<cfset variables.property = variables.propertyIterator.next()>
#Evaluate("variables.q.#variables.property.getName()#")#
</cfloop>
Using query array notation: <cfset variables.propertyIterator = variables.objectMetadata.getPropertyIterator() />
<cfloop condition="#variables.propertyIterator.hasNext()#">
<cfset variables.property = variables.propertyIterator.next()>
#variables.q[variables.property.getName()][variables.q.currentRow]#
</cfloop>
I haven't used array notation much, so even though I had used it in the past, it wasn't my first choice to get things rolling. Fix nmber three for creating a parent object by invoking the TransferObject getParentXXX() method dynamically. Using Evaluate(): <cfset variables.parentObj = Evaluate("variables.object.getParent#ListFirst(variables.parent.getName(),"_")#()") /> Using <cfinvoke/> <cfinvoke component="#variables.object#" method="getParent#ListFirst(variables.parent.getName(),"_")#" returnvariable="variables.parentObj"> This was a nice moment of enlightenment for me. I had no idea you code use <cfinvoke/> on an object instance. I always thought you had to use the class path to create a new instance, prior to invoking the method. So, needless to say, I'm a bit humbled by the fact that I still have a lot to learn, both as developer and with regard to the resisting the evil of instant gratification (a.k.a hacks).