Posted in ColdFusion | Posted on 09-07-2010 | 2,064 views
Adobe evangelist Greg Wilson just asked me the following on IM and I thought it would be good to share with others. I also think it's something that folks may have strong opinions on so I'd like to see what kind of debate this can cause. Here is his question:
I've got a CFC method that returns a static structure. Basically it creates the struct on the fly and returns it. The data in the structure is all hard coded - no dynamic portion at all. Does it make sense to cache that data?
Ok, so first, let me demonstrate what he is talking about.
2
3 public struct function getCoolRankings() {
4 s = {};
5 s["low"] = "Raymond Camden";
6 s["medium"] = "Ben Forta";
7 s["high"] = "The Fonz";
8 return s;
9 }
10
11}
In this component I've got one method, getCoolRankings. It returns a structure of labels and the person who most exemplifies the value of that label. Every time you call getCoolRankings, the structure will be recreated and returned to the caller. So the question is, would you get much benefit from caching this? Obviously the answer is yes, you would. But the savings would be so minimal that I don't think it is worth really worrying about. That being said, I did mention to Greg that I like to do things a bit differently.
ColdFusion does not have a concept of a constant, a variable that once created cannot change. But even so, I like to think of such variables as Greg's structure as a constant. I'll then create them in the constructor area of the CFC like so.
2
3 variables.COOL_RANKINGS = { low="Raymond Camden", medium="Ben Forta", high="The Fonz" };
4
5 public struct function getCoolRankings() {
6 return variables.COOL_RANKINGS;
7 }
8
9}
As you can see, I've moved the structure into the constructor area of my CFC. I've also used an all caps name to help make it obvious that this is a special variable. Finally I modified my method to return the variable. This by itself won't cache the structure, but if the CFC itself is cached then the variable is only created once.
Finally, I also mentioned to Greg that another option would be to define the keys/data within ColdSpring. This separates the static data into your ColdSpring XML and may make for a "cleaner" separation of your CFC and the static data. I've done that a few times in the past myself.


But, like you said I'd actually have a SimpleConfig bean in ColdSpring that stores the static values and I'd inject that into my services since I use ColdSpring for everything...
application.coolRankings = {
low = "Raymond Camden",
medium = "Ben Forta",
high = "The Fonz" };
Then just refer to application.coolRankings whenever you need to look it up.
I'm sure you're aware of that - I just wanted to mention that is one drawback to keeping the constants outside of a component...
To be clear - I definitely DO hit the app scope from CFCs. This is especially true of CFCs I use to "respond" to Ajax stuff.
But still in any application I do have a number of fairly straightforward set of simple lookups, such as "coolRankings" that I do not want to store in database tables (no point) and so simple store them all as different structs in the application scope, with perhaps a function to access it.
I was just worried that I might be risking some sort of "race" condition or other weird error by accessing application directly from a component.
I would declare a property myself, but without the public 'setter' function. This makes it a little clearer that the value is constant.
;-)
That being said I would also declare the data in coldspring via properties and corresponding mutators. Also doing it this way "caches" the data in the App Scope so it's a 2x win.
Thanks all!
<cfset this.SOME_CONSTANT = 5734 />
<cfset this.SOME_OTHER_CONSTANT = 454 />
This is an attempt to mimic javas "public static final" style constants (except that they won't be static, or final!). With the example above, we may then have some code such as:
myObj = CreateObject('component', 'myObj').init();
someValue = myObj.someMethod( myObj.SOME_CONSTANT );
Dominic
In that case I'd do this:
public struct function getSomeConstant() {
return 5734;
}
public struct function getSomeOtherConstant() {
return 5734;
}
At least here you can be assured that the value wont change.
I think it's more that you have now made the values public and can be altered, rather than keeping them private and "semi-constant-like", even though you can access them similarly to Java. Perhaps a mix of the 2?
variables.CONSTANTS.SOME_CONSTANT = "myPrivateSomeConstant";
public string function SOME_CONSTANT() { return variables.CONSTANTS.SOME_CONSTANT }
Then in the calling page it would be slightly modified
someClassHas.SOME_CONSTANT()
someObj.SOME_VALUE
This less so:
someObj.getSomeValue()
I'm happy to allow the flaw.
component {
//...
metadata = getMetaData(this);
if( not structKeyExists(metadata,"COOL_RANKINGS") ) {
metadata.COOL_RANKINGS = ...;
}
//...
}
Note that you don't even need locking since you're not going to be modifying the value.
component {
// Constants
VARIABLES._COOL_RANKINGS = {
ultraLow = "Eric Belair",
low = "Raymond Camden",
high = "Ben Forta",
supreme = "The Fonz"
};
function getCoolnessList() {
return Request.UDFLib.Struct.StructValuesToList(VARIABLES.COOL_RANKINGS);
}
function getCoolRankingsQuery() {
return Request.UDFLib.Array.simpleArrayToQuery(StructValuesToArray(VARIABLES.COOL_RANKINGS));
}
function getUltraLowCoolness() {
return VARIABLES.COOL_RANKINGS.ultraLow;
}
function getLowCoolness() {
return VARIABLES.COOL_RANKINGS.low;
}
function getHighCoolness() {
return VARIABLES.COOL_RANKINGS.high;
}
function getSupremeCoolness() {
return VARIABLES.COOL_RANKINGS.supreme;
}
}
[Add Comment] [Subscribe to Comments]