ColdFusion MX Coding Guidelines - Style: Naming, Comments
& Layout
Release 3.0.2 (10/17/2003)
« Contents | Structure:
Application, Component, Tag etc »
Style: Naming, Comments & Layout
This section provides guidelines on naming conventions (for files, tags, variables
etc), comments and source code layout.
Naming
This section provides guidelines for naming various entities in your ColdFusion
code.
General Naming Guidelines
All entities should be named for readability - names should be readable English
words or phrases. The primary function or purpose of any entity should be obvious
from its name. In general, "noun-verb" and "adjective-noun"
phrases are the most natural choice, e.g.,:
course_list_output.cfm - invoked in a URL
sales_tax_calculate.cfm - a custom tag
productinformation.cfc - a ColdFusion component
userName - a variable, attribute, property etc
The singular noun is preferred. In general, files will be lower case with
words optionally separated by underscores.
Abbreviations
Abbreviations and acronyms should be avoided. Only a few, widely understood
acronyms or abbreviations may be used, such as ID, CGI and URL. Such abbreviations
and acronyms will be uppercase, unless they are part of a filename that forms
part of a URL, in which case they will be lowercase, e.g.,
userID - variable, attribute, property etc
set_user_id.cfm - invoked in a URL
File Naming
Suffixes:
- HTML files end in
.html
;
- CFML files end in
.cfm
;
- Component files end in
.cfc
;
- XML files end in
.xml
.
In general, follow our existing file
naming conventions for files: all URL-accessible filenames shall
be lowercase, with words optionally separated by underscores (determined
by readability). Filenames must never contain spaces! Files whose
names are not URL-accessible should also be lowercase for consistency but
we allow more leeway in this situation.
Note: Application.cfm
and OnRequestEnd.cfm
are the only exceptions to the lowercase filename rule for URL-accessible files
and must have exactly the case shown! The Mach
II framework
files are mixed case (and are not URL-accessible) - when referencing those
files (as type names), you must use the same exact case as the filename.
ColdFusion Components
These are similar to Java classes but instead of following the traditional
Java class naming conventions (MixedCase
), we have historically
kept component filenames lowercase because, prior to CFMX 6.1, mixed case component
filenames were not uniformly supported. With CFMX 6.1, this practice can be
relaxed and mixed case component names can be used if desired for components
that are not URL-accessible.
The component name shall be lowercasewords
, lowercase_words
or
MixedCaseWords
; all method names, property names and instance
names (variables referring to components) shall be mixedCaseInitLower
.
Components that are URL-accessible, e.g., that implement Web Services, shall
be lowercasewords
or lowercase_words
.
All references to component names in code shall match exactly the case of the
implementation filename, i.e., references will be path.to.lowercasewords
,
path.to.lowercase_words
or path.to.MixedCaseWords
as
appropriate.
If a ColdFusion component contains methods that are accessible as Web Services
or via Flash Remoting (i.e., the cffunction
tag specifies access="remote"
),
then the component should be stored under {cfmxroot}/wwwroot/{applicationname}/
(and
have lowercase filenames). Otherwise, ColdFusion components should
be stored under {cfmxroot}/extensions/components/{applicationname}/
.
The directory structure should reflect the logical grouping
of the major elements of each application. All the application-specific components
should live in application-specific
sub-directories. All the utility and common reusable components should live
in appropriately named library sub-directories, e.g., WTG has both
lib
and util
sub-directories for these common components
(although those names are somewhat arbitrary).
Custom Tags
Custom tag names will be lowercase_words
. Their implementation
filename should be lowercase_words.cfm
, stored somewhere within
the
{cfmxroot}/extensions/customtags/
hierarchy (so custom tags cannot
be invoked directly via a URL). They should be invoked using a tag prefix (defined
using cfimport
before the first use of any custom tags in each
file - cfimport
tags should be grouped together near the top of the file) e.g., <pfx:lowercase_words
...>
... </pfx:lowercase_words>
. The pfx
will
usually be the lowest-level directory containing the tags, e.g., mmlf
for
{cfmxroot}/extensions/customtags/mmlf/
- used like:
<cfimport taglib="/customtags/mmlf" prefix="mmlf" />
...
<mmlf:ssi virtual="/path/to/file.html" />
The expectation is that directories under the Custom Tag Paths will have unique
names - the tag prefix must be unique within a page.
Note: The ssi
tag currently complains if you invoke
it with a closing / but I think that's a bug that should be fixed!
Note: CFX tags will not be used - instead write Java
tag libraries and <cfimport ...>
them (assuming you can't
write the tag in CFML for some reason).
Type Names
The names used to reference ColdFusion types (e.g., in type=
and returntype=
attributes)
shall be lowercase for built-in types (e.g., boolean
, string
).
The names used to reference user-defined types (i.e., ColdFusion Components
shall exactly match the case of the implementing filename, e.g., article
, news_item
, MachII.framework.Listener
.
Built-in CFML Tags, Attributes & Operators
Built-in CFML tags shall be lowercase, just like our HTML tags. Attributes
for CFML tags shall either be lowercase (mirroring XHTML-compliance) or mixed
case, first letter lowercase (mixedCaseInitLower
) - this is a stylistic choice
but be consistent. Built-in operators shall be mixed
case, first letter lowercase, e.g., mixedCaseInitLower
.
Note: This means simple built-in operators will be lowercase,
e.g., is
, and
, or
, not
.
Attributes, Fields, Functions, Methods, Parameters, Properties & Variables
All these entity names will be mixedCaseInitLower
. To enhance
readability, boolean attributes and variables should generally begin with "is
"
or "has
", e.g., <cfif hasFlash> ... </cfif>
.
Attribute Values
All attribute values to all tags - except cfset
, cfif
and cfreturn
- will be quoted, usually with double quotes ("
).
Single quotes ('
) may be used if the attribute value already contains
a double quote.
In cfset
, the attribute name is always a variable name (possibly
evaluated, e.g., arr[i]
) and the apparent attribute value is
really an expression. In cfif
and cfreturn
, the 'attribute' is really an expression. String
values in expressions will be quoted (with "
or '
as
appropriate). Numeric values in expressions will not be quoted. Variable
names in expressions will not be quoted, so that pound signs (#
)
are not needed, i.e., variableName
instead of "#variableName#"
.
The attribute name in cfset
- the variable name - will not
be quoted.
Do not use evaluated variable names like "caller.#resultVariable#"
or
"varname_#index#"
- use caller[resultVariable]
or variables["varname_"
& index]
instead.
The only acceptable boolean
attribute values are true
and false
- which may be quoted or unquoted (in cfset
,
they should always be unquoted).
Examples:
<!--- string requires quotes: --->
<cfset x = "A string" />
<!--- other expressions require no quotes: --->
<cfset y = len(x) />
<cfif z gt y * 2 >
<!--- simple variable requires no quotes: --->
<cfset request.value = z />
<!--- evaluated variable requires no quotes: --->
<cfset caller[result] = z />
Scope Names
Scope name qualifiers should be used with all variables (except var
scope
variables inside functions), where there is any possibility of a collision
with a name in another scope. Since ColdFusion looks 'up' the scope chain if
it cannot find a name in the current scope, variables
scope should
be used for safety, to avoid accidentally picking up the wrong variable in
an outer scope, e.g., a cookie. See Creating
and using variables in scopes on LiveDocs for more
information about scope lookup.
Inside components, variables
scope refers to non-public instance
data (and this
scope refers to public instance data). If you want
a local variable in a function, you
should
use var
and then set the variable to 'declare' it (at the top
of the function). Within a script function,
you introduce local variables as follows:
function foo() {
var localVar = 0;
var anotherLocalVar = 0;
...
}
Within cffunction
, you can use either of the following styles:
<!--- using tag syntax for the function body: --->
<cffunction name="bar">
<cfset var localVar = 0 />
<cfset var anotherLocalVar = 0 />
...
</cffunction>
<!--- using script syntax for the function body: --->
<cffunction name="bar">
<cfscript>
var localVar = 0;
var anotherLocalVar = 0;
...
</cfscript>
</cffunction>
Inside components, there are two special scopes: this
and variables
(in
CFMX 6.0, variables
scope was not available and you used instead
the unnamed scope). When variables are qualified with this
scope,
they become public data members of the component instance and accessible to
code
outside the component. When variables are qualified with variables
scope,
or left unqualified
- using the unnamed scope, they become non-public data members of the component
instance (and, therefore, are not accessible outside the component). This
is important since unqualified
variables within functions will persist for the lifetime of the instance -
which may not be what you intended.
Example:
<cfcomponent>
<cffunction name="example">
<cfset var localVar = "Just in this function" />
<cfset variables.nonPublicVar = "Non-public data member" />
<cfset anotherNonPublicVar = "Not recommended - use 'variables'" />
<cfset this.publicVar = "Public data member" />
</cffunction>
<cffunction name="more">
<cfset var localVar = "Different to example localVar" />
<cfset var x = variables.nonPublicVar & " set in 'example' above" />
</cffunction>
</cfcomponent>
Note: this.member
and member
denote two distinct variables in distinct scopes (but don't do this: in general,
name collisions are bad practice and cause debugging headaches!). variables.member
and member
denote the same variable (assuming member is not also declared
with var
) - always use variables.member
for clarity.
Scope names should follow the same capitalization rules as variables:
Examples:
form.myFormField
URL.myURLVar - note: URL is an acronym (uppercase)
cfhttp.fileContents - note: cfhttp is a built-in tag name (lowercase)
variables.pageVar
arguments.argName
this.publicVar
Query Naming
Query names follow the same convention as other variable names, using the
verbs Update
, Insert
, Delete
, or Select
as follows:
Query Type
|
Pattern
|
Example
|
Select Data
|
querynameSelect
|
customerSelect
|
Update Data
|
querynameUpdate
|
customerUpdate
|
Insert Data
|
querynameInsert
|
customerInsert
|
Delete Data
|
querynameDelete
|
customerDelete
|
This section provides guidelines on commenting your source code. In general,
we should comment code to assist other developers work on it in the future.
We do not want our comments to be visible to the public so we do not want
to generate HTML comments from CFML - we use <!--- ... --->
in CFML which does not get published into the HTML. This means that for file
types that can be accessed directly over the web, such as JavaScript include
files, XML files and CSS style sheets, we should keep comments to a minimum
- documentation for such files must be maintained separately, in the "projects"
area of our internal site for example. Comments are there to be read - consider
your audience!
General Guidelines
Write CFML style <!--- ... --->
comments, for all important
entities, that describe what code does and why - document the
how if it is not obvious.
When you make a change, comment it. Identify the change with the date and your
user name:
<!--- 2001-11-26 scorfield Expanded the Comments section --->
When you want to leave a note about a bug to be fixed or functionality to be
added, put TODO:
in front of the actual comment so developers can easily
search for them:
<!--- 2001-11-26 scorfield TODO: Incorporate everyone's feedback --->
Additional standard search keywords can be added after TODO:
e.g.,
FIXME:
, NOTE:
- this is very important as it helps
your audience, other developers. Furthermore, standard tags like this can be
read by code editors such as jEdit
to create a "task list" whenever you're working on a file.
<!--- 2001-11-26 scorfield TODO: BUG: Fails on Fridays --->
Here are some of the comment 'keywords' supported by jEdit's Task List plugin:
DEBUG: DONE: FIXME: IDEA: NOTE: QUESTION: TODO: XXX:
. You can easily
customize jEdit's list and add new keywords.
File Comments
Each CFML file should begin with an CFML style <!--- ... --->
comment containing the filename and a standard copyright message
followed by
an explanation of the file and then, optionally, its modification history:
<!---
$Id: news.cfm,v 1.7 2003/06/03 21:46:27 scorfield Exp $
Copyright (c) 2002 Macromedia, Inc.
Description:
This page renders information about each product.
Parameters:
product - the name of the product family
Usage:
product_page.cfm?product="Flash"
Documentation:
http://sandbox.macromedia.com/wtg/projects/runtime/product_page.html
Based on:
/software/dreamweaver/index.html 1.74
$Log: $
Revision 1.2 2001/07/26 15:19:03 scorfield
Added copyright comment
Revision 1.1 2001/07/23 11:23:46 scorfield
Initial version
--->
Note: We use $Id: $
so that CVS
will insert the filename, version and last modified date and author.
The explanatory comment for the file should contain, roughly in decreasing
order of importance:
-
a brief Description:
of the file, including some
kind of classification for components and custom tags,
-
a list of Attributes:
/ method or URL Parameters:
/ Result:
variables with brief descriptions,
Dependencies:
, both outward (this file depends on other things)
and inward (things known to depend on, or use, this file - preferably with
URLs),
-
a Usage:
example,
- the URLs of any known
Documentation:
for this file,
-
any files that were used as a basis for creating this file
(Based on:
),
-
any files that have in turn used this file as a basis because
future changes to this file may require similar changes to those files (Basis
for:
).
The modification history is optional but can be automatically generated
by $Log:
$
.
It prepends each new entry at check-in, so provide meaningful comments when
you check files into CVS. In long $Log: $
entries, developers
may replace older sections of the log by:
... See the CVS log for details ...
Note: $Log: $
can cause problems
for automated CVS merges - that's another reason to prune the generated log
entries at regular intervals (or omit $Log: $
altogether).
Component Comments
The cfcomponent
, cfproperty
, cffunction
and cfargument
component tags all have displayName
and hint
attributes which should be completed for every component,
every property, every method (function) and every argument. For cffunction
,
if the function throws any exceptions, the hint
attribute should
have "<br />Throws: document any exceptions that the
function can throw
" at the end of the hint.
- Put the label text you might show to a business user (on an edit form)
in
displayName
.
- Put a sentence or two of usage details in the
hint
attribute.
Note: The displayName
and hint
'comments' are in addition to the file comment
described above.
Layout
This section provides guidelines on source code layout for ColdFusion (and
HTML).
General File Format
Make sure you use Unix Linefeeds - see tool
setup tips for information on making Dreamweaver, CF Studio, etc. behave
properly. All indentation should be based on 4-space tabs - actual TAB characters
are preferably to multiple SPACE characters to reduce file size and make editing
easier.
General HTML Guidelines
Use Dreamweaver's validator tools to help you create clean, cross-browser
XHTML-compliant HTML. All generated HTML must pass tidy -errors
with
no errors, except that tables used purely for presentation do not need the "summary" attribute.
tidy
is a free tool from Dave Raggett, one of the HTML people
at the W3C. You can find it at http://tidy.sourceforge.net/.
http://www.w3.org/People/Raggett/tidy/ says "Tidy
is able to fix up a wide range of problems (in HTML documents) and to bring
to your attention
things that you need to work on yourself."
All generated HTML must pass Section 508 accessibility guidelines. See Accessibility
for more detail.
All generated HTML must specify a Content-Type
, a Content-Language
and a character set encoding (which should be UTF-8
). See Globalization
for more detail.
HTML & XHTML Compliance
All generated HTML should be XHTML-ready:
- Lowercase element and attribute names,
- All attribute values in quotation marks,
- Close all tags correctly, e.g., close
<p>
with </p>
and <li>
with </li>
,
- Although there are rumors that closing empty-body tags with
/>
breaks some old browsers, it is still recommended to do this, e.g., <br
/>
(note the space before the /
),
<img src="..." ... />
. Set Dreamweaver to generate
XHTML instead of HTML.
Generated HTML that is XHTML-compliant should begin with this:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Some browsers
interpret this as strict XHTML so you also need to add the following to the HTML
tag:
<html xmlns="http://www.w3.org/1999/xhtml">
Do not put the above code in generated HTML that is not XHTML-compliant!
CFML & XHTML Compliance
ColdFusion source code cannot quite be written to be purely XHTML-compliant
because of certain tags (cfif
/ cfelse
, cfreturn
, cfset
)
but you should make an effort to be as XHTML-compliant as possible. cfelse
cannot
have a closing tag so it cannot be XHTML-compliant; cfif
and cfreturn
do not
have an attribute="value"
syntax so they cannot be XHTML-compliant (but cfif
has a closing /cfif
tag and cfreturn
can and should have a self-closing /
);
cfset
does not in general follow the attribute="value"
syntax
and these guidelines recommend that for readability you do not quote the value
in cfset
- but cfset
can and should have a self-closing /
.
This makes the source code more consistent (across CFML and HTML) and will
also help you avoid subtle errors such as unterminated nested cfmodule
calls.
If
a simple custom tag invocation is written as XHTML-compliant, i.e., with
a closing />
,
it will be executed twice as if it were a paired tag with an empty body.
This can be surprising at first and cause subtle bugs if your code doesn't
expect it! You can guard against this in simple custom tags by
enclosing the code with:
<cfif thisTag.executionMode is "start">
...
</cfif>
Complex custom tags will probably already use thisTag.hasEndTag
and have different code executed for thisTag.executionMode is "start"
and thisTag.executionMode is "end"
.
All built-in CFML tags should be written as XHTML-compliant where possible
(cfif
, cfelse
,
cfset
and cfreturn
are notable exceptions).
Table Indentation
These are the guidelines for the layout of table source code (see also Accessibility):
- All table tags go on their own lines.
<tr>
tags are placed at the same indentation level as their
parent <table>
.
<td>
tags are indented.
- The contents of
<td>
tags may be placed on a separate line
and indented, or if they are short they may be placed on the same line as
the <td>
.
<table>
attributes should be explicitly specified.
Example:
<table border="0" cellPadding="0" cellSpacing="0">
<tr>
<td>
Table data goes here
</td>
<td>Short text here</td>
<td>
<table>
<tr>
<td>
Nested table data here
</td>
</tr>
</table>
</td>
</tr>
</table>
If whitespace is a problem (e.g., with very
long / deeply nested tables), use your judgment to adjust the layout to improve
the readability of the code. Given our use of CSS instead of tables for layout,
this should be a rare occurrence!
Tag Layout
When more than one attribute is passed to a custom tag, each attribute should
be placed on its own line and indented. The tag closing bracket (>
)
should be on a line by itself, indented the same as the matching opening
bracket. This allows for long, descriptive names for both the custom tag
and its attributes. For very short (single attribute) or relatively short
but frequently repeated tags (e.g., cfparam
),
this is optional.
Examples:
<cf_my_custom_tag_two
attributeOne="ValueOne"
attributeTwo="ValueTwo"
attributeN="ValueN"
/>
<cf_my_custom_tag
attributeTwo="Value Two"
/>
<cf_my_custom_tag attributeOne="Value One" />
<cfparam name="myVar" default="x" type="boolean" />
HTML tags do not need to follow these rules, due to whitespace considerations.
ColdFusion Component Layout
ColdFusion components should follow the same general rules for layout as other
tags.
Example:
<cfcomponent hint="..." displayName="...">
<cffunction name="doSomething" returnType="string">
<cfargument name="arg" type="string" />
<cfset variables.thing = arguments.arg />
<cfreturn arguments.arg />
</cffunction>
</cfcomponent>
An acceptable alternative, using more vertical space, is as follows:
<cfcomponent hint="..." displayName="...">
<cffunction
name="doSomething"
returnType="string"
>
<cfargument
name="arg"
type="string"
/>
<cfset variables.thing = arguments.arg />
<cfreturn arguments.arg />
</cffunction>
</cfcomponent>
SQL/cfquery Indentation
The following examples will most effectively describe the preferred SQL indentation
standards.
Example 1:
SELECT
TO.COLUMN_ONE,
TT.COLUMN_TWO,
TO.COLUMN_THREE
FROM
TABLE_ONE TO,
TABLE_TWO TT
WHERE
TO.TABLE_ONE_ID = TT.TABLE_TWO_ID
AND
TT.TABLE_TWO_ID = 10
ORDER BY
TO.TABLE_ONE_ORDER_KEY
Example 2 (Insert type A):
INSERT INTO
TABLE_ONE
(
COLUMN_ONE,
COLUMN_TWO,
COLUMN_THREE
)
VALUES
(
'ValueOne',
'ValueTwo',
'ValueThree'
)
Example 3 (Insert type B):
INSERT INTO TABLE_ONE
(
COLUMN_ONE, COLUMN_TWO, COLUMN_THREE
)
VALUES
(
'ValueOne', 'ValueTwo', 'ValueThree'
)
Example 4:
UPDATE TABLE_ONE
SET
COLUMN_ONE = 'ValueOne',
COLUMN_ONE = 'ValueTwo'
WHERE
TABLE_ONE_ID = 10
AND
COLUMN_THREE = 'ValueThree'
Contents | Structure:
Application, Component, Tag etc »
Source: http://livedocs.macromedia.com/wtg/public/coding_standards/style.html