YOUR FEEDBACK
James Nelson wrote: Thanks for the posting, which we are hoping will solve our software issue with t...
AJAXWorld RIA Conference
$300 Savings Expire August 29
Register Today and SAVE!


2008 East
DIAMOND SPONSOR:
Data Direct
Frontiers in Data Access: The Coming Wave in Data Services
PLATINUM SPONSORS:
Red Hat
The Opening of Virtualization
Intel
Virtualization – Path to Predictive Enterprise
Green Hills
IT Security in a Hostile World
JBoss / freedom oss
Practical SOA Approach
GOLD SPONSORS:
Software AG
The Art & Science of SOA: How Governance Enables Adoption
PlateSpin
Effective Planning for Virtual Infrastructure Growth
Fujitsu
Automated Business Process Discovery & Virtualization Service
Ceedo
Workspace Virtualization
Click For 2007 West
Event Webcasts

2008 East
PLATINUM SPONSORS:
Appcelerator
Think Fast: Accelerate AJAX Development with Appcelerator
GOLD SPONSORS:
DreamFace Interactive
The Ultimate Framework for Creating Personalized Web 2.0 Mashups
ICEsoft
AJAX and Social Computing for the Enterprise
Kaazing
Enterprise Comet: Real–Time, Real–Time, or Real–Time Web 2.0?
Nexaweb
Now Playing: Desktop Apps in the Browser!
Sun
jMaki as an AJAX Mashup Framework
POWER PANELS:
The Business Value
of RIAs
What Lies Beyond AJAX?
KEYNOTES:
Douglas Crockford
Can We Fix the Web?
Anthony Franco
2008: The Year of the RIA
Click For 2007 Event Webcasts
SYS-CON.TV
TOP COLDFUSION LINKS


Preserve Precious Resources- Recycle
Preserve Precious Resources- Recycle

Doing so gave me the chance to clean up lots of old code (updating it to use new CF features in the process) while rethinking the organization and management of code to facilitate better reuse of common code and components.

Code organization and reuse are important topics, and judging by lots of code I've seen at customer sites of late (production code nonetheless), they are topics that need clarifying and addressing. So I'd like to use this month's column to share some of these ideas with you.

