I've been working on a project a bit lately and found I've had the need to use some constants.
This has gotten me thinking how to implement them.
When work in Flex, I use the Extensions for Adobe Cairngorm and when creating your custom events involves you declaring constants in the event. The consts in the event are related to the Event type.
The idea behind constants is that this is information that *will never change*, hence the name "constants" :-)
In the CF application I've been working on, UUIDs are used, and there is no way you can call a UUID "human readable", so this can make code harder to understand when you see something like:
<cflocation url="/index.cfm?page=70688909-1676-D9C3-F2C5B9F163AEBDCF ">
If you want the person who reads this code later understand which page that is with out having to pull the application apart (and hair out too sometimes), you might to this:
<cfset uInfoPage = "70688909-1676-D9C3-F2C5B9F163AEBDCF">
<cflocation url="/index.cfm?page=#uInfoPage#">
That way the name of the variable will indicate *what* that UUID value indicates.
With me so far?
"But Dave, my application has more than one template and I don't want to have to do that every time I want to send a user to the info page, and what happens if the UUID of the info page changes?" you cry.
Well, why not have a single "thing" that stores all your constants that you can store in one place and use everywhere?
What I started doing here is I created a "Const.cfc" that had getter functions on them to return the constants.
EG:
<cfcomponent output="false">
<cffunction name="getInfoPageUUID">
<cfreturn "70688909-1676-D9C3-F2C5B9F163AEBDCF">
</cffunction>
</cfcomponent>
So the previous code can be done as:
<cflocation url="/index.cfm?page=#oConst.getInfoPageUUID()#">
(to be honest, I'd actually drop the "get" on the function name and just call it "InfoPageUUID", as it is a const and there is no "set", so why "get"?)(Another note: I'd usually declare/call the function in all CAPS too, as this is the "standard" way of naming constants)
The above relies on "oConst" being created, which could be stored in application scope for example.
What I didn't like about this is that the actual value is hidden from my old friend "cfdump", and if I have alot of constants I can't see their values in one hit.
This lead me to the "this" scope of my CFC(s).
Something like this:
<cfcomponent output="false">
<cffunction name="init">
<cfset this.INFOPAGEUUID = "70688909-1676-D9C3-F2C5B9F163AEBDCF">
<cfreturn this>
</cffunction>
</cfcomponent>
...which them means the example code can be written like this:
<cflocation url="/index.cfm?page=#oConst.INFOPAGEUUID#">
Before you cry "But people can change the values in the 'this' scope and break stuff!", I've always thought if people want to do that, it's up to them, but don't come running to me if it breaks!
(Also, CFCs are not secure at all anyway! see related entry)
The two things I like about using the "this" scope for constants are:
- 1: You can see all the values if you cfdump it
- 2: If you CFC has functions, you don't have lots of functions to work out that don't really do anything
Let me explain the second point a bit further.
Imagine I have a DB table that stores information of pages on my site.
My CFC has functions to work with this data.
In my application I have 1meeeeeeelllion UUIDs to do with various parts of the application, that are used in various ways, that would help the readability of my code if they are stored as constants.
This would render the "One Constant.cfc to rule them all" a bit hard to manage.
What I have been doing is storing the UUIDs to do with that part of the application in the CFC that deals with that part of the application.
EG:
<cfcomponent output="false">
<cffunction name="init">
<cfset this.INFOPAGEUUID = "70688909-1676-D9C3-F2C5B9F163AEBDCF">
<cfset this.HOMEPAGEUUID = "70826CD8-1676-D9C3-F256954C82CAF104">
<cfreturn this>
</cffunction>
<cffunction name="doSomething">
</cffunction>
<cffunction name="doSomethingElse>
</cffunction>
...lots more functions here...
</cfcomponent>
If you create that cfc and dump it as below:
<cfset oMyObject = createObject("component","someCFC").init()>
<cfdump var="#oMyObject#">
by default (CF8 I think...)
I would see all my constants at the top and all my functions would be collapsed.
Given the above code uses no frameworks and if any of you managed to read all my brain dump, what thoughts do you have on the above and/or how have you approached ColdFusion constants?
Disclaimer: all the above code is psedo code and hasn't actually been tested, but feel free to point out syntax errors etc. I may change it, I may not...