Skip to page content

Coding Standards and Best Practices

For www.faa.gov & employees.faa.gov

1. Naming Conventions

1.1 The J2EE/Java Naming Convention

The FAA web development group has adopted the Java naming convention for its applications with some slight modifications to reflect differences in Java and ColdFusion. Basic details of this naming convention will be presented in this document.

1.2 Variable and Function Naming

1.2.1 Basic Variables and Functions

Variable, attribute, and function (or “method”) names should begin with a lowercase letter, with the first letter of each subsequent word being capitalized. All letters not beginning a new word should be lowercase. Underscores and spaces should not be used, and other special characters should be avoided if possible. Numbers may be used when appropriate, but a number should not be the first character of the name.

Variable names should be verbose, providing general information about the purpose of a variable. Avoid nondescript names, such as a single letter, unless the variable is being used as a counter in a loop like the universally accepted “i.” Several examples are shown below illustrating correct and incorrect usage.

Variable and function naming
Incorrect Variable / Function Names Correct Variable / Function Names
MyNewVARIABLE myNewVariable
A_Variable_Name aVariableName
V descriptiveNameRequired
%LOUSY_Name lousyName
MyFunctionName() myFunctionName()

1.2.2 Constant Variables

Constants should be in all uppercase letters. Each word in a constant should be separated by an underscore. An example of a correctly formatted constant variable name is “NEW_VARIABLE.” Additionally, the Boolean constants “true” and “false” should always be written in capital letters as TRUE and FALSE when writing CFML. This does not apply to JavaScript or other implementations where lowercase letters are required or otherwise appropriate.

1.2.3 Query names

Query names should follow the same convention as regular variables, but should begin with a lowercase “q” to indicate that a particular structure is a query. This allows anyone reading the code to immediately know that a scoped variable starting with a “q” is coming from a query. The example below shows proper naming of a query and referencing its variables.

Code example

<cfquery name="qGetJunkDataForExample" datasource="#request.dsn#">
	SELECT  null AS junk
	FROM    dual
</cfquery>

<!--- Reference the variable --->
<cfoutput>#qGetJunkDataForExample.junk#</cfoutput>

1.3 Scope Naming

When referencing scopes, capitalize the first letter of the scope, and then write subsequent letters as lowercase. In the context of the Java naming convention, think of a scope as a Java class. Two exceptions to this are the URL and CGI scopes, which should be written in all uppercase letters because they are initialisms.

More information:

1.4 File Naming

The basic file naming scheme follows the Java naming convention with regards to case and capitalization, but appends a few additional guidelines. Based on the file context, most component files on the web server should have a prefix. The table below shows examples of where each component type should be located and when to use each prefix.

File naming
File Type Description and purpose Example File name(s)
Controller The index.cfm is the root file in a directory. This file is considered a core file, and does not need any prefix. Other files may also be in the core directory to encapsulate a given function of an application and they may be named the same way, with no prefix. index.cfm
confirmSubmission.cfm
processStep2.cfm
Query A query file, part of the model, located in a /model/ directory. Query files should begin with “qry” and should give an idea of the general purpose of a query in the file name. It is recommended, but not required, that SELECT queries use “Get,” INSERT queries use “Insert,” UPDATE queries use “Update,” and DELETE queries use “Delete.” qryGetAllSites.cfm
qryInsertUser.cfm
qryUpdateAircraft.cfm
qryDeleteLocationById.cfm
Action Actions contain most of the business logic and execute some portion of the request. Action files are located in a /model/ directory. An example of an action file might be validating data submitted via a form and then passing off to another component to perform a database update. Action files should begin with “act.” actValidateSearchForm.cfm
actVerifyLogin.cfm
actLogout.cfm
Display A display file should process logic determining the look and feel of a page. This may entail hiding or showing additional information based on a set of rules. Display files are located in a /view/ directory, and should begin with “dsp.” dspIndex.cfm
dspRightSidebar.cfm
dspSearchResults.cfm
Script A script file provides the client-side behavior layer for a page. All client-side JavaScript should be implemented unobtrusively, degrade gracefully, and not be relied on for critical tasks. Script files are located in an /assets/js/ or /script/ directory, and do not require a prefix. animation.js
domSelectors.js
Style A style file provides the presentation layer for a page. Style files are located in an /assets/css/ or /style/ directory and do not require a prefix. newsSearch.css
Media Media files include documents, images, video, audio, and other files available for the user to use or download. Media files are located in a /media/ directory. Image files can also go in an /assets/img/ directory. Media file names should not contain spaces, but are otherwise generally free of the file naming requirements for other files. banner.jpg
CustomerList2021-06.xls

File names are encouraged to be lengthy enough to explain a file's basic purpose without viewing the contents. For more complex processing, this may not be possible, but in most cases an effort should be made.

Back to Top


2. System Architecture

2.1 Model View Controller (MVC)

The model/view/controller (MVC) paradigm is one of the most widely known and commonly accepted approaches to software development. The MVC architecture is employed by the FAA website to separate the multiple tiers of the application. Each component and how it relates to the FAA website design is discussed in brief.

2.1.1 Model

