ColdFusion MX Coding Guidelines - Good Practice
Release 3.0.2 (10/17/2003)
« Structure: Application, Component,
Tag etc | Contents | Database
Conventions »
Good Practice
This section provides some hints and tips that are considered "good practice".
Booleans
Booleans are always true or false, conditions are also true or false - do
not test a boolean expression against a value, just test the expression:
<cfif boolVar is "true"> <!--- BAD! --->
<cfif boolVar is "false"> <!--- BAD! --->
<cfif boolVar> <!--- good --->
<cfif not boolVar> <!--- good --->
cfswitch/cfcase
Instead of cascading cfelseif
blocks, when you are branching on the
value of a single expression, use cfswitch
and cfcase
instead:
<!--- bad: --->
<cfif expr eq "Value A">
...
<cfelseif expr eq "Value B">
...
<cfelse>
...
</cfif>
<!--- good: --->
<cfswitch expression="expr">
<cfcase value="Value A">
...
<cfcase>
<cfcase value="Value B">
...
</cfcase>
<cfdefaultcase>
...
</cfdefaultcase>
</cfswitch>
Components & cfargument
ColdFusion MX does not require that you use cfargument
tags but they provide
validation (type safety) and act as additional documentation - always provide
a cfargument
tag for each named argument your function expects and follow these
rules:
- Always specify the
type=
attribute in your cfargument
tags. Try to avoid
using type="any"
.
- Always specify the
required=
attribute in your cfargument
tags.
- If an argument
is required, do not specify a
default=
attribute.
- If an argument is not required,
you may specify a
default=
attribute (but remember that you will not
be able to tell the difference between the caller omitting that argument
and the caller providing that same default value as an argument).
- If you need to
detect whether a non-required argument was provided, do not specify
default=
but
instead use structKeyExists(arguments,"argName")
in
the function body.
Components & cfproperty
Be aware that the cfproperty
tag is of limited use - it does
only two things:
- It provides additional type validation for Web Service return types.
- It provides a way to add metadata to components.
In general, cfproperty
should not be used - it does not provide
type checking for instance data (in general) and it does not provide default
values for instance data so its presence can be misleading rather than helpful.
If you really are returning a component type from a Web Service and want the
public data members of that component to be type-checked at runtime, then cfproperty
can
be useful.
If you are creating a metadata-driven system, then cfproperty
can
be useful (although dynamic systems driven by component metadata tend not to
scale well!).
All components should define a method called init()
that initializes
the instance, even if the body of the method is empty, i.e., the initialization
doesn't do
anything. This makes usage of components consistent since you are guaranteed
to be able to call init()
on any component instance, just as you
can for Java objects created within ColdFusion. The method should have a return
type that matches the component and it should return
this
so that
the following construct is always legal:
<cfset obj = createObject("component","util.lib.thing").init() />
This matches the way that createObject().init()
behaves for Java objects -
init()
returns the fully initialized Java object.
The util.lib.thing
CFC
would have a method that looks like:
<cffunction name="init" access="public" returntype="util.lib.thing">
...
<cfreturn this />
</cffunction>
If your component extends another component, your init()
method should begin
with a call to super.init()
to initialize the base component.
Note: The call to super.init()
must
use positional arguments - the argumentCollection=
calling style
does not work with methods called via super
.
Note: There is a notable exception to this guideline
- when you are extending components in Mach II (listeners, plugins, event filters),
instead of defining a method called init()
, you define
a method called configure()
(which
does not return anything - configure()
has returnType="void"
).
This is because the framework itself uses init()
for
its own initialization and provides configure()
, which it automatically
calls for you once the framework has been initialized, so that you do not have
to worry about any initialization arguments that the framework requires.
Custom Tags
Custom tags should be organized into related group by using a meaningful directory
tree under the Custom Tag Path (defined in the ColdFusion Administrator). This
makes it easier to use cfimport
to access specific groups of custom
tags.
All custom tags should anticipate being executed in both start mode
and end mode, i.e., they should be structured as follows:
<cfif thisTag.executionMode is "start">
...
<cfelse> <!--- thisTag.executionMode is "end" --->
...
</cfif>
If the custom tag is a simple one, i.e., it doesn't process a tag
body, then the cfelse
section should be empty (and cfelse
can
be omitted). Do not put spurious complaints in the cfelse
section about being
called twice!
Do not hardcode a result variable in a custom tag, e.g., caller.result
.
Instead, use a resultVariable
attribute
and return results by setting the specified variable, i.e., caller[attributes.resultVariable]
.
This is more flexible and also reduces coupling between a custom tag and its
calling page.
« Structure: Application, Component,
Tag etc | Contents | Database
Conventions »
Source: http://livedocs.macromedia.com/wtg/public/coding_standards/goodpractice.html