Why Reuse?
Programmers love reusing code, and for good reasons.

  • Reusing code can dramatically cut down development time. After all, why develop something from scratch when you can reuse something written previously?
  • Reusing proven code helps write bugfree applications. Programmers are human. We make mistakes, and we gradually fix them when we find them. Why start with a whole new set of mistakes when you can leverage the code with mistakes already fixed? Furthermore, applications that share common code also share common code fixes.
  • Code that's properly shared and reused is far more maintainable. If you've ever had to update menu options (images, links, DHTML code) in multiple application pages you know what I mean.
  • Code designed for reuse can be shared far easier. If another developer needs to use your complex drop-down menu code, invoking an abstracted menu object is far simpler than nitpicking and dissecting an application page with that code embedded in it.
  • And finally, the very act of writing code with reuse in mind helps organize code properly.

    Well-organized code, code broken into small, bite-size chunks, code thought through and designed to be reusable - that's the kind of code that separates experienced professional developers from beginners.

    That's true of any language, and CFML is no different. In fact, CFML has several language features designed with code organization and reuse in mind.

    The <CFINCLUDE> Tag
    ColdFusion's <CFINCLUDE> tag has been part of CFML for a long time now. It is used to perform server-side includes. When ColdFusion encounters a <CFINCLUDE> in your code, it includes the appropriate CFM file right then and there at the location of the <CFINCLUDE>, as if the included code had been typed there directly.

    And that's important to understand. ColdFusion processes the included file as if it were part of the calling page. This means that the two pages share the same scope, so any variables or queries defined before the <CFINCLUDE> are visible (can be read and written to) within the included code. Similarly, any variables or queries defined within the included page are visible in the calling page to any code after the <CFINCLUDE> tag.

    This also means that there is no protection of data. Within an included page you can (deliberately or inadvertently) change or overwrite data in the caller page. In fact, as <CFINCLUDE> has no formal mechanism for passing data (parameters or attributes) to included code, setting variables explicitly with <CFSET> before a <CFINCLUDE> is often necessary.

    This is a very important behavior to bear in mind when using <CFINCLUDE>, and it is not an oversight or bug. Rather, this behavior is intended and by design. Because included pages share the same scope, ColdFusion's overhead in including files is minimal. This translates into extremely fast performance. In fact, you'll notice no real difference in execution time between a single thousand-line page and 10 included pages of 100 lines each.

    So when should (and when shouldn't) <CFINCLUDE> be used? Obviously, if all you're doing is grabbing content to be sent to the client, a <CFINCLUDE> makes a lot of sense. For example, my site uses a collection of JavaScript functions that I want available to most pages. Rather than copy all that JavaScript into each file, I simply insert the following line into each file:

    <CFINCLUDE TEMPLATE="/common/jsfuncs.cfm">

    This way, ColdFusion inserts the entire jsfuncs.cfm file into all the pages that need it.

    But if your included code does any form of CFML-based programmatic processing or manipulation, it might not be a candidate for use with <CFINCLUDE>. For example, I have a block of code that surrounds the body of each page, code that contains header and title information, menus and toolbars, and DHTML-related code. If this code had been static, <CFINCLUDE> use would be appropriate. But my code isn't static at all; it has all sorts of conditional code in it, like logic to highlight the currently selected menu option. Code like that, code that manipulates data (and can thus inadvertently manipulate data it shouldn't), code that needs data passed to it, code that does more than just include content to be sent to the client – that kind of code should not be included with <CFINCLUDE> at all.

    To summarize, <CFINCLUDE> is fast, it's easy to use and it's ideally suited for use with simple code and content.

    Custom Tags
    Custom Tags were introduced in ColdFusion 3, and substantially enhanced in ColdFusion 4. These tags provide a mechanism to execute code without actually including it in your page. A Custom Tag runs in its own scope, so any queries or variables defined within it aren't automatically visible to the calling code. Similarly, data defined in the calling code is not automatically visible to code within the Custom tag.

    Unlike <CFINCLUDE>, Custom Tags have a formal method for passing data to called code. Like any other CFML tag, these tags can take attri-butes, optional parameters passed in the standard NAME="VALUE" format. So while data can indeed be passed to Custom Tags, this isn't an automatic process. You must pass attributes explicitly if they are to be visible with the Custom Tag.

    Notice that I used the word automatic. It is indeed possible to expose calling page data to the Custom Tag by using the CALLER scope. There is even a special scope (introduced in ColdFusion 4.01) called REQUEST that is automatically shared between calling pages and Custom Tags. But CALLER and REQUEST aren't the default scopes, and using them is your choice. In other words, Custom Tags provide data protection unless you explicitly choose to violate it. (The exception is read-only data, like CGI variables, URL parameters or form fields, which are automatically visible to code within Custom Tags because there's no risk in overwriting them anyway.)

    And there's more. Custom Tags can be paired (a start and an end tag), and they can also be nested (parent and child tags). This makes it possible to write extremely powerful (and complex) reusable components.

    All this extra power is a good thing, but it's also expensive. ColdFusion has to do a lot more work to execute Custom Tags while providing the protection of separate scopes, and that translates into slower execution time. Custom Tags don't execute as quickly as <CFINCLUDE>. That's just the way it is, and it's a reality to consider when using them. That doesn't mean you shouldn't use Custom Tags. The slight performance degradation is a small price to pay for all that flexibility and power, but at the same time, if something can be included with <CFINCLUDE>, calling it as a Custom Tag is a waste of resources.

    When should (and shouldn't) Custom Tags be used? Well, if all you're doing is including a file of JavaScript functions (like the example above), or embedding a common header or footer, or including a set of CSS styles, you should be using <CFINCLUDE>. But if you're writing reusable components, files that contain lots of programmatic and conditional code, components that need to create and manipulate data without the fear of overwriting calling data, code that needs to process runtime-specified attributes, then you should definitely be writing Custom Tags.

    The code I referred to above-the code that creates the page layout, including styles and menus with correctly highlighted sections-that code is written as a Custom Tag. Here's a snippet showing how that code is called:

    <!--- Page settings --->
    <CFSCRIPT>
    page=StructNew();
    page.title='Forta.com - About Me';
    page.section='about';
    ...
    </CFSCRIPT>

    <!--- Page template --->
    <CFMODULE TEMPLATE="../common/SitePage.cfm"
    PAGE_TITLE="#page.title#"
    SECTION_ID="#page.section#">
    ...
    </CFMODULE>

    First I use a <CFSCRIPT> block to define the variables needed in this page. I could have used <CFSET> tags to do this, but when writing long lists of variables (it is a long list; this is just a small part of it), <CFSCRIPT> is quite a bit cleaner. Then the SitePage.cfm file (the actual Custom Tag file containing all the page layout code) is called using <CFMODULE>. I could have called this page as <CF_SitePage> too (the more common form of Custom Tag use), but <CFMODULE> is a little quicker. And this is just the start of it. Between those <CFMODULE> tags are calls to additional Custom Tags, tags that define navigation bars, tags that create content body boxes - and others too.

    To summarize, Custom Tags are powerful and flexible, and are ideally suited for use with more complex reusable code and components, especially components that are runtime configurable via passed attri-butes.

    Application Scope Data
    There's one additional and related topic to discuss - the reuse of data (as opposed to code). I am a firm believer in not hard-coding anything in your code. Even data sources, for example, should be passed to <CFQUERY> as a previously defined variable rather than as a string containing the actual datasource name. This way, if a data source needs to change (perhaps when migrating the application from development to staging server), a single variable needs to change, not every <CFQUERY> tag.

    The simplest way to do this is to add code similar to the following to your APPLICATION.CFM:

    <CFSET dsn="forta">

    Then you could refer to DATASOURCE="#dsn#" in every <CFQUERY>, and just change that single variable to change all <CFQUERY> tags.

    Listing 1 is a snippet out of my new APPLICATION.CFM. This code defines a global structure named APPLICATION.settings within my application's APPLICATION scope. By surrounding the code within the statement <CFIF NOT IsDefined("APPLICATION.settings")>, I can ensure that these variables are initialized only once. Of course, because these variables are shared across the entire application, a <CFLOCK> must be used to prevent concurrency issues, but that lock will be processed only once, the first time any page in the application is requested.

    Again, I use a <CFSCRIPT> block for simplicity's sake and define a single structure for all my global variables. This reduces the risk of creating naming conflicts or mistakenly overwriting variables. The code here defines my data source as APPLICATION.settings.dsn, then creates an array of structures (within the global structure) for menu options - and does a whole lot more not shown in the listing. Now my <CFQUERY> tags can simply use the following for the data source:

    DATASOURCE="APPLICATION.settings.dsn"

    This global application structure isn't used just for data sources and menus. For example, I load color and stylesheet information as well as lists of states and provinces into it. Anything that doesn't change (or changes infrequently enough that the structure can be updated as needed) can, and should, go here. (I know of some very high visibility e-commerce sites that load entire product catalogs into structures like these, thereby eliminating lots of database access.)

    Summary
    Writing applications with code (and data) reuse takes a little extra planning upfront. But the effort is worth it. You'll end up with better quality, and less buggy and far more manageable code as well as far more scalable code - code you'll be much happier with and proud of.

    So it turns out that recycling really is good for the environment. The development environment, that is.

    About Ben Forta
    Ben Forta is Adobe's evangelist for the ColdFusion product line. He is the author of several books.

  • CFDJ LATEST STORIES . . .
    Two of the biggest launches in Rich Internet Application history took place in 2007/2008 when Adobe launched AIR 1.0 in February '08 and Microsoft launched Silverlight (September '07). At the 6th International AJAXWorld RIA Conference & Expo in October SYS-CON Events is delighted to be...
    Red Hat CTO Brian Stevens, Citrix CTO Simon Crosby, Egenera CTO Pete Manca, Allen Stewart, Group Manager, Windows Virtualization at Microsoft, and Brian Duckering, Sr. Director of Products and Alliances at Symantec were the top industry executives who joined Jeremy Geelan in the 4th Fl...
    Mike Neil is general manager for virtualization strategy in the Windows Server Division at Microsoft. Mike is focused on the delivery of the Windows virtualization technology, including Windows Server 2008 Hyper-V, Microsoft Hyper-V Server and Virtual PC 2007. Mike also directs the tec...
    SQL Injection attacks are one of the easiest ways to hack into a website. One recent hack, using a script from verynx.cn, involves injecting sql into a web form that then appends some JavaScript code into fields in a database that then gets executed on the client side when a user views...
    Recursion Software released a private beta version of their Voyager mobile platform, with powerful interoperability for Android, Microsoft .NET and Compact Framework (CF), all Java editions (JME CDC, JSE and JEE), and more than 15 embedded operating systems. The Voyager platform is a p...
    2008 is going to be an important year for Rich Internet Applications. Most organizations are delivering or planning to deliver Rich Internet Applications; however, at the same time, most IT managers are facing a dilemma: which Rich Internet Application technology and platform to use? T...
    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