Many ColdFusion developers use common coding practices that are not optimal and don't follow "best practices". The following article shows 10 different mistakes and coding problems that you may find in your applications that can be easily corrected.

Top Ten Mistakes in ColdFusion

10. Misusing IsDefined

When using a variable or form field on a page, it has to be defined or otherwise expected. One way to do this is to use the IsDefined() function. A common mistake is to use # signs or to leave the quotes off. The proper syntax is like this:

<cfif IsDefined("form.firstname")>
  <!--- Do this --->
</cfif>

Because you are asking if a particular variable is defined or not, you do not need to use pound signs (which would indicate a "replacement" of that variable). Leaving off the quotes also causes the ColdFusion server to replace the variable with its contents, causing an error.

9. Setting the applicationtimeout in the <cfapplication> tag.

Application settings for variables are frequently set the same as sessiontimeout settings (about 20-30 minutes) using the CreateTimeSpan function. This is incorrect -- an application variable is something that you expect to change only when an application restarts, so it is better to set the applicationtimeout between a week and a month.

<cfapplication
name="myapp"
sessionmanagement="yes"
applicationtimeout="#CreateTimeSpan(7,0,0,0)#"
sessiontimeout="#CreateTimeSpan(0,0,20,0)#"
>

Here, the timeout is set for one week (7 days), which will refresh the application variables every week.

8. Using SELECT * in a <cfquery> tag.

This is one of the worst things you can do for performance of your application. The performance hit is roughly equivalent to the percentage of fields that you don't need on your page. For example, if you only need 2 fields for your web page, but you are doing SELECT * and retrieving 10 fields, the statement will be about 80% slower than if you only selected the 2 fields in the statement:

SELECT * from mytable 100ms

SELECT fname, lname FROM mytable 20ms

I've seen pages where a user will write SELECT * FROM mytable and use only one field, where the database table has 20-30 fields in it. This is outrageous, in that the performance penalty is 95-97%. In a busy web application, this can be disastrous.

7. Allowing variables directly in the SQL statement in a <cfquery> tag.

When using <cfquery> with a filter, it is common to see something like this:

SELECT productname, productdescription, productprice
FROM Products
WHERE ProductID = #url.productid#

This opens your database up to hackers and also possible errors -- a url variable can be modified by a user easily. It is better to validate the variable beforehand with a <cfparam> or simply use a <cfqueryparam> in the query itself:

SELECT productname, productdescription, productprice
FROM Products
WHERE ProductID = <cfqueryparam value="#url.productid#" cfsqltype="cf_sql_integer" />

6. Using <cfquery> instead of <cfstoredproc> when using a database that supports stored procedures.

Many of the potential security threats to your application and your data can be eliminated simply by using the tools available to you. In SQL Server, you can turn off all permissions to tables from your web application and use stored procedures to access all data. Your tables become much more secure, and as an added bonus, the code will execute faster because stored procedures are compiled. Community MX has many articles showing how to use stored procedures, including Chaz Chumley's article, Using the CFSTOREDPROC Tag and Ray West's series on building strored procedures in SQL Server: Moving to Stored Procedures.

5. Not using ColdFusion components

ColdFusion components (CFCs) became available for use with ColdFusion MX (version 6) in 2002. CFCs make it easy to separate business logic from presentation logic in a ColdFusion application. CFCs are easy to use, and everyone should be using them. CFC instances can also be placed in Session or Application scope for speed and efficiency. See my article on Persistant Scoped CFCs for more information on the advantages of this. Community MX has many articles showing how to use ColdFusion components, such as Adrian Senior's series on building your first CFCs: Our First CFC.

4. Not using <cftry> and <cfcatch> and other error handling mechanisms

Errors happen, whether you expect them or not, no matter how bulletproof you make your ColdFusion application. Ultimately, you want all errors handled, but using <cftry> and <cfcatch> allows you to narrow your error handling to specific places, such as around each <cfquery> and <cfmail> tag.

<cftry>
<cfquery name="rs" datasource="#mydsn#">
SELECT productname, productdescription, productprice
FROM Products
WHERE ProductID = <cfqueryparam value="#url.productid#" cfsqltype="cf_sql_integer" />
</cfquery>
<cfcatch>
<p>Please try your page again</p><cfabort>
</cfcatch>
</cftry>

In this case, the query will error if a url variable other than an integer is used. The <cftry> tag catches the error and shows the user a message (you could do anything here, such as show an error page, continue execution, or display a default data set.)

An overall application error handler can also be implemented using a <cferror> tag in the application.cfm or the onError function if you are using the Application.cfc file instead of application.cfm.