The model represents the data sets and the bottom tier of an application. This typically includes database queries, system objects, and in object-oriented design includes classes representing the domain model. On the FAA website, model components are found in the /model subdirectory for each directory.

2.1.2 View

The view is the top tier of the application, frequently referred to as the presentation layer. The view file should only include logic to render the page to the user in the correct fashion, and should not be able to affect changes to the model directly. Once the view is rendered, it is a static page that must submit a request to the controller to proceed. On the FAA website, view components are found in the /view subdirectory for each directory.

2.1.3 Controller

The controller is the middle tier that represents the actions an application may perform and determines the flow from one page to another. The controller handles requests and forwards the user to the appropriate destination. It also contains “actions” which perform tasks such as validating user input data. On the FAA website, action components are found in the /model subfolder for each directory. In the FAA website implementation, the main controller for each page is the index.cfm file, located in the root of a given directory. This file is responsible for including the necessary components from the model and view. An exception is made for applications, which should use the FuseBox framework to handle requests to the controller. This is discussed later.

More information:

Back to Top


3. ColdFusion

3.1 General Practices

3.1.1 Operators

It is recommended that ColdFusion operators (such as greater than, less than, equals, etc.) be written in uppercase. This helps differentiate them easily, making key logic operators easy to discern. This is also the convention typically used by Adobe, developer of ColdFusion. Additionally, it is important to group logical operators explicitly with parentheses. In many cases this may not affect the compiler's interpretation, but makes logic much easier for other developers to follow.

Incorrect
<cfif 1 eq 2 or 3 neq 5>
	<cfset nothing = "" />
</cfif>
Correct
<cfif (1 EQ 2) OR (3 NEQ 5)>
	<cfset nothing = "" />
</cfif>

More information:

3.1.2 Boolean variables

Boolean variables are always TRUE or FALSE, and do not need to be tested against a value.

Incorrect
<cfif boolExpression EQ TRUE>
<cfif boolExpression EQ FALSE>
Correct
<cfif boolExpression>
<cfif NOT boolExpression>

ColdFusion is loosely typed and will silently convert variable types when the context requires it. However, for clarity and safety it is preferable to avoid relying on implicit conversions from numeric or string types to Boolean.

Incorrect
<cfif compareNoCase(x,y)>
Correct
<cfif compareNoCase(x,y) NEQ 0>

More information:

