A reader asks:
Ray, I'm royally confused between CFINCLUDE vs CFMODULE. When is it best to use one over the other?Simple... neither! I probably need to back a bit and talk about when you would want to use either, and when you would want to use one over the other.
Both <cfinclude> and <cfmodule> allow for code encapsulation. What do we mean by code encapsulation? Imagine this scenario: You are in the business of selling light sabers. When a person shops, you have a page where you display their shopping cart. The total price of their order is the total of all the line items (each unique lightsaber) multiplied by their unit prices. (The double-sided ones cost more ya know.)
Now let's say your boss wants you to offer a volume discount. Any order with 10 or more lightsabers will have a 10% discount. So now you have a problem. You have code to calculate the price in multiple places - the cart - during checkout - and in the confirmation. This is a perfect example of when encapsulation would be useful. If the business logic for calculating the price for a set of products was in one place - you would only need to update the code once. If your boss changes the 10% to 9%, it wouldn't be a big deal.
So obviously this is just one simple example. Many more exist. ColdFusion offers different types of encapsulation. At the last few MAX conferences I spoke on this topic. As a very basic summary - the types of encapsulation in ColdFusion include: Includes, Custom Tags, User Defined Functions (UDFs) and ColdFusion Components (CFCs). All of them have advantages over each other and have their appropriate use - although sometimes it isn't so obvious. However - let's focus on your question of comparing an include to a custom tag.
When you use <cfinclude>, the file that is included acts as if it were in the document itself. You can imagine ColdFusion simply copying the lines into the file when it is executed. This is important. Consider the following code:
<cfset name="Jacob Camden">
<cfinclude template="logic.cfm">
<cfoutput>#name#</cfoutput>
Do you know what this code will print? Most likely it will be Jacob Camden. But the code inside of logic.cfm could very easily change the value of the name variable. You may say, "Hey, I wrote logic.cfm, I know what's in there. It's safe." But are you sure you will always be working on the file? Are you sure you will be the only person working on the project in general?
On the other hand - when you work with custom tags, the code inside the tag is run within it's own scope. You do not have to worry about the tag accidentally overwriting your variables. (Technically it is possible - but will not happen unless the tag is poorly written.) This "black boxing" does come at a cost of speed. I know some of my readers will comment on this. However - in my experience - I have never seen the use of custom tags have any real impact on a site. I've only seen it happen when a) the code itself was bad, not the fact that it was a custom tag, or b) way too many custom tags were used (think Spectra, if anyone remembers it).
So why use <cfinclude> at all? The <cfinclude> tag is good for including things like static variables. So for example - you may have a configuration file that is simply a set of <cfset> tags. Another example is including a header and footer. (Although I typically use a wrapped custom tag for that.)
Archived Comments
Why would you use a custom tag for header/footer display as opposed to a cfc with functions with output set to "true"? This question comes up where I work every once in a while where I work, and I'ver never had a reason for one versus another.
Terrence,
This is of course a debatable answer, but many folks (including me) believe that a CFC should include logic only (I never set output to true except for debugging during development). Instead it is preferred to treat the CFC like a black box where you put in values it requires and it outputs values you expect. Then you can apply said values to your output pages (cfm files).
There's no "rule" that says you have to follow this method and I'm not a stickler to those who wish to output within CFCs (as long as they don't work for me ;)). One of the nice things about ColdFusion is that you can code the way you want most of the time (like outputting within CFCs) even if its not the favored method.
-----
Hehe. I expect to get hate messages from the hard core OO zealots (or strongly-typed framework users) who shun away from outputting within CFCs. Just please remember that I'm on your side :). I'm just acknowledging the fact that ColdFusion lets the programmer be pretty versatile.
Terrance, I think Jeff answered it. Also - something that includes, UDFs, and CFC's can't do is wrap. So my templates look like this normally:
<cfmodule template="/tags/layout.cfm" title="Home">
content here
</cfmodule>
I'm speaking on this sort of thing at CFUnited. ( And CFObjective ).
One other thing that cfmodule can do (that includes, UDFs, and CFCs can't) is nested tags.
Hey Jeff, a recommendation. Nested tags are one of those things that I tell people are cool - but rarely used. One good example of a nested tag though is a DataTable custom tag I wrote. The purpose is to create a grid of data with pagination and sorting built in. I use nested tags to allow you to define columns. If you download Galleon you can see an example of that. I find it to be a good example. (Although I think the Galleon version is modded quite a bit.) Anyway - just a suggestion. :)
Okay so we're talking philosophic/stylistic concerns versus any performance reasons. That makes sense to me.
Ray, I'm not actually sure what you were suggesting. ;)
I've never needed to use a nested tag. But, if needed, it is not a functionality you can get from UDFs or CFCs.
I think encapsulation can be used in many different ways that style and philosophy will keep a good blog alive. However, if the scope (not variable scope) of the encapsulation is trying to achieve too much, then the style/philosophy needs to go through the scientific method again. Planning up front for precise functionality of an encapsulated piece of code is possible, but usually encapsulation is a refinement process.
Sorry Jeff - I thought you meant you were speaking on CFCs, UDFs, and Custom Tags together.
re-reading my initial post, I actually should have said
"One other thing that CUSTOM TAGS can do (that includes, UDFs, and CFCs can't) is nested tags."
I apparently had a brain misfire that resulted in the typo. ;)
One advantage of <cffunctions> over Includes and Modules is the significant savings in object instantiation. ColdFusion compiles each of your .cfm files into an object, which it then passes data back and forth to. When you <cfinclude> a template, or when you use <cfmodule> to pull a template in, ColdFusion has to instantiate that Object, pass the data in, process the request, and then destroy the object. One at a time, this isn't a big deal, but I once worked someplace that used some very table-heavy data views, and we'd often see code like this:
<table>
<cfinclude template="tableHead.cfm">
<cfloop query="foo">
<cfinclude template="tableRow.cfm">
</cfloop>
</table>
.
.
.
By converting the tableRow.cfm into a <cffunction> we were able to trim about a half a second from queries that were returning more than a hundred or so lines.
Lesson I learned from this: if you're working in tight loops, don't use <cfinclude>. It'll cost you a lot of time.
I've been using cfc's for my layouts and I really feel comfortable doin' it that way.
showHeader(), showLeftMenu(), showFooter(), listProducts(), etc.
It's really versatile and feels pretty darn natural if you love cfc's.
As for the output or no output from a cfc .... Heck, It's doesn't bother me a bit! :)
my two cents,
Will
Adam,
I don't think you said what you meant to say. How could moving a query out of an include and into a function trim off time from the query? I think you meant that moving the code from an include to a function made the CF code bad.
I'll also add, to no one in particular, that many people who use CFCs will create the CFC instance once (using CreateObject or cfobject), and then just call multiple methods off that CFC.
Will,
Normally I'd side with Jeff C when he said that CFCs are best for business logic, however I do not have a problem with CFCs designed strictly for presentation logic. I only have a problem with CFCs that mix presentation and business logic.
yep, gotcha.
For products I'll have a productDAO.cfc, then a productDisplay.cfc. The template calls productDAO for getProducts(), then calls productDisplay.cfc, passing in the getProducts query as an argument.
I also wrap the presentation code around the display call, keeping look'n'feel out of the cfc. And/or pass in a class as an argument.
Will
Jeff,
I actually meant what I said: by moving the code that was repeated out of an include, and into a function, I realized significant speed gains. I think you might have misunderstood which part of the code was better off in functions though: the "TableRow.cfm" was the one that was translated into a function for the most significant speed gains. Basically, <cfincluding> a file incurrs a lot more overhead than calling a <cffunction>, whether it's in a CFC or just part of a function library.
As to mixing logic and display, a lot of my history comes from the PHP/Smarty world, so I tend to think that the logic should be almost entirely contained in the CFC files, and the display should be contained in the CFM files, but I admit it's purely a preferential thing.