ColdFusion ?Best Practices?

Before we delve into these so-called ?Best Practices??I need to issue a caveat. ?Best Practices? are a relative term, at best.

What I might consider a best practice, others might not. Some think that writing highly, highly optimized code is a best practice. However, this often results in code that is less readable. Some think that maintaining readable code is a best practice (makes it easier for you and whoever else may follow you to work with and debug).

So with that in mind?I should point out that these are *my* best practices. Others may disagree. That?s fine. The beauty of programming is there?s never just one way to get from point A to point B. Some prefer a direct route. Some prefer a scenic route.


A) Scope your variables

What is a scope? Well, ColdFusion has quite a few. There?s the form scope. The URL scope. Application, session, client, CGI, server, query, caller, cookie, and more.

Think of each scope as a dresser drawer (trust me on this). One hold the form variables?one holds URL variables?one holds form variables, and so on.

Now, let?s say you do: <cfoutput>#URL.firstName#</cfoutput>. ColdFusion knows exactly what to do. It goes to the URL drawer and pulls out the variable firstName.

Is the prefix URL. Mandatory? No. You can do <cfoutput>#firstName#</cfoutput>, and it?s just as legitimate. However, notice what happens. ColdFusion is standing in front of a dresser looking for a specific variable (firstName). It has no idea what drawer to look in. So it has to hunt through the drawers until it finds the appropriate variable.

Obviously, it?s going to take longer to find that variable without knowing which drawer to check. Do this a few hundred times in your Web application?with a few hundred users on your site?and you can see where that time difference can start to become significant.

Now that you know why you should scope your variables, learn a little bit more about the scopes themselves. This Macromedia Live Doc will teach you a great deal.


B) Use Boolean evaluation

Have you ever needed to check to see if a form field is empty? The most straightforward way is:

<cfif form.firstName IS ??>

It simply checks to see if the specified form field is an empty string (??).

Another way of writing the same thing would be:

<cfif len(form.firstName) EQ 0>

This checks to see if the length of the form field value is 0 (empty string).
This second method can be shortened a little bit?

<cfif len(form.firstName)>

Assume that form.firstName is empty. This would then become <cfif 0>. In boolean evaluation, 0 is false. Assuming the value was not empty (let?s say it?s ?charlie?), it would become <cfif 7>. A non-zero number evaluates to true.

<cfif form.firstName IS ??> <-- equals --> <cfif len(form.firstName)>

This is a classic example of where a ?best practice? becomes subjective. I personally prefer the Boolean evaluation (on the right), for it?s performance increase. Others prefer the method on the left, as it?s much more intuitive to read, which makes maintaining your code easier.

Either way is acceptable. It?s a matter of preference.

Another example of using Boolean evaluation can be demonstrated in trying to determine if a particular query returned any records. Traditionally, one would write:

<cfif queryName.recordCount EQ 0>

Using Boolean evaluation, we can write:

<cfif NOT queryName.recordCount>

<cfif queryName.recordCount EQ 0> <-- equals --> <cfif NOT queryName.recordCount>


C) Learning to debug


Okay?not necessarily a ?best practice??but a very necessary skill if you want to be a good programmer.

With the advent of CF 5.0, and continuing in MX, debugging became much easier with the introduction of the <cfdump> tag. Want to know exactly what your query returned? <cfdump var=?#myQueryName#?>. Want to know what?s in that array? <cfdump var=?#myArray#?>. Previously, to ?see? the contents of an array or structure, you?d have to loop (and for 2d arrays you?d have to do nested loops). <cfdump> changes all that. It?s an invaluable tool that I?ve seen too many people forget about.

If you are getting unexpected results after a form submission, do <cfdump var=?#form#?> on the form?s action page, and you?ll see everything that was passed in the form.

Another debugging technique would be turning debugging on in the ColdFusion Administrator (assuming you have access). This will output all relevant (and some irrelevant) variables and values at the bottom of the page. However, not everybody has access to do this. Since the introduction of <cfdump>, I?ve never had to resort to CF?s debug output option.


D) Using structure functions to your advantage

