Cutter's Crossing - General Coding Guidelineshttps://www.cutterscrossing.com/index.cfm
We talk about web development, often covering the three core pillars: HTML, CSS, and Javascript. There is a lot of legacy content here, discussing everything from ColdFusion to ExtJs, as well as more current stuff like modern EcmaScript, etc.en-usSun, 15 Sep 2019 15:43:52 -0000Thu, 08 Oct 2009 02:28:00 -0000BlogCFChttp://blogs.law.harvard.edu/tech/rssweb.admin@cutterscrossing.comweb.admin@cutterscrossing.comweb.admin@cutterscrossing.comnoScripting a ColdFusion Applicationhttps://www.cutterscrossing.com/index.cfm/2009/10/8/Scripting-a-ColdFusion-Application
With the release of <a href="http://www.adobe.com/products/coldfusion" target="_blank">ColdFusion 9</a> this past week, at MAX, we finally have full parity for cfscript with all of the cf tags. I personally prefer script when writing data access and business logic. For some it might not appear to be the sexiest feature, but I can see it making <a href="http://www.opencfml.org" target="_blank">CFML</a> much more appealing to developers from other languages.A terrific resource, for ColdFusion developers, has always been <a href="http://www.coldfusionjedi.com" target="_blank">Ray Camden's</a> <a href="http://www.coldfusionjedi.com/downloads/application.cfc.txt" target="_blank">Application.cfc Reference</a>. In giving back (and so Ray doesn't have to type it all this time), I thought I'd write an updated Application.cfc Reference, purely in cfscript. This is only the first draft, so if you find anything that should be corrected/added/removed, please let me know. I show you the code directly below, and include it in the download link at the bottom of this post. (BTW, there is code formatting in the file, it just didn't hold in the post for some reason)
<code>
/*
* ===================================================================
* COMPONENT/CLASS
* Application
*
* PURPOSE
* Defines certain ColdFusion application operating parameters, the
* Application.cfc is called on every single ColdFusion request, and
* specific methods automatically run, depending upon the order of
* events within the application lifecycle. This is an example of
* an Application.cfc written in pure cfscript. For a better under-
* standing of Application.cfc's properties and methods, please
* read the Adobe ColdFusion 9 documentation:
* http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-74fa.html
*
* AUTHOR
* Steve 'Cutter' Blades [C], webDOTadminATcutterscrossingDOTcom
*
* REVISIONS
* ===================================================================
* [C 10.07.09]
* Initial creation
* ===================================================================
* @output false
*/
component {
// http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec22c24-7d39.html#WSc3ff6d0ea77859461172e0811cbec22c24-68e0
this.name = "ComponentTest";
this.applicationTimeout = createTimespan(0,2,0,0);
// this.clientManagement = true|false;
// this.clientStorage = "cookie|registry|[dsn]";
this.customTagPaths = ExpandPath("/tags");
// this.googleMapKey = "[Google Map API key]";
this.dataSource = "cfbookclub"; // With this I don't need to include the attribute in my cfquery tags
// this.loginStorage = "cookie|session";
// this.mappings = {mapping1="loc1",mapping2="loc2"}; /* I haven't tried this syntax yet */
this.serverSideFormValidation = false; // this is 'true' by default, but I like to write my own
this.sessionManagement = true;
this.sessionTimeout = createTimespan(0,0,20,0);
this.setClientCookies = true;
this.setDomainCookies = true;
this.scriptProtect = true;
// this.secureJSON = true|false;
// this.secureJSONPrefix = "[some couple of characters to prefix all JSON]";
// this.welcomeFileList = "[comma delimited list of file names]";
// this.smtpServerSettings = {server="10.1.93.15",username="someUserName",password="somePassword"};
this.timeout = 3000; // This overrides the CF Admin's request timeout value, in milliseconds
// this.debuggingIPAddress = "[List of IP's requiring debugging access]";
// this.enableRobustException = true|false;
/**
* FUNCTION onApplicationStart
* Runs when an application is first initialized
* http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7d48.html
* @access public
* @returnType boolean
* @output false
*/
function onApplicationStart() {
return true;
}
/**
* FUNCTION onApplicationEnd
* Runs when the application times out, or when explicitly called
* http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7d47.html
* @access public
* @returnType void
* @output false
*/
function onApplicationEnd(required applicationScope) {
}
/**
* FUNCTION onMissingTemplate
* Runs when a (CF) template is called that does not exist
* http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7d2a.html
* @access public
* @returnType boolean
* @output false
*/
function onMissingTemplate(required string targetpage) {
include "404.cfm"; // not required
return true;
}
/**
* FUNCTION onRequestStart
* Runs at the beginning of a request, prior to the processing of
* http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7d41.html
* the requested template.
* @access public
* @returnType boolean
* @output false
*/
function onRequestStart(required string thePage) {
// The following is not required
param name="URL.reload" default="false";
if (URL.reload){
onSessionEnd(SESSION,APPLICATION);
onApplicationEnd(APPLICATION);
onApplicationStart();
onSessionStart();
}
// end
return true;
}
/**
* FUNCTION onCFCRequest
* New to CF9, this function runs only at the beginning of a CFC request
* http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSe821657cd7d6f83f6daaa733122cf6931bb-8000.html
* @access public
* @returnType void
* @output false
*/
function onCFCRequest(required string cfcname,required string method,required struct args) {
}
/**
* FUNCTION onRequest
* This runs after the onRequestStart, but still prior to the requested
* template itself. This method no longer applys to CFC requests
* (see onCFCRequest() for more information)
* http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7d43.html
* @access public
* @returnType void
* @output true
*/
function onRequest(required string thePage) {
include ARGUMENTS.thePage; // When using this method, you must include the requested page
}
/**
* FUNCTION onRequestEnd
* Runs after a requested template has completed it's process
* http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7d42.html
* @access public
* @returnType void
* @output false
*/
function onRequestEnd(required string thePage) {
}
/**
* FUNCTION onError
* This is an application wide error handler. Best practice would be to
* write process specific error handling, but this method will help
* you trap unexpected errors for custom notification and process
* http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7d4a.html
* @access public
* @returnType void
* @output true
*/
function onError(required exception,required string eventname) {
writeDump({var=ARGUMENTS.exception,label=ARGUMENTS.eventname}); // not required
}
/**
* FUNCTION onSessionStart
* Runs when a user first starts there visit to your application.
* The application will initialize if it's not currently active
* [through onApplicationStart()]. This method would also run
* prior to onRequestStart().
* http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7d4b.html
* @access public
* @returnType void
* @output false
*/
function onSessionStart() {
}
/**
* FUNCTION onSessionEnd
* Runs when a user's session times out, or when explicitly called
* http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7d40.html
* @access public
* @returnType void
* @output false
*/
function onSessionEnd(required struct sessionScope,required struct appScope) {
}
}
</code>
There you go! Enjoy! Stay tuned, as I have more ColdFusion 9 goodies on the way...
General Coding GuidelinesDevelopmentColdFusionThu, 08 Oct 2009 02:28:00 -0000https://www.cutterscrossing.com/index.cfm/2009/10/8/Scripting-a-ColdFusion-ApplicationRequest vs Variables - Which is right?https://www.cutterscrossing.com/index.cfm/2009/8/10/Request-vs-Variables--Which-is-right
Last week I stirred the pot a bit, stating that we've been improperly using the VARIABLES scope, and it's hurting our applications. Variables placed within the VARIABLES scope do not appear to have proper Garbage Collection performed on them when we're done with them, except in the case of the scope's usage within a CFC or a custom tag. This brought up some interesting discussion, where Ray Camden, Mike Brunt, and others chimed in.
I, with very good success, have been using REQUEST where most people use the VARIABLES scope. Wait! Hold on! You have to let me finish first before you get bent. What I said was that, in the past, we placed variables into the VARIABLES scope within our base request templates, with no way of clearing those variables at the end of the request (if using Application.cfc). My thought is, if VARIABLES have no true (apparent) mechanism for release, in context of variables scoped this way in a base request, then they don't really belong in the VARIABLES scope, but rather in the REQUEST scope.
This was met with some push back. The first argument was that this breaks encapsulation. I want to begin my response here by saying the first obvious thing that comes to mind: ColdFusion is not OO! Sure, your ColdFusion application can be written in an OO fashion, but ultimately it doesn't have to be. There are even some who seem that think that maybe it shouldn't be. All of that being said, I agree with OO principles, and think that proper encapsulation is very important when developing your applications, especially in terms of portability and reuse. Just because the REQUEST scope <em>can</em> be used directly within your custom tags or CFC's <strong>doesn't</strong> mean that you should. I would never suggest referencing the REQUEST scope directly within a CFC, with the exception of Application.cfc itself.
So another argument was that the REQUEST scope should only be used "when (and only when) the variable must be accessible to all the elements composing the request...", going further to state that the REQUEST scope should be avoided if at all possible. Why? The rest of the argument once again comes back to encapsulation. My point is to use the REQUEST scope within the context of a <em>request</em>, paying attention to maintain encapsulation. Within that context, doesn't it make <em>sense</em> to use the REQUEST scope for variables that should only exist for the length of a request?
The <a href="http://www.coldfusionjedi.com" target="_blank">ColdFusion Jedi</a> piped in to correct me on my timeline of scope introductions to ColdFusion, and we had some back and forth over declaration of scope to clearing of scope. I contended that onApplicationEnd() cleared the APPLICATION scope, that onSessiondEnd() cleared the SESSION scope, and that onRequestEnd() cleared the REQUEST scope. Ray reminded me that Application.cfc was about application process, and that the server handled when to 'clear' variables 'under the hood.' My point back was that <em>something</em> has to tell the server when to de-reference these variables, and that I had always assumed that was triggered by the execution of these methods. <a href="http://www.cfwhisperer.com/" target="_blank">Mike Brunt</a> chimed in on this, saying that the application must de-reference the variables prior to the server knowing it can perform Garbage Collection on them (Side Note: he didn't come out and agree with all of my conclusions here, only seeming to agree with the logic applied.)
Possibly the largest argument overall relates to whether the apparent memory leak, when using the VARIABLES scope within a base request, is really a leak or just a byproduct? I've theorized that the intention of the VARIABLES scope was that it was to be used <em>only</em> within CFC's and custom tags, where it does appear to properly get de-referenced. I put out there that the only reason you were able to use VARIABLES within the base request was because custom tags were created from .cfm files as well, so there really isn't any way to restrict it's usage. Ray says that the VARIABLES scope was introduced to provide access (like StructKeyExists()) to the unscoped variables out there in the wild.I think our thoughts of 'best practice' usage should follow these lines: Using the REQUEST scope within the base request, while maintaining encapsulation.
Ultimately, I just don't know. Maybe there's still an Adobe engineer out there who goes back that far, and can remember exactly what's what and why. I do know that, after migrating several high traffic applications to these guidelines I did get a higher return on application performance. I've gotten notes from others, after reading the original post, who have done similar changes to their systems with the same improvements. What other pluses or minuses do you, dear reader, think of when considering this practice of variable scoping? Is it right? Is it wrong? Is it a sin? What do you say?
(You can follow the original comment thread by referencing the post linked below)
General Coding GuidelinesColdFusion 8DevelopmentColdFusionMy 2 centsMon, 10 Aug 2009 19:06:00 -0000https://www.cutterscrossing.com/index.cfm/2009/8/10/Request-vs-Variables--Which-is-rightScope Usage and Application Scalinghttps://www.cutterscrossing.com/index.cfm/2009/8/6/Scope-Usage-and-Application-Scaling
Mike Brunt has posted an excellent article called <a href="http://www.cfwhisperer.com/post.cfm/good-practices-for-scaling-coldfusion-applications" target="_blank">Good Practices For Scaling ColdFusion Applications</a>, in which he speaks about the importance of memory management within ColdFusion applications, and calls out certain avenues of scope usage that every CF developer should pay attention too.
Great post Mike! Another 'scope' issue that I've often seen (and abused myself) is the misuse of the VARIABLES scope. Back in the early days of CF, every example you saw showed an unscoped variable, placing it into the VARIABLES scope by default. This was fine, back then, as your view layers primarily consisted of Custom Tags. Use of the VARIABLES scope, within a custom tag, was permissable as those variables were then only available within that tag (or within a nested tag, if the nested tag used the CALLER scope). Once execution of the tag was completed, the memory space of those variables was cleared.
But, since custom tags were made from .cfm templates, there is no constraint within CFML from placing VARIABLES scoped variables within <strong>any</strong> .cfm template. This, in itself, is bad, as the VARIABLES scope (in the case of a base template, not a custom tag) is not properly cleared from memory space.
What I find people doing (and I've done it myself) is using the VARIABLES scope in place of the REQUEST scope. Memory allocated to REQUEST variables is properly recovered at the end of a request. Although variables in the VARIABLES scope are no longer available (except within a persistent CFC), their memory isn't properly released at the end of request execution. (For more information on this, see Jason Sheedy's post on the <a href="http://www.jmpj.net/jason/index.cfm/2007/4/14/Cold-Fusion-Memory-Leak" target="_blank">ColdFusion Memory Leak</a>, and the accompanying comment thread and other referenced posts.)
A technique that some used, to get around this issue, was to have a <em>StructClear(VARIABLES)</em> statement as the last line of their onRequestEnd.cfm. This would explicitly clear out the VARIABLES scope at the end of a request. But, with the advent of Application.cfc, this no longer became an option (if you use Application.cfc.) If you tried to use that statement within the <em>onRequestEnd()</em> method of Application.cfc, you would only be clearing the VARIABLES scope of the CFC itself, and not the request.
That's actually a good pointer at the true underlying issue: proper scope usage. Use of the VARIABLES scope within a CFC makes variables within that scope <em>only</em> available directly by all methods of that CFC. Use of the VARIABLES scope within a custom tag makes variables within that scope <em>only</em> available within that tag (or a nested tag using the CALLER scope to access them.) Within a custom tag, you can not access variables of the calling template's VARIABLES scope, unless you use the CALLER scope to do so (which should only be in the case of a nested custom tag). You can, however, access REQUEST variables through out the request, from within a custom tag, an include file, or even within a CFC (though I wouldn't suggest doing that one.) By confining the usage of the VARIABLES scope to within custom tags and CFC's, and properly setting request level variables within the REQUEST scope, you could better manage your memory usage and application performance.
I've personally seen major differences in application performance, both through Mike's advice on persistent scope usage, as well as what I've outlined above. Unlike Jason Sheedy though, I'm not very familiar with Java profiling tools, so I'll have to leave it up to someone else to test all of this for the scientific proof. I only know that it appears my applications are running better as I migrate them to this paradigm. What are your thoughts?
*** Post Revision 080609: 2230 hrs ***
More revision to my comments than the post itself, but Ray, the ColdFusion Jedi himself, corrected me. According to Ray, the VARIABLES scope wasn't added until CFMX, so my supposition on the 'intention' of the VARIABLES scope was incorrect. You really have to read the comment thread to see the fun we're having;) Hopefully we'll find an answer. <em>Cutter</em>
General Coding GuidelinesColdFusion 8DevelopmentColdFusionMy 2 centsThu, 06 Aug 2009 17:29:00 -0000https://www.cutterscrossing.com/index.cfm/2009/8/6/Scope-Usage-and-Application-ScalingGuidelines: Code Readability - Pt1https://www.cutterscrossing.com/index.cfm/2008/2/20/Guidelines-Code-Readability--Pt1
<textblock label="CGLIntro">
In everything there must be balance, two sides to every coin. A debate goes on about code "structure". To indent? Or not indent? One argument persists that unnecessary spaces/tabs within code increase the bandwidth used by our systems, serving up 'empty' content. The other argument is that this cost is minimal, in comparison to the time savings with relation to maintaining 'readable' code.Our official position is that the maintainability of code is more important. At some juncture, in the future, we may implement other methods for reducing the 'space', possibly eliminating it during the Ant build process during deployment. For now it is more important to be able to quickly scan code, find items for clarification or change, and accomplish our mission.
Proper indentation of code does assist in the maintainability of the code, and should be applied regardless of the language being used (XHTML, ActionScript, JavaScript, SQL, ColdFusion, etc.) Indentation should be applied to logical blocks of code within a document. The following are a few different examples:
ColdFusion CFC:
<code>
<!---
*====================================================================================
* TEMPLATE/CLASS
* com.DM.testObj
*
* PURPOSE
* Just a test object
*
* AUTHOR
* Stephen G. 'Cutter' Blades, Jr. [SGB] sbladesATmycompanyDOTcom
*
* COPYRIGHT
* MyCompany (c) 2008, All Rights Reserved
*
* NOTES
*************************************************************************************
* SGB [02.20.2008]
* Initial file creation.
* Dependencies:
* com.DM.superObj
* Dependent Objects:
* com.DM.subObj
*====================================================================================
--->
<cfcomponent displayname="testObj" extends="superObj" output="false">
<!--- Some props --->
<cfset VARIABLES.instance = StructNew() />
<cffunction name="Init" output="false" returntype="testObj" access="public">
<cfargument name="objID" type="numeric" required="false" default="0" />
<cfargument name="objName" type="string" required="false" default="" />
<cfargument name="dtCreated" type="date" required="false" default="#Now()#" />
<cfset var iItem = 0 />
<cfloop collection="#ARGUMENTS#" item="iItem">
<cfset Set(iItem,ARGUMENTS[iItem]) />
</cfloop>
<cfreturn THIS />
</cffunction>
</cfcomponent>
</code>
Most documents, of any type, will have very similar, base level code stylization. The following example is for a standard ColdFusion template. Most nested elements/tags will further increase the indentation, though there will be exceptions.
ColdFusion CFM
<code>
<cfsetting enablecfoutputonly="true">
<!---
*====================================================================================
* TEMPLATE/CLASS
* wwwroot/public/time.cfm
*
* PURPOSE
* To demonstrate Coding Guidelines
*
* AUTHOR
* Stephen G. 'Cutter' Blades, Jr. [SGB] sbladesATmycompanyDOTcom
*
* COPYRIGHT
* MyCompany (c) 2008, All Rights Reserved
*
* NOTES
*************************************************************************************
* SGB [02.20.2008]
* Initial Creation
* Dependencies:
* com.DM.subObjGateway
*====================================================================================
--->
<!--- Processing code before output --->
<cfimport taglib="/custom/interface" prefix="ui" />
<cfscript>
// Set some variables
VARIABLES.soGW = CreateObject("component","com.DM.subObjGateway").Init(APPLICATION.DSN.myDS);
VARIABLES.qUsers = VARIABLES.soGW.GetAdminUsers();
VARIABLES.arrNames = ArrayNew(1);
/*
* Loop over the returned query, and create an array
* of names, concatenated from the returned FirstName
* and LastName
*/
for(VARIABLES.i = 0;VARIABLES.i LTE VARIABLES.qUsers.recordCount; VARIABLES.i = VARIABLES.i + 1){
if(Len(VARIABLES.qUsers.FirstName[VARIABLES.i])){
ArrayAppend(VARIABLES.arrNames, VARIABLES.qUsers.FirstName[VARIABLES.i] & " " & VARIABLES.qUsers.LastName[VARIABLES.i];
}
}
</cfscript>
<!--- The header and footer includes already wrap the output in cfoutput --->
<ui:incHeader>
<cfif ArrayLen(VARIABLES.arrNames)>
<cfoutput>
<cfsilent>
<!---
* Here we wrap a multi-line CF comment in a <cfsilent> tag
* to prevent the whitespace from being rendered into the
* rendered source. ColdFusion comments would typically
* show as whitespace, if included inside an output block,
* but the <cfsilent> tag will suppress that processing
* output. It is also good to use the tag around display logic
* blocks you may have nested within output.
--->
</cfsilent>
<div id="nameDescr">
This is a breakdown of the various names within our Administrative System - <strong>#APPLICATION.systemName#</strong>.
</div>
</cfoutput>
<cfloop from="1" to="#ArrayLen(VARIABLES.arrNames)#" index="VARIABLES.lpIndex">
<cfif VARIABLES.lpIndex eq 1><cfoutput><p></cfoutput></cfif>
<cfoutput>Name: #VARIABLES.arrNames[VARIABLES.lpIndex]#<br /></cfoutput>
<cfif VARIABLES.lpIndex eq ArrayLen(VARIABLES.arrNames)><cfoutput></p></cfoutput></cfif>
</cfloop>
<cfelse>
No names were returned by your request.
</cfif>
<ui:incFooter>
<cfsetting enablecfoutputonly="false" />
</code>
From the previous example, you see a number of examples simultaneously. We start with the standard comment header, come to some processing directives, then get into actual output. The entire document is wrapped within a &lt;cfsetting&gt; tagset. These tags, at the beginning and end of the document, are open (or self-closing) tags, the first stating that any document content after the tag should only be displayed if it is within an explicit output block (either &lt;cfoutput&gt; or a WriteOutput() statement). The second &lt;cfsetting&gt; tag opens the document for non-explicit output, in case this template is <em>included</em> inside another document. By usinging the <em>enablecfoutputonly</em> attribute, the server will reduce the amount of whitespace rendered in the XHTML passed to the browser. Another tool for this is the use of the &lt;cfsilent&gt; tags. Here they are wrapped around a multi-line ColdFusion comment, which would be processed as whitespace to the XHTML document (The above example is for example use only. The above comment would have typically been outside the &lt;cfoutput&gt; altogether). By using the &lt;cfsilent&gt; tags around this, we eliminate that whitespace generation. These tags are also handy if you require a processing block in the middle of your output, as it will hide the whitespace that processing block would produce.
The example above also shows that there are times when you should, and should not, indent. With ColdFusion, JavaScript, ActionScript, etc., simple conditional output (if this then "ok") will typically be inline, while more complex conditional output will be indented as normal. Any looping conditionals will be indented. There are examples above for both tag based, and simple scripted programming.
Our next post will be part II of this topic, where we will show more examples covering XHTML, script, and SQL examples.
General Coding GuidelinesColdFusion 8DevelopmentColdFusionWed, 20 Feb 2008 19:47:00 -0000https://www.cutterscrossing.com/index.cfm/2008/2/20/Guidelines-Code-Readability--Pt1Watch What You Write, Someone Is Readinghttps://www.cutterscrossing.com/index.cfm/2007/10/30/Watch-What-You-Write-Someone-Is-Reading
Today I received the following comment here, on an older post on <a href="/index.cfm/2007/1/13/Variables-and-Naming-Conventions" target="_blank">Variables and Naming Conventions</a>:
<blockquote>
...I wish Adobe would publish and adopt some kind of
official naming convention. Sometimes reading sample code written in
some other convention can make things harder to follow...
</blockquote>
It was almost funny that this comment had come in when it had. Recently I was doing a lot of research for a User Group presentation I just did on the new ColdFusion 8 Ajax Components (have to re-record it before public release). In the process, I spent a great deal of time going over documentation all over the internet, from <a href="http://www.adobe.com/support/documentation/en/coldfusion/" target="_blank">LiveDocs</a> to countless blogs, absorbing the wealth of information that is already out there. It was outstanding that there were so many resources out there for people to learn from. On the other hand, it was a little sad that so much of the sample code was written in ways that can really start new developers off with some bad habits.
I'm not perfect, by any means, but I try to pay careful attention to the code that I place on this blog for readers to use and learn from. One thing that I attempt to do is pay attention to basic Web Standards, like using XHTML (the current standard) instead of HTML, keeping styles in the stylesheet, and having unobtrusive JavaScript. I don't always do it, sometimes it doesn't make sense for a quick example, but I try, especially within code downloads. I also try to adhere to my own <a href="/index.cfm/General-Coding-Guidelines" target="_blank">Coding Guidelines</a>, so that code appears to be consistent and easy to read and understand.
Probably the one that bothers me the most, and that I see most prevalent in blogs, documentation, and books, is the lack of proper variable scoping. I know that, often, we're just publishing quick examples, but this can be an extremely detrimental practice. I have worked on some very large enterprise applications, with years of code written by half-a-dozen different developers, most of whom learned their ColdFusion (and development) skills through the docs or a book. Many had actually come up with some very creative and effective algorithms to fix some issue, or create some new whiz bang feature, but their code was so poorly scoped that, after time, it could take down the server. Why? How? Enterprise sites may contain several hundred (or thousand) templates, containing dozens of variables on each page, and can potentially be hit by hundreds (or thousands) of users simultaneously. Multiply the number of variables by the number of pages by the number of users, then imagine ColdFusion doing a ScopeCheck on each one, to figure out which scope each variable requested belongs in. Even if the variable <em>is</em> in the VARIABLES scope, it's still that many times ScopeCheck will be called while rendering a page.
Still not convinced? Go download <a href="http://varscoper.riaforge.org" target="_blank">varScoper</a>, and run it on your project root folder, including your subfolders, and see what it comes up with. Yeah, I'm still in shock. Cleanup on that is easier on a small subproject scale, but it's definitely forced me to <strong>think</strong> better when I'm writing my code, <em>paying attention</em> as I go, to minimize the performance impact of my applications, no matter how small it may be. I learned my bad habits from the docs, various books, sample code slung around on the <a href="http://www.houseoffusion.com/groups/cf-talk/" target="_blank">CF-Talk list.</a> I've continued to realize that there are better ways of doing things (like <a href="http://www.cfoop.org" target="_blank">OOP</a> and frameworks), and adjust my style and methods, and I think it's important to consider these 'best practices' when contributing. A little more code, but the right thing to do in the end, for you, your app, and your systems.
So, if you own a site of documentation, revise it. If you're writing a book, edit it. If you publish a CF blog, live it. The up-and-coming are reading us all of the time to find out how to use this wonderful language. Let's try to show 'em how to do it the <strong>right</strong> way. You might not follow any guidelines at all, within your development, but this scoping thing is way too important to gloss over, and will only help everyone in the long run.
General Coding GuidelinesDevelopmentColdFusionMy 2 centsThis BlogWho I AmTue, 30 Oct 2007 01:12:00 -0000https://www.cutterscrossing.com/index.cfm/2007/10/30/Watch-What-You-Write-Someone-Is-ReadingCall For Input: Document Revision Commentshttps://www.cutterscrossing.com/index.cfm/2007/6/22/Call-For-Input-Document-Revision-Comments
A little over a year ago we instituted a new policy within our dev team: placing a comment header at the top of every new (or revised) template. This comment header states what the template is, what it is used for, who originally created the file (if known) and a 'revision' listing. Every time a template is revised a notation was added to this header, with initials and date stamp, as to the purpose of the revision. This didn't replace line level comments to explain blocks of code, only augmented the process so that a total document change overview was available in an easy to review location.Recently we finally moved to a version control system, Subversion. This is a huge step for us, that is long overdue, and allows us to finally begin working as an enterprise level team. Very important with a 3,000+ template system. But, currently I am in a minor debate with our Development Manager, as well as a few members of our team. They believe that we should no longer use our revision comment system, since Subversion is setup to require a comment on commit. Their argument is that you can easily pull the 'history' of a document from Subversion.
But, like any good team, the issue is open for debate. No one has layed down new policy in stone yet. I asked if I could put the question out to the community-at-large, to get an idea of how others handle this situation and try to learn from the experiences of those who've traveled this road before. How do you handle this? How would you/should you handle this?
General Coding GuidelinesDevelopmentColdFusionFri, 22 Jun 2007 11:56:00 -0000https://www.cutterscrossing.com/index.cfm/2007/6/22/Call-For-Input-Document-Revision-CommentsVariables and Naming Conventionshttps://www.cutterscrossing.com/index.cfm/2007/1/13/Variables-and-Naming-Conventions
<textblock label="CGLIntro">
<p>Variables. They define the data within our applications. Hard to peg down within our system, with thousands of variables over thousands of files. For this reason, it is time to define proper variable declaration.</p>
<p>Variable naming conventions and scoping can be very different in different programming languages. Within ColdFusion variables are case insensitive, whereas in most others proper case is critical. With the wide mix of languages used here (XHTML, CSS, ActionScript, JavaScript, etc.) we will take the stance that all variables, across all platforms, should remain case specific unless explicitly necessary to change. A <a href="http://en.wikipedia.org/wiki/CamelCase" target="_blank">camel case</a> approach should be used, with the first letter of the first word (or one word) of a variable remaining lower case, while any subsequent word is capitalized. i.e.: oneVariable, anotherVariable, stillAnotherVariable. (Functions should capitalize each word) You may also employ <a href="http://en.wikipedia.org/wiki/Hungarian_notation" target="_blank">Hungarian Notation</a> to further identify the type of a variable, if you wish, but it won't (at this time) be required.</p>
<p>Another important action with variables is declaring, and referencing them, from their proper scope. In ColdFusion, you could reference most variables without identifying the <a href="http://livedocs.macromedia.com/coldfusion/6/Developing_ColdFusion_MX_Applications_with_CFML/Variables7.htm" target="_blank">scope</a>, but to do so would cause unnecessary load on our systems. When a template is processed by ColdFusion, if the <a href="http://livedocs.macromedia.com/coldfusion/6/Developing_ColdFusion_MX_Applications_with_CFML/Variables7.htm" target="_blank">scope</a> is not identified then the server will search through each <a href="http://livedocs.macromedia.com/coldfusion/6/Developing_ColdFusion_MX_Applications_with_CFML/Variables7.htm" target="_blank">scope</a> separately until the variable is found. Not only does this cause the system to overwork, but you also run the risk of the system discovering a variable of the same name within a higher <a href="http://livedocs.macromedia.com/coldfusion/6/Developing_ColdFusion_MX_Applications_with_CFML/Variables7.htm" target="_blank">scope</a> of the search tree. By expressly referencing all variables by their scope you eliminate these possible issues within our system. Also (within ColdFusion) all <a href="http://livedocs.macromedia.com/coldfusion/6/Developing_ColdFusion_MX_Applications_with_CFML/Variables7.htm" target="_blank">scope</a> names should be listed in all uppercase. i.e.: FORM.strUserName, SESSION.intUserID, URL.intStartRow.</p>
<h3>Flash</h3>
<p>Although they've been used in the past, <b>_global</b> and <b>_root</b> scopes should only be used cautiously. As we integrate more of our tools into each other, these scopes can easily cause problems. <a href="http://livedocs.macromedia.com/flash/mx2004/main_7_2/wwhelp/wwhimpl/common/html/wwhelp.htm?context=Flash_MX_2004&file=00000846.html">Local Variables</a> should be used in functions when possible.</p>
<p>Adobe has a detailed document on best practices on <a href="http://livedocs.macromedia.com/flash/mx2004/main_7_2/wwhelp/wwhimpl/common/html/wwhelp.htm?context=Flash_MX_2004&file=00000846.html">using scope</a> in ActionScript.</p>
<p>Use variable/instance names that describe the functionality of the the item being named. Append an underscore then the ActionScript abbreviation for the type or variable or instance when appropriate. This will make code hinting available in the Flash IDE. For example, <strong>next_btn</strong>, or <strong>submitForm_lv</strong></p>
<p>Use anonymous functions when appropriate, so as not to clutter the code with named trivial functions. Example:</p>
<code>
/*Not this way:*/
function nextButtonPress(){
timeline.nextFrame();
}
next_btn.onRelease = nextButtonPress;
/*Rather, this way:*/
next_btn.onRelease = function(){
timeline.nextFrame();
}
</code>
<h3>Database Architecture</h3>
<h4>Table Names</h4>
Table names should be camel case, but with the first letter capitalized as well. Table names should not be the pluralized form of what it stores. Example: <strong>ProductItemDetail</strong>
Linking or Lookup tables which serve as a relationship between a Many-to-Many should include the word <strong><em>Map</em></strong> in the name, preferrably at the end. Example: <strong>ProductItemCategoryMap</strong>
<h4>Column Data Types</h4>
<ul>
<li><strong>boolean</strong>: Boolean values are stored in bit columns, and have historically been named <strong>b<em>VerbWhatever</em></strong>, for example <strong>bIsCertified</strong>.</li>
<li><strong>foreign keys</strong>: Foreign key column names should be <strong>fk<em>TableName</em></strong>, for example <strong>fkProductItemDetail</strong>.</li>
<li><strong>hex color</strong>: Hexadecimal colors are stored in char(6) fields.</li>
<li>All fields that store numeric data should be of datatype INT(4) except for very special circumstances.
</li>
</ul>
<h3>SQL</h3>
<p>SQL keywords should appear in ALL CAPS. Tables should be aliased. For example:</p>
<code>
SELECT PID.displayName,
PID.description
FROM ProductItemDetail PID WITH (NOLOCK)
WHERE PID.ID = #arguments.itemDetailID#
</code>
<p>All Joins should be specified in the FROM clause.
For Example:</p>
<code>
SELECT PI.Make, PICM.Price
FROM ProductItem PI WITH(NOLOCK)
INNER JOIN ProductItemCategoryMap PICM WITH(NOLOCK) ON PI.fkItem= PICM.fkItem
</code>
<p>There are, always, exceptions to the rules. Typically these exceptions are due to the rules of another language. For instance, within <a href="http://www.stylusstudio.com/xmldev/200109/post70770.html" target="_blank">XHTML all tag names, attributes, and attribute values are always lower case</a>. The exception to that rule is anything calling a script function (like the event actions) where case is defined by the JavaScript itself (which is case sensative).</p>
<p>Examples:
<code>
<!--- ColdFusion variables --->
<cfset VARIABLES.strNextPage = "myNextPage.cfm" />
<cfparam name="URL.intRowStart" default="1" />
<cffunction name="GetNextPage" access="public" output="false" returntype="string">
<cfreturn VARIABLES.strNextPage />
</cffunction>
/*Flash variables*/
selectedElements = {};
propCount = function(obj){
var count = 0;
for (var i in obj){
count++;
}
return count;
}
delete_btn.onRelease = function(){
if (propCount(selectedElements) == 0){
this._parent.error_mc._visible = true;
} else {
this._parent.error_mc._visible = false;
deleteElements(selectedElements);
}
}
</code>
</p>
General Coding GuidelinesSat, 13 Jan 2007 18:25:00 -0000https://www.cutterscrossing.com/index.cfm/2007/1/13/Variables-and-Naming-ConventionsCommentshttps://www.cutterscrossing.com/index.cfm/2007/1/13/Comments
<textblock label="CGLIntro">
<p>First and foremost is documentation. We have an extremely large system, currently made up of nearly 7,000 ColdFusion, XML, Javascript, Cascading Style Sheet, ActionScript, and Flash templates. The original authors of these templates were spread fairly thin, working a variety of tasks while attempting to produce a usable product base to build our company upon. Because of this a large majority of our system is completely un-documented. Now, as a matter of standard practice, every template touched by a developer is given, at minimum, a document header comment to create some form of initial documentation.</p><code>
<cfsetting enablecfoutputonly="true">
<!---
===========================================================================
// CLASS/COMPONENT:
// wwwroot.Admin.myComponent
//
// DESCRIPTION:
// Here is a brief description of 'myComponent'
//
// AUTHOR:
// Steve 'Cutter' Blades (SGB), web.adminATcutterscrossingDOTcom
//
// COPYRIGHT:
// Copyright (c) 2007 CuttersCrossing, Inc. All Rights Reserved.
//
// REVISION HISTORY:
//
// *****************************************************************************
// User: SGB Date: 01.14.07
// Initial Creation
//
******************************************************************************
===========================================================================
--->
<!--- The rest of the code is included here --->
<cfsetting enablecfoutputonly="false">
</code>
<p>This is a very basic header comment. Opening and closing comment identifiers will be different for Javascript, ActionScript, Flash files, or Style Sheet documents, but the basic structure would be the same. First you have the path to the document being worked on. This is a dot notated reference to the path, in this case a ColdFusion Component (<em>myComponent.cfc</em>) locatated in <em>/wwwroot/Admin/</em>. Documents other than component classes would also include their document extension (i.e.: <em>wwwroot.Admin.myTemplate.cfm</em>). A brief description of what the template does is included next, followed by the name and email of the author of the template (only to be used on new documents), and the copyright notice. The final area is the revision history. This is the most important area within this documentation, as every change made to a template will be documented here, with the most current revision being the top item then going downward for each revision made to a template. Each revision will be listed with as much detail as possible, stating the initials of the developer making a change and the date that it was modified. Similar revision notes should also be made inline within the document at the location of any revisions, with the same data included (initials and date stamp). You should also note the <em>cfsetting</em> tags. These are utilized to minimize white space output in the generated page, and are only used within .cfm templates, but require the developer to pay close attention to the code contained between them, as display code will only be rendered if it exists within <em>cfoutput</em>tags (or within the <em>writeoutput()</em> statement of a <em>cfscript</em> block.</p>
<p>Inline revisions:
<code>
<!---
// SGB [11/27/2006]: Added a param in the event that the value is not included within the querystring
--->
<cfparam name="url.event" default="" />
</code></p>
<p>JavaScript example:
<code>
/*
// Function to validate a form
// Input: fields array of fields to be validated
// Output: boolean value for success or failure
*/
function validateForm(fldsObj){
success = 1;
// Validation processing would reset 'success' on failure
return success;
}
</code></p>
<p>Comments are handled differently with different languages:
<ul>
<li>ColdFusion (CFML) - &lt;!--- Comment ---&gt;</li>
<li>HTML/XHTML - &lt;!-- Comment --&gt;</li>
<li>Cascading Style Sheet - /* Comment */</li>
<li>ColdFusion (CFScript), JavaScript, Flash/ActionScript -
<ul>
<li>Multiline - /* Comment */</li>
<li>Single Line - // Comment</li>
</ul></li>
</ul></p>
General Coding GuidelinesSat, 13 Jan 2007 18:20:00 -0000https://www.cutterscrossing.com/index.cfm/2007/1/13/Comments