View comments | RSS feed

ColdFusion MX Coding Guidelines - Style: Naming, Comments & Layout

Release 3.2 (4/14/2005)

Contents | Structure: Application, Component, Tag etc »

Printable Version

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, "verb-noun" and "adjective-noun" phrases are the most natural choice, e.g.,:

course_list_output.cfm - invoked in a URL
calculate_sales_tax.cfm - a custom tag
ProductInformation.cfc - a ColdFusion component
userName, lastName, getBankBalance - a variable, function, attribute, property etc

The singular noun is preferred. In general, .cfm files will be lower case with words optionally separated by underscores and .cfc files will be MixedCase (also known as CamelCase).

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:

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 generally be lowercase for consistency but we allow more leeway in this situation.

Note: Application.cfc, 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

The component name shall be MixedCaseWords (preferred), lowercasewords or lowercase_words; all method names, property names and instance names (variables referring to components) shall be mixedCaseInitLower (also known as headlessCamelCase). 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.MixedCaseWords, path.to.lowercasewords or path.to.lowercase_words 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., Macromedia Web Team 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, NewsItem, 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>.

Function and method names should generally be of the form verb() or verbNoun(), e.g., read(), getName().

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. 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 - hence the need to use var to declare local variables!

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

Comments

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 Eclipse to create a "task list" whenever you're working on a file.

<!--- 2001-11-26 scorfield TODO: BUG: Fails on Fridays --->

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
--->

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:

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.

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 preferable 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 should also 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 / Section 508 Guidelines 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:

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 / Section 508 Guidelines):

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 »

Comments


ednagel said on Apr 13, 2004 at 4:36 AM :
It may just be me, but isn't ColdFusion script processed out of the page before being sent to the Web server and subsequently, the client's browser? And if that is the case, why would you have to make your ColdFusion code XHTML compliant? After all, once the CF server processes out the CF code, if applicable, it will be replaced by html and the CF code won't be there anymore! I would appreciate any understanding you would be willing to pass along.
SeanCorfield said on Apr 13, 2004 at 11:03 AM :
Yes, by the time the page reaches the browser, the ColdFusion tags have been processed and are no longer part of the document.
This guideline is merely about visual consistency within a source page: rather than have some tags be closed XHTML-style and some tags not, it is easier on the eye - and more consistent - to close all tags XHTML-style, regardless of whether they are HTML or ColdFusion.
Furthermore, if you get into the habit of closing all tags XHTML-style, you are more likely to write XHTML-compliant HTML.
The same logic is what drives the recommendation to have lowercase ColdFusion tags (to match lowercase HTML tags, required by XHTML). The lowercase tags do not contribute to XHTML-compliance but they provide a most consistent visual style and, in my opinion, make code easier to read.
JButter said on Jul 22, 2004 at 5:57 AM :
Concerning the HTML & XHTML Compliance section: Some ColdFusion tags force non-compliance to this standard. Use of CFFORM in conjunction with any CFFORM control creates ugly, uppercase, non-terminated form controls. The only choices you have is to not write XHTML or not use CFFORM.

This should be addressed in a bug fix or new version of CF anyways. Otherwise, why even provide the CFFORM tag at all.
SeanCorfield said on Jul 22, 2004 at 10:14 AM :
The non-compliance of code generated by CFFORM is a known issue that will be addressed in a future release.
eric.moritz said on Dec 27, 2004 at 7:40 AM :
You can also add xml complience by simulated a cfif with a cfswitch like the xslt choose tag, although it is hard to simulate some cfelseif's without some clever coding.:

<cfscript>
i = 10;
</cfscript>
<!--- This is a simulation of a cfif/cfelse --->
<cfswitch expression="#evaluate('i gt 3')#">
<cfcase value="true">
<cfoutput>Yes, #i# is greater than 3</cfoutput>
</cfcase>
<cfdefaultcase>
<cfoutput>This is the else equivilent</cfoutput>
</cfdefaultcase>
</cfswitch>
nathany said on Mar 5, 2005 at 10:47 AM :
Really good read... a very nice set of standards so far.
The only thing I would change, is the yucky all upper-case SQL
statements. Why is that? Shouldn't database field names should be
consistent with variables names used the rest of the application
(headlessCamelCase)?

The following example is never going to come through nice on the
forum. So I'll try
to describe it. The tabs form a nice solid line between the statements on
the left and what data they are working with (all expect for order by,
which is a tad too long and I'd rather not add another tab just for it).
Keywords like on/and have a tab before and after, so they are separate
from the main keywords. Keeping the "and" at the beginning of the same
line as the expression makes it easy to comment out that one "and"
when testing things.

select to1.columnOne, to1.columnThree,
tt1.columnTwo
from table_one to1
join table_two tt1
on to1.tableOneId = tt1.tableTwoId
where tt1.tableTwoId = <cfqueryparam
cfsqltype="CF_SQL_INTEGER" value="10" />
and to1.columnOne = <cfqueryparam
cfsqltype="CF_SQL_VARCHAR" maxlength="40" value="AndIndented" /
>
order by to1.tableOneOrderKey
SeanCorfield said on Mar 5, 2005 at 1:16 PM :
The SQL coding guidelines come from our Oracle DBA team.

We like the upper case SQL code because it makes it stand out on the page, distinct from the CFML that surrounds it.

Also, some databases are case sensitive so using all upper case table / column names is actually safer (more portable). However, the most important thing is consistency. As it says on the opening page of these guidelines, you are free to take the document and change it for your own use.
MattRobertson said on Jul 27, 2005 at 2:10 PM :
Why isn't cfqueryparam shown in the SQL examples in the MX coding Guidelines? You would think something so critical would be illustrated so that beginners and even intermediate developers would begin to be aware of its existence.
SeanCorfield said on Feb 24, 2006 at 9:33 AM :
Matt, if the SQL examples used variables, cfqueryparam would definitely be present.
Wadem said on Apr 12, 2006 at 1:52 AM :
SeanCorfield that was a very easy point to make... there are no variable's so cfqueryparam is not required. That point taken do you not think it would be a good idea to add at least one example in the same section, that uses a param. So that if a complete CF novice was reading this page they would see right away `<cfqueryparam` and think to them selves... what’s that then? Why should I use them? I know its a coding standards doc, but it can't harm to point out something important that some people may not know about.
SeanCorfield said on Apr 14, 2006 at 3:28 PM :
Wadem, a very fair point. I shall make sure the next revision of this page does show cfqueryparam.

 

RSS feed | Send me an e-mail when comments are added to this page | Comment Report

Current page: http://livedocs.adobe.com/wtg/public/coding_standards/style.html