CFML Coding Conventions
7/3/2000
Variables
- Specify the scope for all
variables.
This
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.
Use
lower case for the scope, e.g., session.UserDirectory.
2.
Use mixed case for
variable names.
Mixed
case makes the variable names easier to read.
Always use mixed case for all variable definitions and references.
3.
Use descriptive
variable names not abbreviations.
If you
use descriptive variable names then the code will be much easier for others to
read and for you to remember how it works yourself.
Note
that queries and variables cannot have the same name in the same ColdFusion
template page.
4.
Match form field
names to the corresponding database field name.
This makes it easier for you and others to remember
what the field contains.
5.
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.
Two exceptions:
a. If
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.
b. If
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
<CFSET> tags.
To include a pound sign that
is not used as a field delimiter, use two consecutive pound signs (##).
6. Use
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.
Example:
<CFLOCK
SCOPE=”Application” TYPE=”Exclusive” TIMEOUT=30>
<CFSET Application.Foo = 1>
</CFLOCK>
<CFLOCK SCOPE=”Server” TYPE=”ReadOnly” TIMEOUT=30>
<CFOUTPUT>The name
of this server is #Server.Name#</CFOUTPUT>
</CFLOCK>
For best performance, you should lock every single instance
of an application, server, or session variable.
Indention – Indent your
code
- 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
tables …
<TABLE
Border=”0” Cellpadding=”0” Cellspacing=”0”>
<TR>
<TD>
Table data goes here and is not indented
</TD>
<TD>Short text here</TD>
<TD>
<TABLE>
<TR>
<TD>
Nested table data here
</TD>
</TR>
</TABLE>
</TD>
</TR>
</TABLE>
Indent code inside of CFIF, CFOUTPUT and CFLOOP. For example …
<CFIF
… >
<CFSET … >
<CFELSE>
<CFSET … >
</CFIF>
- Keep the line length below 80
characters.
This makes the code easier
to read. Use a return and an indent for
continuation lines.
- 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
opening bracket.
Example 1:
<cf_mycustomtag
AttributeOne=”ValueOne”
>
Example 2 (Alternate indention for one
attribute):
<cf_mycustomtag AttributeOne=”ValueOne”
>
Example 3:
<cf_mycustomtagtwo
lAttributeOne=”ValueOne”
bAttributeN=”ValueN”
>
This rule
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.
Example 1:
SELECT TO.ColumnOne, TT.ColumnTwo, TO.ColumnThree
FROM TableOne
TO, TableTwo TT
WHERE TO.TableOneID = TT.TableTwoID
AND TT.TableTwoID = 10
ORDER
BY TO.TableOneOrderKey
Example 2 (Alternate indention for SELECT):
SELECT
TO.ColumnOne,
TT.ColumnTwo,
TO.ColumnThree
FROM
TableOne TO,
TableTwo
TT
WHERE
TO.TableOneID = TT.TableTwoID
AND
TT.TableTwoID = 10
ORDER
BY
TO.TableOneOrderKey
Example
3:
INSERT
INTO
TableOne
(
ColumnOne,
ColumnTwo,
ColumnThree
)
VALUES
(
‘ValueOne’,
‘ValueTwo’,
‘ValueThree’
)
Example
4 (Alternate indention for INSERT):
INSERT
INTO TableOne
(
ColumnOne,ColumnTwo,ColumnThree
)
VALUES
(
‘ValueOne’, ‘ValueTwo’, ‘ValueThree’
)
Example
5
UPDATE TableOne
SET
ColumnOne = ‘ValueOne’,
ColumnTwo = ‘ValueTwo’
WHERE
TableOneID = 10
AND ColumnThree = ‘ValueThree’
Custom Tags
1.
Use Attribute Name
Prefixes.
Prepend
the appropriate prefix to all Custom Tag attribute names:
Type
|
Prefix
|
Example Name
|
Array
|
a
|
aMyArray
|
Boolean
|
b
|
bMyBoolean, bChecked,
bStable
|
Date, Time, Date/Time
|
d,t,dt
|
dMyDate, tMyTime,
dtMyDateTime
|
Double
|
db
|
dbMyDouble
|
Integer
|
i
|
iMyInteger
|
List
|
l
|
lMyList
|
Number
|
n
|
nMyNumber
|
Query
|
q
|
qMyQuery
|
String
|
s
|
sMystring
|
Structure
|
st
|
stMyStuct
|
WDDX Struct
|
wst
|
wstMyWDDXStruct
|
- Prepend an ‘r_’ to the front of
the return attribute name.
For
example, r_stProduct.
3.
Don’t arbitrarily
create or overwrite hard-coded variables in the CALLER scope.
Pass
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.
Comments
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.
General
1.
Use upper case for
all tag names and lower case for the attribute names.
Using
upper case for the tag names makes them stand out. For example:
<FONT
face=”Arial Black” size=”+2”>Title of the page</FONT>
Quote
all values within the tag.
- Use boolean expressions in CFIF
tags.
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.
EXAMPLES:
Instead of:
<CFIF MyVar IS NOT “”>
<CFIF MyVar IS “POST”>
<CFIF MyVar IS NOT 0>
|
Do this:
<CFIF Len(Trim(MyVar))>
<CFIF NOT Compare(MyVar,”POST”)>
<CFIF MyVar>
|
3.
CFOUTPUT is faster
than CFLOOP.
If you’re looping through a query,
it’s much faster to use CFOUTPUT then to use CFLOOP.
4.
Validate variables
before using them in the template.
If you
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.
<CFPARAM
name=”form.NumericFieldName” value=”0” type=”Numeric”>
5.
Write portable
code.
To
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!)
·
Never, ever
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.
·
Use the
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.
6.
Validate your
input.
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.
7.
Use the CFSWITCH
statement in place of CFIF…CFELSE to repeatedly check the same variable for
different values.
For Example:
<CFSWITCH
expression=”#intYrsService#”>
<CFCASE value=”1”>
<CFSET
Message = “One! One year of
service.”>
</CFCASE>
<CFCASE value =”2”>
<CFSET
Message = “Two! Two years of
service.”>
</CFCASE>
<CFCASE value =”3”>
<CFSET
Message = “Three! Three years of
service. Ah.”>
</CFCASE>
</CFSWITCH>
8.
Calling functions
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.
<CFSET
StructDel(jedi,”anakin”)>
9.
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
to implement.
10.
Include comments at
the beginning of each file.
Include
comments at the beginning of each template or Custom Tag that includes the
following information:
·
File name
·
Author’s name
·
Date written
·
Description of the template or Custom Tag
·
List of attributes (Custom Tags only):
·
Name
·
Description
·
Required/Optional
·
Error return codes (where applicable, Custom Tags
only):
·
Return code
·
Description
·
Thrown errors (where applicable):
·
Type
·
Error code
·
Description
·
History of changes made to the code with the date,
author and description of the change, from oldest to most recent.
11.
Include embedded
comments in the code.
Include
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.
12.
Avoid Whitespace.
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.
14.
Cache relatively
persistent data.
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
reads.
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:
<CFIF NOT
IsDebugMode()>
<CFCACHE
timeout=”#DateAdd(“h”,”-4”,Now())#”>
</CFIF>
15.
Pages with forms
should post to themselves.
The best way to handle
forms in terms of user interface and consistency is to have all forms post to
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
advantages:
·
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
Conventions
- Use lower case for all directories
and file names used in a URL.
2.
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.
3.
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:
/Program Files/Allaire/spectra/handlers/BookSeller/
The above convention
assumes that there is only one site, or a limited number of sites on the
machine.
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.
4.
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.