Comments
Richard Davies wrote: The UK has a good crop of technology pioneers in cloud computing - for example ElasticHosts, FlexiScale, Flexiant, OnApp - and also some strong government initiatives such as G-Cloud. We will have to see whether this kind of technical leadership converts into swift mass-market adoption or not.
Cloud Expo on Google News

SYS-CON.TV
Cloud Expo & Virtualization 2009 East
PLATINUM SPONSORS:
IBM
Smarter Business Solutions Through Dynamic Infrastructure
IBM
Smarter Insights: How the CIO Becomes a Hero Again
Microsoft
Windows Azure
GOLD SPONSORS:
Appsense
Why VDI?
CA
Maximizing the Business Value of Virtualization in Enterprise and Cloud Computing Environments
ExactTarget
Messaging in the Cloud - Email, SMS and Voice
Freedom OSS
Stairway to the Cloud
Sun
Sun's Incubation Platform: Helping Startups Serve the Enterprise
POWER PANELS:
Cloud Computing & Enterprise IT: Cost & Operational Benefits
How and Why is a Flexible IT Infrastructure the Key To the Future?
Click For 2008 West
Event Webcasts
Maybe We Should Try a Separation
Maybe We Should Try a Separation

I have been writing and talking about ColdFusion components since before ColdFusion MX shipped. After I explained them in detail in two recent columns (CFDJ, Vol. 4, issues 6, 7), quite a few of you asked for practical examples of when and where they should be used. So, once again, let's take a look at CFCs, but this time from a very different angle.

Spot the Problem
To get things going, take a look at the following code (a working example, assuming you installed the ColdFusion sample applications and databases). It reads a user list from a database table and then displays the user names in an HTML unordered list:

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

<H1>Users</H1>

<!--- List users --->
<UL>
<CFOUTPUT QUERY="users">
<LI>#LastName#, #FirstName#</LI>
</CFOUTPUT>
</UL>

So what's wrong with it?

Don't see it? Look again. Carefully.

Still nothing?

Well, maybe there's nothing actually wrong with the code. It will run as is and will work (generating the appropriate output). But while it's syntactically correct, there actually is something very wrong with it.

<CFQUERY> Proliferation
Let's take a step back. Think about the application you last wrote, or the one you're working on right now.