3.1.3 Use of Pound (#) Signs

Pound signs (#) in ColdFusion are used to specify that the content between the pound signs should be evaluated as a variable. Unfortunately it can frequently be unclear to programmers new to ColdFusion which situations warrant the use of pound signs to achieve the correct result.

Pound signs are most often used between <cfoutput> tags to evaluate and output the contents of a variable as shown below:

Required use of <cfoutput>#variableName#</cfoutput> pound signs.

Another appropriate place to use pound signs is in attributes of a tag when the value of an attribute is a variable instead of static text. In the following example, failure to use the pound signs would result in the literal string “Variables.listNames” being treated as the list to loop over instead of the list variable's contents.

Code example
<cfloop list="#Variables.listNames#" index="currentName">
	<!--- Some processing --->
</cfloop>

There are many places it is unnecessary and often confusing if pound signs are used. Instances where pound signs are frequently used unnecessarily include <cfif> and <cfset> statements.

Incorrect
<cfif #len(myString)# EQ #1#>
	<!--- Some processing --->
</cfif>
Correct
<cfif len(myString) EQ 1>
	<!--- Some processing --->
</cfif>

The examples below show various misuses of cfset and their cleaner, more concise counterparts.

Incorrect
<!--- Example 1: Standard cfset --->
<cfset myVariable = #anotherVariable# />
<!--- Example 2: Concatenation --->
<cfset myVariable = "#anotherVariable#" & ", " & "#stateVariable#" />

The corrected example achieves the same operation without the use of messy pound signs. The quotes surrounding the values in the concatenation operation are also not necessary in this case, as ColdFusion will automatically evaluate the variables. It is important to note, however, that if the variables are surrounded in quotes, the pound signs would be needed or ColdFusion will treat the variable as literal text. In this case, the best solution is to forgo use of the quotes and pound signs around the variable so that particular issue is not a factor.

Correct
<!--- Example 1: Standard cfset --->
<cfset myVariable = anotherVariable />
<!--- Example 2: Concatenation --->
<cfset myVariable = anotherVariable & ", " & stateVariable />

More information:

3.1.4 Variable Scoping

Scopes should be explicitly defined when variables are set and referenced. ColdFusion allows for very relaxed scoping of variables. If no scope is specified, ColdFusion will search each native structure (Form, Request, etc.) looking for a variable using a predetermined order. In many cases, scoping a variable may not lead to significant performance boosts, but makes the code much more readable. Someone reading your code can immediately know where to find a particular variable without wondering where it is coming from. Local variables should use the “Variables” scope as shown below.

Incorrect
<cfset zelda = 0 />
<cfoutput>#zelda#</cfoutput>
Correct
<cfset Variables.zelda = 0 />
<cfoutput>#Variables.zelda#</cfoutput>

3.1.5 Code Indentation

Proper indentation of code is often one of the easiest steps to take towards creating friendlier, more readable code. A little indentation while writing the code will save time later in debugging and understanding the flow of the program. Block statements should always have code between tags indented. This includes any tag that has an opening tag followed by a separate closing tag (i.e. not a singleton like <cfset />).

There are some exceptions to the rule, such as <cfoutput> tags enclosing a single variable, or <cfif> tags that are used within an HTML element to change a single attribute. Provided below are a few examples of how to implement indentation.

Incorrect
<cfif myString EQ "Hello World"><cfoutput>#myString#</cfoutput></cfif>
Correct
<cfif myString EQ "Hello World">
	<cfoutput>#myString#</cfoutput>
</cfif>

In the example above, since we're only outputting a single variable with the <cfoutput> tag, it's acceptable to leave it on the same line. The next example shows an acceptable usage of a <cfif> tag without indentation in order to avoid breaking the spacing in a text string.

<p>Found #rows# match<cfif rows NEQ 1>es</cfif> in #files.recordCount# file<cfif files.recordCount NEQ 1>s</cfif>.</p>

Often, <cfoutput> is used in large paragraphs of text to enclose single variables within the paragraph, so it does not help readability to disjoint the paragraph. However, any time <cfoutput> is used around a large block, for instance as a looping tag, its contents should be indented.

Incorrect
<cfoutput query="qTest">
<td>Looping with no indent</td>
<td>Is a bad idea.</td>
<td>If we nested another</td>
<td>Loop it would be worse</td>
</cfoutput>
Correct
<cfoutput query="qTest">
	<td>Looping with no indent</td>
	<td>Is a bad idea.</td>
	<td>If we nested another</td>
	<td>Loop it would be worse</td>
</cfoutput>

Indentation is often a matter of judgment, but adherence to the guidelines established here will ensure cleaner code. Note that actual tab characters are preferable to multiple space characters.

More information:

3.1.6 Comments

All code should include clear, succinct comments, in order to assist developers who work with the code in the future. Comments should describe what code does and why, leaving aside how it works unless it is not obvious. CFML comments (<!--- … --->) should be used instead of HTML comments (<!-- … -->) to prevent them from being visible to the public, and to reduce the weight of pages downloaded by users.

More information:

3.1.7 CFScript

Before the release of ColdFusion MX, many developers heavily used CFScript because of the performance boost it offered over tag-based CFML. However, this performance distinction no longer exists in recent versions of ColdFusion since all code is compiled to Java bytecode and run within the J2EE server.

3.1.8 CFML and HTML Compliance

CFML tags should be written as HTML-compliant, with the following necessary exceptions:

  • <cfelse> and <cfelseif> cannot have a closing tag.
  • <cfif> does not use an attribute="value" syntax.
  • <cfreturn> does not use an attribute="value" syntax. However, <cfreturn> should have a self-closing /.
  • <cfset> does not always use an attribute="value" syntax, and non-string values should not be within quotes in <cfset>. However, <cfset>, <cfparam>, and similar tags should have a self-closing /.

ColdFusion tags and attributes should also be written in all lowercase to be consistent with HTML tags. Some ColdFusion examples on the Internet, particularly older ones, may use capitalized tags. It is preferred that tags are written in lowercase.

Incorrect
<CFPARAM NAME="myVariable" DEFAULT="0">
Correct
<cfparam name="myVariable" default="0" />

More information:

3.2 Forms

3.2.1 Use of <cfform>

When creating forms, use of the ColdFusion <cfform> tag is not recommended. Although some of the drawbacks of using the tag (including non-HTML markup, clumsy JavaScript validation, limited extensibility, and reliance on poor-performing Java applets) have been reduced to varying degrees with later versions of ColdFusion, it is still preferable to create custom forms using traditional HTML markup.

3.2.2 Naming Form Elements

When naming form elements that correspond to fields in a database, form elements should be named the same as the column in the related database. If the column name contains underscores, remove them from the form element name. Use the Java naming convention to name the form input, for instance a database column called “NUMBER_TIMES_ACCESSED” would become “numberTimesAccessed.”

3.2.3 Form Validation

Developers should never rely on client-side validation (such as JavaScript) as the sole mechanism for verifying user input. Client-side validation relies on the user's browser, which might not meet the requirements necessary to perform the validation, or might intentionally circumvent the validation. See JavaScript for more details.

Validation of a form should take place on a server-side page within the controller or “action” aspect of the MVC architecture. Typical validation operations include checking the length of data, verifying that data are within an accepted range, and ensuring integrity between sets of data.

Validation feedback should be provided if the data provided do not meet the established criteria. The system should forward the user back to the form where the data were entered and conspicuously display messages regarding why the data were not accepted. The form should also retain the data the user had previously entered. As an additional option, form fields that contained an error might be highlighted, but this is not a requirement.

3.3 Performance

Much of optimizing ColdFusion performance involves using good development practices, such as those outlined in this document. In general, it is not important to focus on low-level performance tweaking, especially when such tweaking negatively impacts code readability.

Following are several issues which can significantly impact performance:

  • Do not use Microsoft Access databases in a production environment. See section 6, “Database and Structured Query Language (SQL) ”, for more information.
  • Ensure that your SQL statements are querying the database efficiently.
  • Use <cfquery>'s caching functionality where appropriate.
  • Avoid the evaluate() and iif() functions.

Additionally, providing visual feedback to users when an application is expected to take a while often gives the perception of better responsiveness.

More information:

3.4 Security

3.4.1 SQL Injection Attacks

An SQL injection attack is the act of embedding partial SQL queries inside of input that is used within a query. For example, the following code is vulnerable:

SQL injection vulnerable code
<cfquery name="qLogin" datasource="#Request.dsn#">
	SELECT *
	FROM   users
	WHERE  userName = '#Form.userName#'
</cfquery>

The easiest way to protect your applications from an SQL injection attack is to use the <cfqueryparam> tag. See SQL for more information.

More information:

3.4.2 Cross-Site Scripting (XSS)

Cross-site scripting attacks are among the easiest to enact and most widespread on the Internet today. Two methods to reduce the likelihood of a successful attack are checking HTTP referrer information before processing form submissions, and HTML-encoding any data derived from users or otherwise susceptible to user-tampering (such as URL parameters).

The encodeForHTML() and encodeForHTMLAttribute() functions can be used to help protect ColdFusion pages that incorporate user-provided data into the HTML response. The aforementioned functions remove return characters from a string (while preserving line feed characters), and convert certain characters to their HTML entities:

Cross-site scripting
Character Entity
< &lt;
> &gt;
& &amp;
" &quot;

Note that these functions might increase or reduce the length of a string. This can cause unpredictable results when performing certain string functions (e.g. left(), right(), and mid()) against the adapted string.

The following code demonstrates how to check if the HTTP referrer is on the same server as the current page.

Code example
<cfif NOT (len(CGI.HTTP_REFERER) GT 0 AND findNoCase(CGI.SERVER_NAME, CGI.HTTP_REFERER) ... GT 0)>
	<p>Post from foreign host detected.</p>
	<cfabort />
</cfif>

In cases where there may be a legitimate reason for an empty HTTP referrer, the code can be modified as follows.

Code example
<cfif len(CGI.HTTP_REFERER) GT 0 AND findNoCase(CGI.SERVER_NAME, CGI.HTTP_REFERER) GT 0>
	<p>Post from foreign host detected.</p>
	<cfabort />
</cfif>

However, neither method accounts for subdomains (such as “www”) existing in SERVER_NAME but not in HTTP_REFERER. They also fail to verify that the server name is not simply a subdomain or within the directory path of the referrer. For these reasons, a regular expression should be used to validate that the referring page is within the same root domain as the template processing the input. The following code applies this for the faa.gov domain.

Code example
<cfif reFindNoCase("^https?://(?:[a-z\d-]+\.)*?faa\.gov(?:/|$)", CGI.HTTP_REFERER) EQ 0>
	<p>Post from foreign host detected.</p>
	<cfabort />
</cfif>

The above code will evaluate the following referrers as shown:

Referrers
Referrer Accepted
https://www.faa.gov/ Yes
https://www.employees.faa.gov/directory/index.cfm?var=value Yes
https://www.faa.gov.example.com No
https://example.com/?www.faa.gov No
https://example.com/directory/www.faa.gov No
(empty referrer) No

However, this cannot defeat a technically savvy user who is able to spoof the HTTP referrer while using a foreign host. Ultimately, user data should always be validated and considered inherently untrustworthy.

More information:

3.4.3 Document Object Model (DOM) Manipulation

DOM manipulation may be used, for example, to modify a form in a way that grants a user special privileges they would not otherwise possess. Two common attack vectors for DOM manipulation are cross-site scripting (XSS) and browser add-ons which allow real-time manipulation of JavaScript or HTML on the page.

To mitigate the risk of these kinds of attacks, applications should not rely on data received from a user (e.g., a hidden input submitted by a form or a URL parameter) for user identification, and should always ensure that the user has appropriate rights to perform the requested action, rather than simply ensuring the user has rights to use an application or page. In other words, it should not be assumed that because an application only presents users with options appropriate for them, the action requested must therefore be within their rights.

3.4.4 Man in the Middle Attacks

Man in the middle attacks involve an attacker or rogue program intercepting and altering communication between a client and server. This can allow an attacker to read or modify messages without either party knowing the link between them has been compromised. To mitigate this risk, sensitive applications should require connections using Transport Layer Security (TLS). Any application that includes an authentication system for users is required to use TLS. Any attempt to use the application over a non-TLS connection should be redirected to the TLS equivalent.

More information:

3.4.5 Passwords and Authentication Mechanisms

OMB policy requires that passwords meet all of the following criteria:

  • Have a minimum length of eight characters or the maximum the existing system allows, if less than eight characters.
  • Not contain all or part of the user's account name.
  • Contain characters from at least three of the four following types: English uppercase characters (A–Z), English lowercase characters (a–z), numerical digits (0–9), and non-alphanumeric characters. Characters cannot be repeated more than once within a succession.

Since the security of all communication media between a user and the server cannot be trusted, passwords and other sensitive data must be transmitted over TLS. On the backend, passwords must be encrypted or stored using a hashing algorithm such as SHA-2 or SHA-3.

Passwords should be changed regularly to limit the usefulness of compromised passwords. Federal policy dictates that passwords have a maximum life of one year, but it is a best practice to limit password life to 30 to 90 days. If a user's password has not been changed by the expiration date, they should be required to change their password when they log in. Additionally, at least five prior passwords should be recorded and the user should be prevented from using these passwords again.

If several invalid login attempts are made in a short period of time, users should be prevented from continuing since it is possible that someone is trying to guess their password. However, user accounts should not be disabled or locked as a result of failed login attempts, because such a mechanism can be exploited to perform a denial of service by systematically locking out many accounts. Instead, the user should be required to wait several minutes or begin a new browser session before reattempting authentication.

Authenticated sessions should be automatically terminated after a period of inactivity.

More information:

More information about general web application security issues:

More information about ColdFusion development and best practices:

Back to Top


4. JavaScript

4.1 Overview of JavaScript and its Use

JavaScript is very powerful and has numerous uses, but also carries some problems with it. When used on the client-side, execution of JavaScript code is largely dependent on the version of the user's browser and the configuration of the user's options. Some JavaScript may run correctly on one browser, but incorrectly on another. JavaScript may never run at all if a user has disabled it. In still other cases, a user may manually manipulate JavaScript through a JavaScript command-line or other browser add-on. For these reasons, JavaScript should be used sparingly and not relied upon for critical functions or layout instructions.

4.2 General Practices

  • Browser support for various JavaScript APIs varies widely. Ensure that your JavaScript code is compatible with the browsers that you are required to support.
  • Ensure that JavaScript functionality degrades gracefully for users who have disabled JavaScript or are using older browsers.
  • Separate behavior and structure. This is also known as using unobtrusive JavaScript. A developer should only have to add a class or id attribute to one or more HTML tags and use JavaScript to query the DOM and attach event handlers to NodeList items at run time. Utilizing this approach improves usability, accessibility, code readability, modularity, and ease of implementation.

    JavaScript example (DOM, Level 2)

    document.getElementById('pathFromRoot').addEventListener('click', function () {
    	console.log('clicked');
    });

    jQuery example (v. 1.7+)

    $(document).on('click', '#pathFromRoot', function () {
    	console.log('clicked');
    });
  • Do not use <noscript> to provide alternative versions of content. Instead, <noscript> should only be used to inform users that enhanced functionality is available when JavaScript is enabled. Unobtrusive JavaScript should be used to extend the functionality of existing, accessible content.
  • Use the same naming convention as established for ColdFusion (the Java naming convention). Keep in mind, however, that unlike ColdFusion, JavaScript is case sensitive. Variables, functions, methods, properties, constructors, and reserved words must all use the correct case or the JavaScript will produce bugs.
  • Use semicolons (;) to indicate the termination of a line when appropriate. JavaScript has automatic semicolon insertion, but developeres are advised to supply statement-terminating semicolons explicitly because it may lessen unintended effects of the automatic semicolon insertion. Additionally, inconsistent usage of semicolons is considered bad practice and sloppy.
  • Limit or avoid declaring variables in the global scope as much as possible in order to improve performance and avoid conflicts with other scripts and libraries. Use the var keyword when declaring variables within functions to ensure that variables are contained within the function scope only.
  • Use script file includes (e.g., <script src="assets/js/thisOneScript.js"></script>) instead of embedding the JavaScript directly in a page's source code. This improves modularity, encourages reusability, helps to keep code hidden from users, and avoids confusion between JavaScript and <cfscript>. JavaScript files should be placed in their own subdirectory (assets/js/ or something similar) for a particular page or section.
  • Do not launch alerts or modal dialogs when a user first visits a page, as this typically annoys users and slows their progress when navigating a site.
  • Do not augment the prototype of the Object constructor (Object.prototype), because this changes the expected behavior when using objects as hash tables and will cause for…in loops to return unpredictable results.
  • Opening curly brackets for functions, if statements, and other structures which utilize them should be on the same line as the statement they begin. Closing curly brackets ending a statement should occupy a new line by themselves unless followed by an “else” or “else if.” Curly brackets should always be used, even for statements with a single line. Although the code may execute correctly without them, the inclusion of brackets can significantly improve code readability and maintenance.

    Incorrect

    // Example 1
    if(someVar == 1)
    doSomething();
    
    // Example 2
    if(anotherVar == 2)
    {doAnotherThing();}
    else
    {doSomethingElse();}

    Correct

    // Example 1
    if ( someVar === 1 ) {
    	doSomething();
    }
    
    // Example 2
    if ( anotherVar === 2 ) {
    	doAnotherThing();
    } else {
    	doSomethingElse();
    }

4.3 Appropriate uses of JavaScript

JavaScript can be useful in moderation. Provided below are a few examples of good uses of JavaScript.

  • Confirming the submission of a form. Record deletion is an operation that should always be prompted with a confirmation. However, for deletion of small, relatively inconsequential data, it is burdensome to force the user to click through extra screens of confirmation. One mechanism that allows a quick confirmation is a JavaScript prompt. The code below will prompt the user to confirm a deletion before submitting the data to be removed.

    JavaScript example (DOM, Level 2)

    document.getElementById('recordForm').addEventListener('submit', function (event) {
    	event.preventDefault();
    	if ( confirm('Are you sure you want to delete?') ) {
    		this.submit();
    	}
    });

    jQuery example (v. 1.7+)

    $(document).on('submit', '#recordForm', function (event) {
    	event.preventDefault();
    	if ( confirm('Are you sure you want to delete?') ) {
    		this.submit();
    	}
    });
  • Supplementary form validation. While HTML5-based form validation has attained near-universal support, it can still be helpful to include some validation through JavaScript. For example: to ensure a selection is made before submission. However, client-side validation should not be relied on and must always be accompanied by validation on the backend.
  • Disabling a button after the submit event. Another common scenario is preventing a form from being submitted multiple times. When users have to wait several seconds for a form to submit, they may become impatient and click the submit button again. In some cases this can result in the form being submitted with the same data more than once, causing duplicate records. To overcome this, many sites disable a submission button once it has been clicked the first time:

    JavaScript example (DOM, Level 2)

    document.querySelectorAll('.content form')[0].addEventListener('submit', function () {
    	this.querySelectorAll('button')[0].setAttribute('disabled', 'disabled');
    });

    jQuery example (v. 1.7+)

    $('.content').on('submit', 'form', function () {
    	$(this).find('button').prop('disabled', true);
    });

This is obviously not a comprehensive list of the appropriate uses of JavaScript, but is intended to show that JavaScript should be used in a sensible manner and typically in small doses. A system should not rely on JavaScript for any critical functions.

More information:

Back to Top


5. HyperText Markup Language (HTML)

All HTML markup is required to be Section 508 compliant and well-formed according to the HTML document type definition. Developers should strive for a fully semantic approach to markup and maintain a strict separation of structure, presentation, and behavior. For more information, refer to the following resources:

Back to Top


6. Database and Structured Query Language (SQL)

6.1 Database Management System (DBMS) Considerations

6.1.1 Using the Correct DBMS

The selection of the correct DBMS can have a drastic impact upon system performance and response time. FAA has an enterprise-wide license for Oracle, and it has been accepted as the DBMS to use. Under no circumstances should a Microsoft Access database be used in a production environment. Even for small projects, an Access database is not appropriate on the web for numerous reasons, some of which are listed below.

  1. Scalability: In theory, the JET engine (database engine for Microsoft Access) can support up to 255 concurrent users, but in practice you will never even approach that mark. Performance will suffer with as few as three or four concurrent users.
  2. Performance: Microsoft Access, in general, performs queries and fulfills requests far slower than other DBMSs optimized for potentially millions of users, such as Oracle.
  3. Security: An Access database on the network provides additional vulnerability. The database is not intended to stand up to serious security threats, and due to numerous bugs could be exploited to gain access to sensitive data.

If relational data needs to be stored in a database, the appropriate tables and relationships should be created in Oracle.

6.1.2 Porting Microsoft Access to Oracle

If a database schema has already been created in Access and database queries have already been written in code, there are several considerations that may ease the transition to Oracle.

  1. 1.If using non-ANSI standard SQL functions, some of them will not work in Oracle. For example, instead of UCase() and LCase() use upper() and lower() in Oracle.
  2. Do not include spaces in table or field names. Replace spaces with an underscore if necessary. Table and field names may not be longer than 30 characters in Oracle.
  3. Do not surround column or table names with brackets [ ].
  4. Any instances of a wildcard asterisk “*” used with a LIKE statement should be replaced with the Oracle equivalent, a percent sign “%.”
  5. Avoid using Oracle keywords in field names, table names, and aliases. Keywords such as TABLE, COLUMN, VALUE, and numerous others can cause queries to fail seemingly inexplicably. For a full listing of keywords, check the Oracle website.
  6. See Structured Query Language (SQL) for more information.

6.1.3 Alternatives to a DBMS

If the data being used do not require a relational model and are “flat,” then the data may not require a database at all. Data are considered “flat” if they occupy a single database table or spreadsheet, and do not have relationships to other entities. Some viable alternatives to using a database to store these data include extensible markup language (XML) and ColdFusion structures.

6.1.4 Using the Backend — Triggers, Views, and Stored Procedures

When used properly, databases can give applications a performance boost by performing actions quickly on the backend where the data resides. However, placing all of the business logic in the database is generally a very poor idea. It makes it accessible to fewer parties, makes maintenance more difficult, and may be less extensible and reusable throughout the entirety of the application. It is important to be familiar with the facilities a database offers and when it is appropriate to use them. An extremely basic overview of Oracle's abilities is provided, but developers are encouraged to explore further on their own to learn more details.

Triggers, views, and stored procedures
Object Description Usage
Views A view is typically a read-only abstraction of data, combined from several tables or using calculated fields that might be cumbersome to write in a <cfquery>. If a particular query utilizing several joins or using fields that are calculated based on functions or procedures is used frequently in an application, it may make sense to make it a view. This view is maintained in the database and can be queried against and have criteria applied as necessary.
Triggers Triggers have many usages. One of the most basic uses for a trigger is to auto-increment a primary key field in a table using a sequence. Triggers should always be used to increment primary keys in the database. ColdFusion <cfquery> tags should never INSERT or UPDATE a primary key field. These triggers should usually be created when a table is created.
Stored Procedures Functions and stored procedures are typically written in PL/SQL and can be very powerful. Stored Procedures are often necessary for scheduled tasks that use backend data, such as sending out a nightly email based on a given criteria, or performing data loading operations. Custom functions that are able to perform complex decisions on the backend may help some queries perform better, particularly if the queries recur throughout the application. Most other processing should be performed in the ColdFusion code unless impractical.

Using the tools provided by Oracle is primarily a matter of judgment. If there is a sound reason for moving certain functionality into the database, contact the database administrator (DBA) about making use of Oracle's facilities.

6.2 Structured Query Language (SQL)

SQL is the means by which data are retrieved, inserted into, and updated from a database. Sloppy SQL can result in many serious consequences, including security vulnerabilities, drastic performance bottlenecks, and poor portability. These guidelines have been established to try to minimize these issues, and should be used when writing SQL.

6.2.1 Specific SQL and <cfquery> Guidelines

  1. Do not use SELECT * to retrieve all the columns in a given dataset. This can cause issues with caching the query (in the event of database structural modifications), and can cause improperly aliased columns to display the wrong value or throw an error. Explicitly list out all column names.
  2. Ensure all tables and sub-queries being used as tables are aliased. An alias is a name assigned to a table or dataset. Oracle 10g in particular is very strict regarding aliasing. Field names should be explicitly listed and each should have an alias in front of the column name. See the figure below for an example of correct and incorrect implementations. In the correct example, the aliases used are “t1” and “t2.”
    Incorrect
    SELECT    *
    FROM      Table1
    LEFT JOIN Table2
    ON        Table1.field1 = Table2.field2
    WHERE     field1 IN (1,2,3)
    ORDER BY  field2
    Correct
    SELECT    t1.field1, t2.field1, t2.field2
    FROM      Table1 t1
    LEFT JOIN Table2 t2
    ON        t1.field1 = t2.field2
    WHERE     t1.field1 IN (1,2,3)
    ORDER BY  t2.field2
  3. Use all uppercase for SQL keywords and Oracle reserved words including SELECT, FROM, LEFT JOIN, INNER JOIN, RIGHT JOIN, OUTER LEFT JOIN, OUTER RIGHT JOIN, UNION, INTERSECT, WHERE, HAVING, ORDER BY, IN, ON, IS, AS, TABLE, COLUMN, UPDATE, INSERT, DELETE, DROP, ADD, MODIFY, VALUES, etc. This improves readability and easily calls attention to key portions of the SQL statement.
  4. Apply the Java naming convention when calling SQL and Oracle functions including trim(), upper(), decode(), etc. Since none of the functions exceed one word, all of the functions will be completely lowercase.
  5. Make proper use of indentation and line breaks. Items following a major keyword should be indented such that the items after each keyword are aligned with the items after the other keywords. See the example below for correct usage.
    Incorrect
    SELECT t1.f1 FROM Table1 t1
    Correct
    SELECT t1.f1
    FROM   Table1 t1

    In the correct example the text after the keywords is aligned.

  6. Each line should contain only one major keyword unless a sub-query is being used. For instance, the following example shows an example of a permissible usage.
    Code example
    SELECT t1.f1, t1.f2, t1.f3
    FROM   Table1 t1
    WHERE  t1.f1 IN (SELECT DISTINCT t2.sid FROM Table2 t2)
    AND    t1.f2 IS NOT NULL
  7. When writing queries within a ColdFusion <cfquery> tag, use <cfqueryparam> in WHERE clauses, INSERT statements, and UPDATE statements. This has numerous benefits, including increased security, automatic escaping of problematic characters, data typing, and portability. More information about the benefits of <cfqueryparam> can be found in the ColdFusion documentation provided by Adobe. You must use <cfqueryparam> for any variables being supplied, but will not be required to use it for static values. Note the one place <cfqueryparam> cannot be used is a WHERE clause containing the LIKE operator and a wildcard (%). In this case, <cfqueryparam> will ignore the wildcard, so in that instance it should not be used. See the figures provided below for proper usage of <cfqueryparam>.
    Incorrect
    UPDATE Table1 t1
    SET    t1.f1 = '#myVariable#'
    WHERE  t1.f2 = #aNumberVariable#
    AND    t1.f3 = 'STATIC_TEXT'
    AND    t1.f4 LIKE '%searchVariable%'
    Correct
    UPDATE Table1 t1
    SET    t1.f1 = <cfqueryparam cfsqltype="cf_sql_varchar" maxlength="250" ... value="#myVariable#" />
    WHERE  t1.f2 = <cfqueryparam cfsqltype="cf_sql_integer" value="#aNumberVariable#" />
    AND    t1.f3 = 'STATIC_TEXT' <!--- Optional use here --->
    AND    t1.f4 LIKE '%searchVariable%' <!--- Cannot use here --->
  8. Multiple criteria in a WHERE clause should each be on a new line, including each AND and OR component. The exception to this is nested criteria and BETWEEN statements. An example of proper usage is shown below.
    Code example
    SELECT t1.f1, t1.f2, t1.f3
    FROM   Table1 t1
    WHERE  t1.f1 = <cfqueryparam cfsqltype="cf_sql_varchar" maxlength="250" ... value="#myVariable#" />
    AND    t1.f2 = <cfqueryparam cfsqltype="cf_sql_integer" value="#aNumberVariable#" />
    AND    (t1.f3 = 5 OR t1.f4 > 3)
    AND    (NOT (t1.f5 BETWEEN 0 AND 1000))

    In this case it would clutter the query to move the NOT, nested OR, and BETWEEN to a new line, so they can be left as is.

  9. Use of comments in large queries is acceptable and encouraged in many cases. For instance, in a search results query, the WHERE clause might be built dynamically based on a several parameters. It makes the code easily understandable to someone else if there are comments noting each parameter.
  10. A <cflock> tag should not be used in a <cfquery> tag. If a variable from a shared scope needs to be used in a query and its access or manipulation presents a potential race condition, retrieve the value first into a local variable via <cflock> and then use the local variable in the query. Operations such as file input/output and web services should also be avoided in a <cfquery> block. In most cases, the only code that is appropriate in a <cfquery> block is the use of decision making statements such as <cfif> and <cfswitch>. Other operations should be performed outside the query first.
    Incorrect
    <cfquery name="qBadExample" datasource="#Application.datasource#">
    	SELECT t1.field1
    	FROM   Table1 t1
    	WHERE  t1.field1 =
    		<cflock scope="Session">
    			#Session.someValue#
    		</cflock>
    </cfquery>
    Correct
    <!--- Get the value from the session and assign it locally --->
    <cflock scope="Session">
    	<cfset Variables.someValue = Session.someValue />
    </cflock>
    
    <cfquery name="qGoodExample" datasource="#Application.datasource#">
    	SELECT t1.field1
    	FROM   Table1 t1
    	WHERE  t1.field1 = <cfqueryparam cfsqltype="cf_sql_integer" ...
    		value="#Variables.someValue#" />
    </cfquery>
  11. Do not make frivolous use of UNION. A UNION operation is one of the more costly SQL operations and can frequently be avoided by intelligent query design. In the example shown below, a UNION is performed to add a blank value to be shown at the top of a drop-down list. This value could easily be added in the form as an option before looping through the result set or with queryAddRow() without the expense of a UNION operation in the database.
    Incorrect
    SELECT   t1.f2, t1.f3
    FROM     Table1 t1
    UNION
    SELECT   0,' '
    FROM     Table2 t2
    ORDER BY t1.f3
  12. Related to the previous item, judicious use of the decode() function provided by Oracle can drastically increase performance in some situations. The decode() function provides a mechanism allowing Oracle to make a decision, similar to an if…then or switch statement. This can be extremely powerful and helpful in reducing the burden a query has on the system, but if abused can lead to lazy query design and over reliance. The example below shows an example of a single query being used to sum the number of employees within certain salary ranges grouped by department. Written using the decode() function, the query can be performed in a single pass, as opposed to several UNION queries or multiple queries to the database.
    Example
    <cfquery name="qDecodeExample" datasource="#Application.datasource#">
    SELECT      em.deptNo,
    	sum(decode(greatest(em.salary, 3001), least(em.salary,9999), 1, 0)) ...
    	AS sum3001To9999,
    	sum(decode(greatest(em.salary,10000), least(em.salary,19999), 1, 0)) ...
    	AS sum10000To19999
    FROM        employees em
    GROUP BY    deptNo
    </cfquery>
  13. When using domain aggregate functions (such as SUM()) as part of a SELECT statement, use the AS keyword to rename the column something more appropriate for ease of reference. When renaming the column, use the standard Java naming convention. See the example provided below.
    Incorrect
    SELECT   max(t1.f1), t1.f2
    FROM     Table1 t1
    GROUP BY t1.f1, t1.f2
    Correct
    SELECT   max(t1.f1) AS maxF1, t1.f2
    FROM     Table1 t1
    GROUP BY t1.f1, t1.f2
  14. Do not use data definition language (DDL) to create or modify database structure on the fly. This includes (but is not limited to) CREATE, ALTER, and DROP statements. This introduces numerous security risks, not to mention concurrency and configuration management problems. If there is a compelling case for use of temporary tables or other structure modification to be effected by code within an application, it must be discussed and approved by a database administrator (DBA) beforehand.

Back to Top


7. Browsers

While browser rendering engines are slowly but steadily converging on their support of web standards, applications and pages must still be tested with many browsers and browser versions. Special consideration should be given to legacy versions of Internet Explorer. It is prudent to support browser versions that are used by at least 1% of your site's visitors. Know your visitors.

Understand the concept of progressive enhancement and how it pertains to web technologies, such as advanced CSS, HTML5 features, new JavaScript APIs, canvas, et cetera.

Back to Top

8. Mobile

Contact Web Management for more information on Mobile standards.

Back to Top

Page last modified: July 06, 2023 5:31:14 PM EDT