3. Improper use of pound signs (#).

ColdFusion uses the pound sign to denote a variable "replacement" -- when ColdFusion encounters a pound sign, it expects to find another one, and expects that the text within the two pound signs is a variable that should be replaced at runtime. The following shows a frequent misuse of pound signs:

<cfoutput><p style="background-color: #fff">#form.firstname#</p></cfoutput>

The pound sign here on the background color needs to be escaped with a second pound sign, or you will have an error.

<cfoutput><p style="background-color: ##fff">#form.firstname#</p></cfoutput>

Consider the following:

<cfset temp = "#form.firstname#">

In this case, the pound signs are extraneous -- no replacement is necessary. You could have used:

<cfset temp = form.firstname>

The following is also a frequent mistake:

<cfmail to="form.emailaddress" from="form.emailfrom" subject="form.subject">
Hello
</cfmail>

Problem -- in this case, you need to have variables replaced by the contents of the variable, so the tag will not work. You need to use the following syntax:

<cfmail to="#form.emailaddress#" from="#form.emailfrom#" subject="#form.subject#">
Hello
</cfmail>

Note that the quote characters are optional in a case like this, but often desired for readability.

Also, when using a query of a date field in an Access database (which also uses pound signs as qualifiers), you need to escape the pound signs:

<cfquery name="rs" datasource="#mydsn#">
SELECT ProductName FROM Products WHERE dateadded > ##1/1/2006##
</cfquery>

or adding an additional pound sign when using a variable:

<cfquery name="rs" datasource="#mydsn#">
SELECT ProductName FROM Products WHERE dateadded > ###form.startdate###
</cfquery>

In this case, the first pound sign is the qualifier, the second pound sign escapes the Access qualifier, and the third is the ColdFusion variable qualifier.

2. Not using <cfhtmlhead> when adding <script>, <link>, or <style> tags.

When adding ColdFusion code that inserts <script>, <link>, or <style> tags into the page or in an include file, frequently the programmer will simply insert the tags:

<body>
<!--- more code --->
<cfif isdefined("form.csschange")>
<link href="styles/alternative.css" rel="stylesheet" type="text/css">
</cfif>

The <cfhtmlhead> tag will cause ColdFusion to parse the content and place the contents of the "text" attribute into the head of the document, where it belongs:

<body>
<!--- more code --->
<cfif isdefined("form.csschange")>
<cfhtmlhead text='
<link href="styles/alternative.css" rel="stylesheet" type="text/css">
'>
</cfif>

In this case, the <link> tag is parsed by ColdFusion and placed in the <head> where it should be. Note that by using single quotes, you can place your double quotes inside without escaping them.

Tip: Single and double quotes have no difference in ColdFusion, unlike some other languages like PHP. If you want to use double quotes within a string, use single quotes around it, and vice versa. You will not have to use escape characters if you follow this procedure.

1. Using loops within loops, without using the <cfoutput> group attribute.

ColdFusion has built-in grouping, for creating a "nested region". Frequently you will see something like this:

<cfquery name="rs" datasource="#mydsn#">
SELECT CategoryID, CategoryName
FROM Categories
</cfquery>
<cfloop query="rs">
<cfoutput><h2>#rs.CategoryName#</h2></cfoutput>
<cfquery name="rsProducts" datasource="#mydsn#">
SELECT ProductName, ProductPrice
FROM Products
WHERE CategoryID = #rs.CategoryID#
</cfquery>
<cfoutput query="rsProducts">
<p>#rsProducts.ProductName#: #rsProducts.ProductPrice#</p>
</cfoutput>
</cfloop>

In this case, the programmer grabbed a list of categories, created a loop of categories, then executed a query within the loop that grabbed the products for that particular category. If there are 10 categories, there will be 2 loops and 11 queries executed. This can all be done with 1 query (using a join) and one loop:

<cfquery name="rs" datasource="#mydsn#">
SELECT p.ProductName, p.ProductPrice, c.CategoryName
FROM Products p
INNER JOIN Categories c
ON p.CategoryID = c.CategoryID
ORDER BY p.CategoryID
</cfquery>
<cfoutput query="#rs#" group="CategoryID" >
<h2>#rs.CategoryName#</h2>
<cfoutput>
<p>#rs.ProductName#: #rs.ProductPrice#</p>
</cfoutput>
</cfoutput>

The trick is to order your query by the field that you want to become the "outer loop", and then wrap a second <cfoutput> around the "inner loop". The <cfoutput> within the loop will execute as a loop itself and loop over all the items in the query that share the same CategoryID (the field specified in the group attribute.)

Conclusion

There are many ways of doing things in ColdFusion, but sometimes there is a "right" way and a "wrong" way. This article has attempted to show some common mistakes, misconceptions, and incorrect coding decisions and ways to avoid them.