Question: How many <CF QUERY> tags does your code contain? You can guess if you like (although I'm sure your guess will be lower than the actual total).

Next question: How many of the SELECT statements in your various <CFQUERY> tags are similar (or even the same)? You'll likely find that most of your queries interact with the same set of tables. Maybe one retrieves fewer or more columns than another, or sorts results differently, or just passes different WHERE clauses, but beyond that, how many are totally different?

Now for the most important question: What would happen to your code if a database column were renamed? Even more exciting, what would happen if a database schema were updated (as they should be periodically) so that your tables were split into multiple relational tables? Or - and I've saved the best for last - what if the database were changed altogether, maybe switching from one DBMS to another, or moving to an LDAP directory or an XML data store? What would that do to your code?

Think it doesn't happen? It does, and when it does, rewriting client code can be painful. And often the changes aren't made, even though they should be, out of fear of the work involved. So improvement and progress are stymied by codephobia (I made that word up as the English language didn't seem to contain one as eloquent. Feel free to use it yourself).

The problem is that the very nature of the Web and Web pages, combined with the immediacy of the platform, encourages this type of development (and, I should add, not just in ColdFusion). Chances are, you've written pages that include everything from database queries, HTML output, form validation, all sorts of conditional processing, and business rules, to logic and...you get the idea.

And that's what's wrong with the code I showed you previously:

  • Is that code reusable? Absolutely not (no, copy-and-paste doesn't equal reusable).
  • Would any UI created in that page be reusable with other data? Nope, not without lots of tweaking.
  • Would a developer or designer be able to create a better interface without knowing about the underlying data? Not at all.
  • Would everything break if the database changed? Most definitely.

    For that matter...

  • Could a designer create a richer user experience without even knowing what a database was, or how to write a SQL statement, or how to JOIN tables? Very unlikely.

    Now, once again, think about the app you just finished or the one you're working on. What if there weren't a single <CFQUERY> em-bedded in the pages that generated output and performed user interaction, would that make your development life easier?

    Separation of Presentation and Content
    Which bring us to the separation of presentation and content. This isn't a radical new idea (even if the same basic concepts keep resurfacing under new names). The basic concept is that your application needs to be broken into layers (often called tiers). Exactly how many layers is up for grabs (there are lots of opinions on this one, and for the most part the discussion is academic), but at a minimum your application should be broken into three distinct tiers:

    1.   The back end (starting with databases)
    2.   The front end (the user interface, be it Web pages, or client-side Flash, or anything else)
    3.   And in the middle, the application itself (often called the business tier)

    The truth is, the front end should never be tied to any particular database. Each should be free to be improved on (and changed and adapted) without fear of things breaking.

    Similarly, you'd never want your business logic in the same page that generates HTML output. Why? Well, as soon as you need an alternate output format (whether it be Flash, XML, a Web service, or even a simple spreadsheet), you'll need to re-create all that logic (or patch your original file).

    So, back to our example: the code both retrieved data from a table and formatted it for output. What if I needed an alternate output format? I'd have two choices. Either I'd create a second file (copying the query code) or I'd put a big <CFIF> statement around the output so it could generate both output formats.

    While that may be acceptable (and even manageable) for simple code like this, imagine if the query were extremely complex and required all sorts of postprocessing. Then neither option would be really workable. What I'd really want to do is move the database-specific code out of the file that generates presentation into its own file. Then I could have two different presentation files (one for each output format) and have them use the same query by accessing the query file.

    In tiered development, content and its presentation are explicitly separated, making each more manageable, more usable, and more reusable.

    ColdFusion and Tiered Code
    Everything discussed thus far applies to any development in any language, not just ColdFusion. But now let's focus specifically on ColdFusion.

    It's been possible to write code like this in ColdFusion for a long time. Between <CFINCLUDE> and custom tags, writing tiered code has been doable. But neither option is ideal. <CFINCLUDE> is ill suited for highly dynamic content (for starters, there's no way to pass variables to an included page or to return results), and custom tags are too cumbersome (no built-in parameter validation, single entry point, can't be introspected and thus can't be shared simply, can't return results, and more).

    Which brings us to ColdFusion components. CFCs are designed for just this purpose, building tiered applications. Imagine that you could take all your user-related queries and store them in a single file, then all your product queries and store them in another file, and so on.

    Then, to obtain a list of users you could do something like this:

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

    This code calls a method (a function) named List in a component named user and returns a result named users. What is in the user component? It doesn't matter. Whatever it is will be executed and a result will be returned.

    Another way to invoke the component would be:

    <!--- Get user --->
    <CFOBJECT COMPONENT="user"
    NAME="usrObj">

    ...
    <CFOUTPUT>
    <!-- Display email address --->
    #usrObj.GetEMail(URL.userid)#
    </CFOUTPUT>

    Here the user component is loaded as an object, and a specific method in that object is then invoked - in this example, passing a user ID and obtaining the e-mail address for the specified user.

    In both examples the component is now that middle tier - your presentation code talks to the component, and the component talks to the database.

    All that's needed then is the component itself.

    CFCs as the Middle Tier
    As explained in the earlier columns mentioned above, writing CFCs is very easy. (And if you use Dreamweaver MX there's a wizard you can use that does most of the work for you.)

    Look at this code:

    <!--- User component --->
    <CFCOMPONENT>

    <!--- List users method --->
    <CFFUNCTION NAME="List"
    RETURNTYPE="query">

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

    <CFRETURN users>

    </CFFUNCTION>

    </CFCOMPONENT>

    This is a complete (albeit rather simple) component. It defines a single method named List (the method used in the prior code snippets). List takes no parameters and returns a query (the same query as used above).

    The preceding code would be saved as user.cfc and references to a user component would access this CFC file.

    Here's the GetEMail method:

    <!--- Get e-mail address method --->
    <CFFUNCTION NAME="GetEMail"
    RETURNTYPE="string">
    <CFARGUMENT NAME="UserID"
    TYPE="string"
    REQUIRED="true">

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

    <CFRETURN user.Email>

    </CFFUNCTION>

    This code would be placed into the same user.cfc file (all methods go between the <CFCOMPONENT> and </CFCOMPONENT> tags). It takes a user ID as an argument and returns the e-mail address for the specified user.

    This is just the start of it. With all database queries in one isolated location, you can start getting creative. You could:

  • Cache data if needed so as to improve performance.
  • Maybe even conditionally update cached data based on system load and performance.
  • Handle all data conversions and reformatting internally so that UI code need not even be aware of it.
  • The list goes on and on.

    And it gets better. Dreamweaver MX is CFC aware and can automatically display a tree control listing all CFCs on your ColdFusion server. This allows users to right-click on any CFC or method to see more information about it, and even drag a method into their code to autogenerate the re-quired invocation code. All automatically, and all without having to register anything in Dreamweaver itself.

    Note: There's another benefit here, Flash MX integration. But more on that next month.

    What Next?
    If your application contained not a single <CFQUERY>, your code would be more manageable, more reusable, and even more scalable. I only showed you components encapsulating SELECT statements here, but you'd want to create components that did it all.

    Databases and database access is a good starting point. After all, it's what we do mostly with ColdFusion and CFML. But it's just a starting point. Any integration with back-end systems should be tiered, starting with databases but also including:

  • COM or CORBA integration
  • Server-side HTTP and FTP calls
  • Talking to Java APIs, beans, and objects
  • XML manipulation
  • Web services consumption
  • Interacting with ERP systems
  • Security and access control
  • Business logic and transaction processing
  • Any business intelligence (shopping carts, for example)
  • ...and anything else that isn't tied specifically to presentation

    The basic rule is this: if it isn't tied to client code, then it doesn't belong in client-generation code. Simple as that.

    Summary
    Most of us write spaghetti code, and that has to change. Structured, organized, tiered code is a must. I wouldn't get too hung up on exactly how many tiers are needed and whether they conform to any specific model as long as it gets done. For starters, commit to no more embedded database calls in your output pages - put them in components. Then apply this methodology to existing code. And start thinking about applying this type of development to nondatabase code as well. ColdFusion components make this very easy (and even reward the effort with better performance), so there's no longer any excuse for not doing it. It turns out that separation can indeed be a good thing.

    About Ben Forta
    Ben Forta is Adobe's Senior Technical Evangelist. In that capacity he spends a considerable amount of time talking and writing about Adobe products (with an emphasis on ColdFusion and Flex), and providing feedback to help shape the future direction of the products. By the way, if you are not yet a ColdFusion user, you should be. It is an incredible product, and is truly deserving of all the praise it has been receiving. In a prior life he was a ColdFusion customer (he wrote one of the first large high visibility web sites using the product) and was so impressed he ended up working for the company that created it (Allaire). Ben is also the author of books on ColdFusion, SQL, Windows 2000, JSP, WAP, Regular Expressions, and more. Before joining Adobe (well, Allaire actually, and then Macromedia and Allaire merged, and then Adobe bought Macromedia) he helped found a company called Car.com which provides automotive services (buy a car, sell a car, etc) over the Web. Car.com (including Stoneage) is one of the largest automotive web sites out there, was written entirely in ColdFusion, and is now owned by Auto-By-Tel.

  • In order to post a comment you need to be registered and logged in.

    Register | Sign-in

    Reader Feedback: Page 1 of 1

    After reading Ben Forta's article "Maybe We Should Try a Separation" it occurred to me this may me an alternative to fusebox. Any thoughts?


    Your Feedback
    Nick France wrote: After reading Ben Forta's article "Maybe We Should Try a Separation" it occurred to me this may me an alternative to fusebox. Any thoughts?
    Latest Cloud Developer Stories
    Swisscom, the Swiss telecom, is going into the cloud business. Its subsidiary Swisscom IT Services AG has signed up with Red Hat as a Certified Cloud Provider and launched a public cloud Infrastructure-as-a-Service (IaaS) cloud targeting enterprise-class customers primarily in ...
    Apache Deltacloud, the Red Hat-contributed ReSTful API that abstracts differences between clouds so services on any cloud can be managed – provided of course there’s a driver – has graduated from the Apache Foundation’s incubator and is now a full-fledged Top-Level Project (TLP)....
    In a surprise move on Tuesday, January 10, Oracle wheeled out its Big Data Appliance. That’s the one it said in October would be ready sometime in the first half. Only nobody believed it meant early in the first half. Heck, it’s not even clear anybody thought Oracle could make ...
    Rackspace Hosting, the service leader in cloud computing, on Thursday announced its acquisition of SharePoint911, an industry leader in SharePoint consulting, training, and "JumpStart" services within SharePoint. The unification of both companies provides capabilities to deliver ...
    CloudLinux, Inc., on Thursday released CafeFS 3, a virtualized file system for shared hosters that cages each customer within its own virtualized file system. CageFS becomes part of CloudLinux OS at no additional charge. CloudLinux OS, the only commercially-supported Linux OS m...
    Subscribe to the World's Most Powerful Newsletters
    Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
    Click to Add our RSS Feeds to the Service of Your Choice:
    Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
    myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
    Publish Your Article! Please send it to editorial(at)sys-con.com!

    Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021

    SYS-CON Featured Whitepapers
    ADS BY GOOGLE

    Breaking Cloud Computing News

    NASHVILLE, Tenn., Feb. 16, 2012 /PRNewswire/ -- Brookdale Senior Living Inc. (NYSE: BKD) (the "Co...