At work I (with heavy input from the rest of the team) am writing these guidelines for our development practices, so that everyone is working 'on the same page.' I will share this series here for others who may want to know how some folks do it.

In everything there must be balance, two sides to every coin. A debate goes on about code "structure". To indent? Or not indent? One argument persists that unnecessary spaces/tabs within code increase the bandwidth used by our systems, serving up 'empty' content. The other argument is that this cost is minimal, in comparison to the time savings with relation to maintaining 'readable' code.

Our official position is that the maintainability of code is more important. At some juncture, in the future, we may implement other methods for reducing the 'space', possibly eliminating it during the Ant build process during deployment. For now it is more important to be able to quickly scan code, find items for clarification or change, and accomplish our mission.

Proper indentation of code does assist in the maintainability of the code, and should be applied regardless of the language being used (XHTML, ActionScript, JavaScript, SQL, ColdFusion, etc.) Indentation should be applied to logical blocks of code within a document. The following are a few different examples:

ColdFusion CFC:

view plain print about
1<!---
2 *====================================================================================
3 *    TEMPLATE/CLASS
4 *    com.DM.testObj
5 *
6 *    PURPOSE
7 *    Just a test object
8 *
9 *    AUTHOR
10 *    Stephen G. 'Cutter' Blades, Jr. [SGB] sbladesATmycompanyDOTcom
11 *
12 *    COPYRIGHT
13 *    MyCompany (c) 2008, All Rights Reserved
14 *
15 *    NOTES
16 *************************************************************************************
17 *    SGB [02.20.2008]
18 *    Initial file creation.
19 *    Dependencies:
20 *        com.DM.superObj
21 *    Dependent Objects:
22 *        com.DM.subObj
23 *====================================================================================
24 --->

25<cfcomponent displayname="testObj" extends="superObj" output="false">
26
27    <!--- Some props --->
28    <cfset VARIABLES.instance = StructNew() />
29    
30    <cffunction name="Init" output="false" returntype="testObj" access="public">
31        <cfargument name="objID" type="numeric" required="false" default="0" />
32        <cfargument name="objName" type="string" required="false" default="" />
33        <cfargument name="dtCreated" type="date" required="false" default="#Now()#" />
34        <cfset var iItem = 0 />
35        <cfloop collection="#ARGUMENTS#" item="iItem">
36            <cfset Set(iItem,ARGUMENTS[iItem]) />
37        </cfloop>
38        <cfreturn THIS />
39    </cffunction>
40
41</cfcomponent>

Most documents, of any type, will have very similar, base level code stylization. The following example is for a standard ColdFusion template. Most nested elements/tags will further increase the indentation, though there will be exceptions.

ColdFusion CFM

view plain print about
1<cfsetting enablecfoutputonly="true">
2<!---
3 *====================================================================================
4 *    TEMPLATE/CLASS
5 *    wwwroot/public/time.cfm
6 *
7 *    PURPOSE
8 *    To demonstrate Coding Guidelines
9 *
10 *    AUTHOR
11 *    Stephen G. 'Cutter' Blades, Jr. [SGB] sbladesATmycompanyDOTcom
12 *
13 *    COPYRIGHT
14 *    MyCompany (c) 2008, All Rights Reserved
15 *
16 *    NOTES
17 *************************************************************************************
18 *    SGB [02.20.2008]
19 *    Initial Creation
20 *    Dependencies:
21 *        com.DM.subObjGateway
22 *====================================================================================
23 --->

24
25<!--- Processing code before output --->
26<cfimport taglib="/custom/interface" prefix="ui" />
27
28<cfscript>
29    // Set some variables
30
    VARIABLES.soGW = CreateObject("component","com.DM.subObjGateway").Init(APPLICATION.DSN.myDS);
31    VARIABLES.qUsers = VARIABLES.soGW.GetAdminUsers();
32    VARIABLES.arrNames = ArrayNew(1);
33    /*
34     *    Loop over the returned query, and create an array
35     *    of names, concatenated from the returned FirstName
36     *    and LastName
37     */

38    for(VARIABLES.i = 0;VARIABLES.i LTE VARIABLES.qUsers.recordCount; VARIABLES.i = VARIABLES.i + 1){
39        if(Len(VARIABLES.qUsers.FirstName[VARIABLES.i])){
40            ArrayAppend(VARIABLES.arrNames, VARIABLES.qUsers.FirstName[VARIABLES.i] & " " & VARIABLES.qUsers.LastName[VARIABLES.i];
41        }
42    }
43
</cfscript>
44<!--- The header and footer includes already wrap the output in cfoutput --->
45<ui:incHeader>
46
47    <cfif ArrayLen(VARIABLES.arrNames)>
48        <cfoutput>
49            <cfsilent>
50                <!---
51                 *    Here we wrap a multi-line CF comment in a <cfsilent> tag
52                 *    to prevent the whitespace from being rendered into the
53                 *    rendered source. ColdFusion comments would typically
54                 *    show as whitespace, if included inside an output block,
55                 *    but the <cfsilent> tag will suppress that processing
56                 *    output. It is also good to use the tag around display logic
57                 *    blocks you may have nested within output.
58                 --->

59            </cfsilent>
60            <div id="nameDescr">
61                This is a breakdown of the various names within our Administrative System - <strong>#APPLICATION.systemName#</strong>.
62            </div>
63        </cfoutput>
64        
65        <cfloop from="1" to="#ArrayLen(VARIABLES.arrNames)#" index="VARIABLES.lpIndex">
66            <cfif VARIABLES.lpIndex eq 1><cfoutput><p></cfoutput></cfif>
67            <cfoutput>Name: #VARIABLES.arrNames[VARIABLES.lpIndex]#<br /></cfoutput>
68            <cfif VARIABLES.lpIndex eq ArrayLen(VARIABLES.arrNames)><cfoutput></p></cfoutput></cfif>
69        </cfloop>
70    <cfelse>
71        No names were returned by your request.
72    </cfif>
73
74<ui:incFooter>
75<cfsetting enablecfoutputonly="false" />

From the previous example, you see a number of examples simultaneously. We start with the standard comment header, come to some processing directives, then get into actual output. The entire document is wrapped within a <cfsetting> tagset. These tags, at the beginning and end of the document, are open (or self-closing) tags, the first stating that any document content after the tag should only be displayed if it is within an explicit output block (either <cfoutput> or a WriteOutput() statement). The second <cfsetting> tag opens the document for non-explicit output, in case this template is included inside another document. By usinging the enablecfoutputonly attribute, the server will reduce the amount of whitespace rendered in the XHTML passed to the browser. Another tool for this is the use of the <cfsilent> tags. Here they are wrapped around a multi-line ColdFusion comment, which would be processed as whitespace to the XHTML document (The above example is for example use only. The above comment would have typically been outside the <cfoutput> altogether). By using the <cfsilent> tags around this, we eliminate that whitespace generation. These tags are also handy if you require a processing block in the middle of your output, as it will hide the whitespace that processing block would produce.

The example above also shows that there are times when you should, and should not, indent. With ColdFusion, JavaScript, ActionScript, etc., simple conditional output (if this then "ok") will typically be inline, while more complex conditional output will be indented as normal. Any looping conditionals will be indented. There are examples above for both tag based, and simple scripted programming.

Our next post will be part II of this topic, where we will show more examples covering XHTML, script, and SQL examples.