Just about all scopes in CFMX are stored in structures. If you are using session variables, they are stored in a structure (don?t believe me? Try this: <cfdump var=?#session#?>). When you submit a form, those form variables are stored in a structure on the action page. Again, a quick <cfdump var=?#form#?> will demonstrate this.

(if you?re not familiar with structures, peruse my 3 part tutorial on complex datatypes in ColdFusion, which teaches arrays and structures).

How to use this to your advantage?

Well, let?s say you have a form action page. You obviously don?t want people to load that page directly?you want to make sure that they came from your form, right? (right).

You could put the following code at the top of the page:

<cfif NOT isDefined(?form.firstName?)>
    <cflocation URL=
?myFormPage.cfm?>
</cfif>


This, of course, works just fine. But it would be a little bit quicker to check the form structure for a specific key:

<cfif NOT structKeyExists(form, ?firstName?)>
    <cflocation URL=?myFormPage.cfm?>
</cfif>


The isDefined() function must parse a string?which is relatively slow compared to other operations. The second method does not require CF to do any parsing?it simply checks a given structure (in this case, the form structure) for the existence of a specific key (in this case, ?firstName?).

The two are functionally identical. Once again, it?s your choice as to which one to use. While the second one is arguably faster (and how much faster is actually debatable), the first one is probably easier to read and understand it?s purpose.

E) Efficient use of <cfoutput> tags

Over the course of any given day, I generally help at least a handful of people with coding problems. And all too often, I see something like:

<cfloop from=?1? to=?100? index=?i?>
    <cfoutput>
       
this is iteration #i#<br />
    </cfoutput>
</cfloop>


This code won?t throw an error?so many people wouldn?t think there?s anything wrong with it. However, it is quite inefficient.

Think of a <cfoutput> tag as starting a car. Likewise, a </cfoutput> tag is similar to shutting a car off. This analogy holds true because with every instance of <cfoutput>, the CF Server leaps into action (red tights and all). With every </cfoutput>, it stops.

Now look at the code snippet above again. The ?car? is going to start and stop 100 times. Would you knowingly do that to your car?

A much better way of writing the same code is:

<cfoutput>
    <cfloop from=
?1? to=?100? index=?i?>
        this is iteration #i#<br />
    </cfloop>
</cfoutput>


Now the car is started once?the loop iterates as many times as necessary, and the car is shut off.


F) Those darn pound signs

Ben Forta (Mr. ColdFusion himself) wrote an article dealing with the overuse of pound signs. It?s that much of an issue.

Of course, the term ?issue? is relative. It?s not earth-shattering?but it deserves to be mentioned.

Pound signs are most often used to output a variable?s value. For example:

<cfoutput>#myName#</cfoutput>

However, in setting that variable, you need not use pound signs.

<cfset myName = ?Charlie?>

is not only perfectly valid?but generally more acceptable than:

<cfset #myName# = ?Charlie?>

Too many people think every CF variable in every set, condition, loop, etc needs to be enclosed in pound signs. The fact of the matter is that overuse of pound signs could conceivably slow up your application?as well as making your code less readable/manageable.

<cfif #myName# IS ?Charlie?>
    Hi, Charlie
<cfelseif #myName# IS ?Pablo?>
    Hi, Pablo
</cfif>

<cfif myName IS ?Charlie?>
    Hi, Charlie
<cfelseif myName IS ?Pablo?>
    Hi, Pablo
</cfif>

While both of these code blocks will function the same, the bottom one is arguably more readable. Especially if you think about a particularly long page of code. Reducing the pound sign usage can significantly ?clean up? the look of your code.

Ben Forta is feared by men and worshipped by women for a reason. I don?t think for a second that I can say it better than him, so I won?t even try. To hear it straight from the horse?s mouth, see Ben?s article at http://www.defusion.com/articles/index.cfm?ArticleID=26

Macromedia has also put out a page trying to clarify when to use pound signs and when to leave them alone (see Macromedia Live Doc)


G) Writing Better SQL

Two rules of thumb immediately come to mind in this area:

1) Avoid SELECT * when possible. If you know the columns that you need, specify them. It may take longer to type, but your queries will execute faster and your query objects will be smaller and easier to work with.

2) Use <cfqueryparam>. Not only will it significantly speed up your queries, it will also add an additional level of security to your database by preventing users from trying to force malicious queries. <shameless_plug>http://tutorial138.easycfm.com/</shameless_plug> <--
I should mention that use of <cfqueryparam> is NOT one of those subjective best practices. It should always, always, always be used. Always.


H) Write valid markup

This should probably be much higher on the list. But whether it?s CFML or HTML or XHTML or XML, write valid code (with the latter two, there?s really no other alternative).

