CFML Coding Conventions
- Specify the scope for all
makes your code more readable and simplifies debugging since you know where
variables are coming from. If you don’t
specify the scope, ColdFusion resolves the name using the following order: CGI,
File, URL, Form, Cookie, and Client. By
explicitly defining the scope, you can skip this name resolution step and
further improve performance. Also note
that the session and application scopes are not in the name resolution list. These must be explicitly called.
lower case for the scope, e.g., session.UserDirectory.
Use mixed case for
case makes the variable names easier to read.
Always use mixed case for all variable definitions and references.
variable names not abbreviations.
use descriptive variable names then the code will be much easier for others to
read and for you to remember how it works yourself.
that queries and variables cannot have the same name in the same ColdFusion
Match form field
names to the corresponding database field name.
This makes it easier for you and others to remember
what the field contains.
Don’t use pound
signs if you don’t need them.
In general, the # signs are needed only when you
are referring to variable outside of a CFML tag, and in that case, the text
that contains the variable will need to be inside a CFOUTPUT tag.
a variable is used inside double quotes.
(Such as when you’re specifying an attribute for a CFML tag.) The quotes indicate that the name is
literal, and you’ll need the pound signs to resolve any variables.
you're dynamically naming variables, you’ll need to put the variable name in
double quotes and use pound signs around the dynamic part of the name.
Otherwise, pound signs should never be used in <CFIF> or
To include a pound sign that
is not used as a field delimiter, use two consecutive pound signs (##).
CFLOCK around shared memory variables.
Application, Server, and
Session variables are special variables and need to be handled differently then
other variables. Because they can be accessed by multiple requests at the same
time, every read or write of a variable of this type should be wrapped by the
CFLOCK tag. Under ColdFusion 4.5, the SCOPE attribute should be used.
SCOPE=”Application” TYPE=”Exclusive” TIMEOUT=30>
<CFSET Application.Foo = 1>
<CFLOCK SCOPE=”Server” TYPE=”ReadOnly” TIMEOUT=30>
of this server is #Server.Name#</CFOUTPUT>
For best performance, you should lock every single instance
of an application, server, or session variable.
Indention – Indent your
- Use white space and indent your
code to set off logical code chunks.
This is particularly useful to show the
organization of nested tags that contain many attributes or additional
tags. For example, when creating HTML
Border=”0” Cellpadding=”0” Cellspacing=”0”>
Table data goes here and is not indented
<TD>Short text here</TD>
Nested table data here
Indent code inside of CFIF, CFOUTPUT and CFLOOP. For example …
<CFSET … >
<CFSET … >
- Keep the line length below 80
This makes the code easier
to read. Use a return and an indent for
- Place each attribute to a custom
tag on its own line.
When more than one attribute
is passed to a custom tag, place each attribute on its own line and
indented. If only one attribute is
being used, it may be typed on the same line as the tag call, but may also be
indented on its own line. Place the tag
closing bracket (greater than sign) on a line by itself, same indention as
Example 2 (Alternate indention for one
is NOT consistent with HTML tag indention rules, but due to the possible
complexity of custom tag calls, experience has demonstrated that readability of
templates increases when this method is employed.
- Indent SQL in CFQUERY tags.
Use consistent indention in the SQL in
CFQUERY tags to make them more readable.
SELECT TO.ColumnOne, TT.ColumnTwo, TO.ColumnThree
TO, TableTwo TT
WHERE TO.TableOneID = TT.TableTwoID
AND TT.TableTwoID = 10
Example 2 (Alternate indention for SELECT):
TO.TableOneID = TT.TableTwoID
TT.TableTwoID = 10
4 (Alternate indention for INSERT):
‘ValueOne’, ‘ValueTwo’, ‘ValueThree’
ColumnOne = ‘ValueOne’,
ColumnTwo = ‘ValueTwo’
TableOneID = 10
AND ColumnThree = ‘ValueThree’
Use Attribute Name
the appropriate prefix to all Custom Tag attribute names:
Date, Time, Date/Time
- Prepend an ‘r_’ to the front of
the return attribute name.
create or overwrite hard-coded variables in the CALLER scope.
the name of the return variable into the custom tag. The custom tag can then modify the contents of the return
variable. If you have multiple return
values, return them in a structure, e.g., r_stProduct.
- Include comments at the top of the
Custom Tag file.
are described below, in the General section.
Use the naming conventions described above for the attributes to the
Custom Tag. Prepend an ‘r_’ to the
front of the return attribute name, e.g., r_stProduct.
Use upper case for
all tag names and lower case for the attribute names.
upper case for the tag names makes them stand out. For example:
face=”Arial Black” size=”+2”>Title of the page</FONT>
all values within the tag.
- Use boolean expressions in CFIF
CFIF tags will evaluate 50% faster if they are
expressed in terms of the boolean values returned by built-in ColdFusion
functions instead of the more-obvious string comparisons.
<CFIF MyVar IS NOT “”>
<CFIF MyVar IS “POST”>
<CFIF MyVar IS NOT 0>
<CFIF NOT Compare(MyVar,”POST”)>
CFOUTPUT is faster
If you’re looping through a query,
it’s much faster to use CFOUTPUT then to use CFLOOP.
before using them in the template.
are accepting URL, Form, or Cookie variables from the client, make sure you
verify that they’re in the proper format before using them in your
template. Not only does this vastly
improve error-handling, but there are also security considerations to blindly
dumping strings into a database.
name=”form.NumericFieldName” value=”0” type=”Numeric”>
ensure that your applications can be ported over other ColdFusion platforms or
onto client servers, use these conventions:
Lower case all
filenames and references to these filenames that are used in URLs.
For pre and
post execution files, name them “Application.cfm” and “OnRequestEnd.cfm” (Unix is case-sensitive!)
hardcode pathnames. Use CFML path
functions -- such as ExpandPath() -- to get an absolute path that is relative
to the template’s location. If you
absolutely must hardcode a path, define this as an Application-scoped variable
in the Application.cfm file.
URLEncodedFormat function if you are passing dynamic parameters that may
contain spaces. This prevents the
server from getting an error or truncating the URL at the first space.
Make sure that you’re
validating your data from form or url inputs before putting it in the
database. Things to look out for are
data types, minimum and maximum lengths, and date formats.
Use the CFSWITCH
statement in place of CFIF…CFELSE to repeatedly check the same variable for
Message = “One! One year of
<CFCASE value =”2”>
Message = “Two! Two years of
<CFCASE value =”3”>
Message = “Three! Three years of
that directly manipulate variables.
Some functions in CF will
directly manipulate variables and then return a boolean value. If you don’t need the return value of these
functions, you don’t need to initalize a dummy variable. Similarly, if you’re performing multiple
queries SQL inserts or updates, you don’t need to dynamically name the queries.
Put frequently used
code into custom tags.
Although it’s much easier
to copy and paste your code where you need it, you’ll save time in the long run
(and save another developers sanity) by encapsulating this code into a custom
tag and calling it where need be. The
concept here is similar to that for writing COM objects, but it’s much simpler
Include comments at
the beginning of each file.
comments at the beginning of each template or Custom Tag that includes the
Description of the template or Custom Tag
List of attributes (Custom Tags only):
Error return codes (where applicable, Custom Tags
Thrown errors (where applicable):
History of changes made to the code with the date,
author and description of the change, from oldest to most recent.
comments in the code.
CFML comments (<!--- --->) before each block of code or before code that
needs to be explained. Basically if
when you return to the code after a couple of weeks absence and you have to
figure out what is does, put in comments.
Use CFSETTING with the
ENABLECFOUTPUTONLY attribute to cut whitespace out of the page ColdFusion
returns to the browser.
13. Perform Error Checking.
Use the CFTRY and CFCATCH tags for
operations that are somewhat likely to fail, such as around expensive queries,
when connecting to flaky COM objects, etc.
This will allow you to customize errors or specify work-arounds for
these specific problems. For general
error-catching purposes, use the CFERROR tag in the Application.cfm file to
specify a general error template that can replace ColdFusion errors.
Caching has been available
in ColdFusion since the advent of Application and Session collections. For example, if you’re reading data out of a
file in your application, you can set the contents of this file read to an
Application or Session variable to save the webserver from time-costly CFFILE
However, with the release
of CF 4.0, Allaire has made caching much easier by integrating query-level and
page-level caching into their language.
Recordsets can be cached
using the CACHEDWITHIN attribute of the CFQUERY tag. This is helpful with queries that seldom change, for example
lists of states and state abbreviations.
Caching these queries saves trips to the database, which the amount of
time your application spends talking to an external component.
If the dynamic
content on your page changes infrequently, you can cache the entire page using
the CFCACHE tag. Note, however, that
pages are cached across the entire application; you can’t use page-level
caching if the page contains data that is user-sensitive. Also note that if you’re debugging an
application, you’ll need to remove page-level caching and then remember to add
it before you redeploy. Save yourself
some time by wrapping your CFCACHE tag with conditions:
Pages with forms
should post to themselves.
The best way to handle
the same page they originate on. Then
at the top of that page, have some code to check if the current page is being loaded
as the result of a form submission and
if so, do any error checking and database processing, then CFLOCATION or
CFINCLUDE to the next page in the sequence.
This method has several
If you post to the next page in the sequence and do
your database processing there, and the user hits reload on that page, the form
is resubmitted, and the database processing happens again.
Using this method, you can pre-fill the form fields
with #form.Fieldname#. This means that
the first time the page is loaded, the fields will be empty, but if there's a
validation error, you can just display the error message along with the same
form over again, with all the values the user entered already there. Then, the user has only to change what they
previously entered and submit the form again to correct their error.
It just makes more sense. You have a form and the code that processes that form on the same
page. From a maintenance perspective,
this is much easier to deal with.
Directory / File Naming
- Use lower case for all directories
and file names used in a URL.
Use mixed case for
all Custom Tags, Handlers, etc, file names.
Mixed case file names are
easier to read than all lower case. All
of the mixed case file names must be defined and referenced with mixed case.
Create a separate
directory for Custom Tags, Handlers, PLPs, etc under the site root directory.
Create a separate directory
under the site root directory for Custom Tags, Handlers, PLPs, etc. This collects all of the files for a site in
one place. By default Spectra sets up directories
to store these files under /Program Files/Allaire/spectra/. For example, the default location of the
handlers files for the BookSeller project is:
The above convention
assumes that there is only one site, or a limited number of sites on the
Add the project Custom Tag
directory to the registry entry
HKEY_LOCAL_MACHINE/SOFTWARE/Allaire/ColdFusion/CurrentVersion/CustomTags/CFMLTagSearchPath. Separate the directories with a comma. The directories will be searched for the
Custom Tag in the order listed.
If you have a large number
of handlers or want to group the handlers by ContentObject Type, then create a
directory under the Handlers directory for each ContentObject Type. If the handlers are overrides for the
default Spectra handlers, e.g., create, edit, or display, place the override
handlers in separate directories which are named for the ContentObject
Type. This is needed since the file name
for the override handler is the same for all of the ContentObject Types.
Create a separate
directory for each major function of the site.
Create directories for the
major site functions under the site root.
This allows you to group the files into smaller groups, making them
easier to find and maintain. If the
site is very large or contains a logical hierarchy to the functions, create
subdirectories for the functions under these directories.