Accessibility
 
Home / Developer Center / ColdFusion MX Application Developer Center

ColdFusion Article

Ben Forta photo
Ben Forta
Senior Product
Evangelist for
ColdFusion
 
Previous Columns
· Building a Macromedia Flash interface for content management
by Kevin Towes
· Security best practices: Authenticating and authorizing against
NT domains with ColdFusion MX

by Rob Rusher
 
Using ColdFusion components--properly


Code reuse is good. It's such a good thing, in fact, that Macromedia ColdFusion lets you reuse code in several ways, from simple includes to custom tags and user-defined functions. Over the past few years, ColdFusion developers have come to understand what these methods are and the better developers out there made a point of taking advantage of code reuse so they could build better applications.

And then, just when everything was clear and well understood, things got a little more complicated.

ColdFusion components (CFCs) are the new application building blocks introduced in Macromedia ColdFusion MX. They do the seemingly impossible—marrying the power of objects with the simplicity of CFML.


ColdFusion components: not your old custom tags
CFCs allow, and even encourage, the creation of structured applications. Of all the code reuse options, CFCs are most like custom tags. However, there are some very important differences between them:

  • Custom tags have a single entry point; CFCs can have multiple entry points. This makes it possible to create a single component that does many related actions. (To do that with custom tags you'd need multiple tags or cumbersome switch processing.)
  • Custom tags have no formalized parameter passing and validation mechanism; CFCs do. In other words, unlike custom tags, CFCs can validate passed data, enforce data types, check for required parameters, and optionally assign default values.
  • Custom tags cannot persist; CFCs can. Custom tags are blocks of code that are executed as is, while CFCs are objects and can be treated as such.
  • Custom tags are designed to contain code; CFCs are designed to contain both code and data.
  • Custom tags are accessible only by ColdFusion and only locally; CFCs can be accessed as web services, opening up a whole new world of reuse possibilities.
To sum it up, CFCs and custom tags are quite different. Although their functionality does overlap a little, they really do not solve the same problems at all.

Let's look at an example. The code sample below, user.cfc, abstracts and encapsulates user processing. It has three methods:

  • List obtains a list of users returning a query containing first and last names and user IDs.
  • Get returns a user record retrieved from two tables.
  • GeEMail retrieves a user's e-mail address.
Here's the code for user.cfc:

<!--- User component --->
<CFCOMPONENT HINT="User processing">

   <!--- List users method --->
   <CFFUNCTION NAME="List"
               RETURNTYPE="query"
               HINT="Get complete user list">

      <!--- Get users --->
      <CFQUERY NAME="users" DATASOURCE="exampleapps">
      SELECT EmployeeID AS UserID, FirstName, LastName
      FROM tblEmployees
      ORDER BY LastName, FirstName
      </CFQUERY>

      <CFRETURN users>
   </CFFUNCTION>

   <!--- Get user method --->
   <CFFUNCTION NAME="Get"
               RETURNTYPE="query"
               HINT="Get a complete user record">
      <CFARGUMENT NAME="UserID"
                  TYPE="string"
                  REQUIRED="true"
                  HINT="Employee ID is required">

      <!--- Get user email --->
      <CFQUERY NAME="user" DATASOURCE="exampleapps">
      SELECT EmployeeID AS UserID, FirstName,
             LastName, Title, Email,
             Phone, DepartmentName
      FROM tblEmployees, tblDepartments
      WHERE tblEmployees.DeptIDFK=tblDepartments.DepartmentID
      AND EmployeeID='#ARGUMENTS.UserID#'
      </CFQUERY>

      <CFRETURN user>
   </CFFUNCTION>

   <!--- Get user method --->
   <CFFUNCTION NAME="GetEMail" RETURNTYPE="string">
      <CFARGUMENT NAME="UserID"
                  TYPE="string"
                  REQUIRED="true"
                  HINT="Employee ID is required">

      <!--- Get user record --->
      <CFQUERY NAME="user" DATASOURCE="exampleapps">
      SELECT Email
      FROM tblEmployees
      WHERE EmployeeID='#ARGUMENTS.UserID#'
      </CFQUERY>

      <CFRETURN user.Email>
   </CFFUNCTION>

</CFCOMPONENT>

The beauty of user.cfc is that it removes all database interaction from an application. Instead of having to use a <CFQUERY> to obtain a user list, you could do the following:


<!--- Get user list --->
<CFINVOKE COMPONENT="user"
          METHOD="List"
          RETURNVARIABLE="ListRet">

The value returned by this <CFINVOKE> call is a query and can be used as such.

Here's another example, this time displaying a user's e-mail address:

<!--- Load user object --->
<CFOBJECT COMPONENT="user"
          NAME="usrObj">
<!-- Display email address --->
#usrObj.GetEMail(URL.userid)#
Here the user component is being loaded as an object (into the default VARIABLES scope, as no other scope was specified), which is then used to execute a particular method.


Building tiered applications
Now that you have seen what can be done with a ColdFusion Component, let's look at why you should do it. Most ColdFusion developers write spaghetti-code—a single CFML file that often contains database queries, HTML output, forms, JavaScript, business logic (in the form of CFML statements), and more. This type of code is not only not reusable, it's difficult to maintain and doesn't scale. This is why more experienced developers use custom tags and other forms of code reuse, as I already mentioned.

Still, custom tags are not good enough. They were designed to black-box and encapsulate functionality—essentially taking blocks of CFML code and packaging them for reuse. Custom tags are ideal for abstracting menuing code, encapsulating payment processing integration, and even rendering output. Custom tags were not designed for truly tiered application development. That's where CFCs come into the picture.

Consider the user.cfc example from before:

  • The CFC cleanly separates content from presentation, making each far more reusable.
  • The CFC makes it possible for developers working on presentation not to have to worry about what the data is and where it comes from. (For example, one of the methods does a JOIN to return the data. The fact that a JOIN is needed is of no consequence to whoever is building your UI.) The truth is, why should someone concentrating on writing DHTML have to worry about your database schemas? Why should they even have to know that the data is in a database?
  • The CFC allows you to make database schema changes (even replacing the database with an LDAP server, perhaps) without having to change a lot of code.
As a result of these qualities, developers can use CFCs in all sorts of ways. This is the basis of tiered applications—the separation of content from presentation—and CFCs are the essential building blocks with which to tier applications.


Writing for reuse
ColdFusion Components are used to create reusable code. As such, they must be written with reuse in mind. This means that CFCs should never make assumptions about the operating environment. For example:

  • CFCs can access all variables in all scopes, but they probably shouldn't. If they do, then whoever uses the CFC will have to know too much about what it does and why. In this case, if a CFC requires a FORM field, for example, it should accept it as an argument and not access it directly.
  • CFCs should never access SESSION variables unless they themselves set them (for example, if all SESSION processing was encapsulated within a CFC). It's dangerous to assume that you know the environment in which your CFCs will be used; after all, SESSION variables may not exist. If you require a variable, it should be passed to you.
  • CFCs should also never access CGI variables. Sure, these variables will always be present if the request comes from a browser, but can you ensure that you won't need to use this component in some other way in the future?

The bottom line is that within a CFC you should never assume that you know anything about where the request is coming from, what the request is for, what the data will be used for, or anything else. CFCs should be capable of standing on their own. Writing for reuse demands it.


What about presentation?
If ColdFusion Components cannot make assumptions about their environment, then CFCs cannot be used to render output. Because you're separating content from presentation, CFCs should return data; they shouldn't worry about prettying it up or generating clients-side HTML. If your CFC is written properly it may be used by all sorts of clients, among them:

  • Web browsers (different versions with different capabilities)
  • Macromedia Flash MX
  • Web services (through SOAP)
  • Mobile devices

To support multiple forms of presentation only the presentation layer has to change; the content layer does not. Your CFCs only process content – logic and processing that is common regardless of presentation , and so the CFCs should not generate finished pages. It is perfectly reasonable (and even advisable) for a CFC to return data followed by a set of pages that present the data in different ways. And if you need reuse at the presentation level, custom tags are ideally suited for that task. Their syntax, especially support for tag pairs and child tags, makes applying presentation to returned content clean and simple.

Of course, every rule has an exception: CFCs can indeed render content. But if you go this route, be careful not to end up right where you started off—breaking the desired separation of presentation and content. If you want to use CFCs to render content, consider using inheritance in CFCs—create a base CFC that holds all your content processing and then extend it using a series of CFCs, one for each presentation type and each with its own display method. This route is definitely feasible, although you may still find that, syntactically, custom tags are better suited for the task.

 
 

About the author
Ben Forta is Macromedia's senior product evangelist and the author of numerous books, including ColdFusion 5 Web Application Construction Kit and its sequel, Advanced ColdFusion 5 Development. Ben is working on several new titles on ColdFusion MX. For more information visit www.forta.com. You can contact Ben at ben@forta.com.