HTML was, by its nature, very forgiving of bad code. However, the current version of HTML will be the last. There will be no HTML 5.0. XHTML will replace HTML as the base markup language of the Web.

In a nutshell, XHTML is nothing more than well-formed markup. What does this mean to you? It means no incorrect nesting of tags (eg <b><i>FOO</b></i>). It means all tags must be closed (including <li>, which needs a </li>, and <option>, which need an </option>).

A full explanation/tutorial on XHTML is WAY beyond the scope of this tutorial. However, getting into these good coding habits now will save you a world of heartache when XHTML becomes ?the- standard (it currently *is* an accepted W3C standard).

Valid markup also means a page that loads faster, and is more easily portable to other platforms (such as wireless).


That should be enough for now. Again, I stress that these are not ?official? best practices. They are endorsed by nobody but me. Obviously, I do prefer these coding methods. Do I suggest that you spend time ?cleaning up? all of the previous code you?ve written? No.

I do suggest that you get into good habits from here on in. That means writing valid markup. That means using cfqueryparam. That means not overusing pound signs. These are the more universally accepted of the concepts that I?ve presented. The others are your choice.

As I?ve said, the beautiful thing about programming is that there is no one right way to do any particular task (this can also be a very frustrating thing about programming). My point is that if you disagree with my opinions of what constitutes a ?best practice?, I?d like to hear about it. I?d like to know why. Your ?best practice? that contradicts mine could very well be a better way to do something, and I would welcome the opportunity to have another option available to me.

This tutorial is also not meant to be an all-inclusive reference to best coding practices. Certainly, there are many more techniques/subjects that I did not cover here. Error handling techniques, for example, come to mind.

Let?s open up the EasyCFM forums with some discussion about this. I?d like to not only hear about whether or not you agree or disagree with my programming ?styles??but I?d also like to hear yours. What do you do that you think makes your code better/faster?

We all stand to benefit through the sharing of ideas. I?d love to hear yours.

CJ
 

About This Tutorial
Author: Charlie Griefer (CJ)
Skill Level: Beginner 
 
 
 
Platforms Tested: CF5,CFMX
Total Views: 67,604
Submission Date: August 15, 2003
Last Update Date: June 05, 2009
All Tutorials By This Autor: 15
Discuss This Tutorial
  • I totally agree with mandatory usage of cfqueryparam...you don't want some malicious user dropping your table...not good when *poof* it disappears...talk about a catastrophe.

  • Well, sometimes you don't necessarily want to output everything. I mean was created to display something on the clientside.

  • Hi Stephen: Personally, I don't care for that method. I know people who do employ it...so once again, it's a very subjective matter as to whether it's "right" or "wrong" (or "good" or "bad" if you prefer). Honestly, I think for me it comes down to a matter of habit. To stick with the car analogy, it's like saying, "I'm going to keep the car running 24/7, so it's always ready when I need it." versus saying "I'm just going to start up the car on the occassions that I need to". But the fact of the matter is that "one big cfoutput" isn't really going to burn any extra gas or cause any extra wear-and-tear on the engine. So the short answer is that personally, I don't like it (since the question asked how I feel about it). But the objective answer is that even though I don't care for it, there's no real reason that I can think of as to why it would be 'bad'. Anybody else have thoughts on it? :)

  • I see your point about not stopping and starting Coldfusion with CFoutput in the wrong places, so how do you feel about just wrapping the entire page in one big CFOutput?

  • I'd like to add to your point "D", about using structure functions whenever possible. I would go farther than you and say this is more than a recommendation -- it's absolutely necessary. In the last paragraph of that section you said "The two are functionally identical" but as Sean Corfield (Director of Architecture in IT at Macromedia) points out on his blog (http://www.corfield.org/blog/past/2004_07.html#000510), that's not strictly true. To build upon your example, if a variable existed named #SESSION.form.firstName#, StructKeyExists(form,"firstName") would return false (as you might expect) but IsDefined("form.firstName") would return true because IsDefined() searches all scopes. It's a holdover from earlier times, when variable names were allowed to have dots. So, unless you're making use of the scope-searching aspect of IsDefined(), you're much better off to use StructKeyExists().

  • "Ben Forta is feared by men and worshipped by women for a reason. " Hahaha do they worship him cos of his looks or his skills ? A part from the funny's, not a bad tutorial www.mattbourke.com

Advertisement

Sponsored By...
Powered By...