<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3532843</id><updated>2011-04-21T16:29:43.923-07:00</updated><title type='text'>Tea Boy</title><subtitle type='html'>Nothing but darjeeling will do.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://spikefu.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>20</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3532843.post-93582645</id><published>2003-05-01T00:17:00.000-07:00</published><updated>2003-05-01T00:18:26.000-07:00</updated><title type='text'></title><content type='html'>kwfu: ['relocated']&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;I've moved!&lt;/h3&gt;&lt;br /&gt;I've finally got round to setting up my blog on a CF server. &lt;br /&gt;&lt;br /&gt;The new url is &lt;a href="http://www.spike.org.uk/fu/blog.cfm"&gt;http://www.spike.org.uk/fu/blog.cfm&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I'll be gradually moving the content from here to the new site, so update your bookmarks Nachos!&lt;br /&gt;&lt;br /&gt;Spike&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-93582645?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/93582645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/93582645'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2003_04_27_archive.html#93582645' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-92360669</id><published>2003-04-10T07:19:00.000-07:00</published><updated>2003-04-10T07:23:04.000-07:00</updated><title type='text'></title><content type='html'>kwfu: ['farcry','cms']&lt;br /&gt;&lt;br /&gt;Just finished a couple of hectic days working on the next release of &lt;a href="http://farcry.daemon.com.au"&gt;FarCry&lt;/a&gt;. If you don't know what &lt;a href="http://farcry.daemon.com.au"&gt;FarCry&lt;/a&gt; is, I suggest you get on down to the website and have a look at it.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://farcry.daemon.com.au"&gt;http://farcry.daemon.com.au&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It's a complete enterprise content management system built in CFMX built by the guys at &lt;a href="http://www.daemon.com.au"&gt;Daemon&lt;/a&gt; in Sydney Australia. It supports many of the things that were available in Spectra, but it's FREE!!!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;100% Open source goodness!&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;You can go download it from &lt;a href="http://farcry.daemon.com.au/index.cfm?objectid=FAE99A2D-D0B7-4CD6-F9A949677D1A0A86"&gt;here&lt;/a&gt;, or you can go and look at the demo site &lt;a href="http://demo.daemon.com.au"&gt;here&lt;/a&gt;. If you do go to the demo site, make sure you login and check out the admin interface. That's the same interface you get from a fresh install.&lt;br /&gt;&lt;br /&gt;If you're currently running Spectra and are looking for something to migrate to, I'd definitely suggest you download it and take a look. It's already been used to migrate a few sites in Australia. They aren't small sites either. Roche Pharmaceuticals Asia Pacific intranet and &lt;a href="http://www.integral.com.au"&gt;Integral Energy&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It's currently being labelled as version 1, but a lot of the code's been in use for the last 4 years in various different projects.&lt;br /&gt;&lt;br /&gt;Definitely worth a look&lt;br /&gt;&lt;br /&gt;Spike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-92360669?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/92360669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/92360669'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2003_04_06_archive.html#92360669' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-89810520</id><published>2003-02-26T18:14:00.000-08:00</published><updated>2003-03-06T00:53:17.000-08:00</updated><title type='text'></title><content type='html'>kwfu: ['cfproperty','cfc']&lt;br /&gt;&lt;br /&gt;A long time ago I promised to put some more info in my blog about CFCs. Well, now I'm coming good on that promise.&lt;br /&gt;&lt;br /&gt;You may be wondering exactly what use the &amp;lt;cfproperty&amp;gt; tag is. Well, there are at least 2 uses for it. I was intending to put them both into this post, but I got a bit overexuberant with the examples, so I'll split it into 2 blog posts. &lt;br /&gt;&lt;br /&gt;&lt;h4&gt;1. Providing static data for component instances&lt;/h4&gt;&lt;br /&gt;When you create a component instance, you can use the getMetaData() function to retrieve all the data that is defined in the &amp;lt;cfproperty&amp;gt; tag. You also get information about the attributes in the &amp;lt;cfcomponent&amp;gt; and &amp;lt;cffunction&amp;gt; tags, but I digress. As an example:&lt;br /&gt;&lt;br /&gt;Say you have employee.cfc that contains employee information.&lt;br /&gt;&lt;br /&gt;&amp;lt;cfcomponent displayname="employee"&amp;gt;&lt;br /&gt;	&amp;lt;cfproperty name="minage" type="numeric" value="18"&amp;gt;&lt;br /&gt;	&amp;lt;cfproperty name="maxage" type="numeric" value="65"&amp;gt;&lt;br /&gt;	&lt;br /&gt;	&amp;lt;cffunction name="getEmployee" access="public"&amp;gt;&lt;br /&gt;		&amp;lt;!--- Code to get employee info goes here ---&amp;gt;&lt;br /&gt;	&amp;lt;/cffunction&amp;gt;&lt;br /&gt;	&lt;br /&gt;	&amp;lt;!--- More methods go here ---&amp;gt;&lt;br /&gt;	&lt;br /&gt;&amp;lt;/cfcomponent&amp;gt;&lt;br /&gt;&lt;br /&gt;You can create an instance of this component as follows:&lt;br /&gt;&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;  emp = createObject('component','employee');&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;br /&gt;You can then retrieve and view the data defined in the cfproperty tags like this:&lt;br /&gt;&lt;br /&gt;&amp;lt;cfdump var="#getMetaData(emp)#"&amp;gt;&lt;br /&gt;&lt;br /&gt;If you look at the output from the &amp;lt;cfdump&amp;gt; tag, you will notice that it contains all the attributes of all the &amp;lt;cfcomponent&amp;gt;, ;&amp;lt;cfproperty&amp;gt; and &amp;lt;cffunction&amp;gt; tags in the component. This is true even if you define your own attributes in those tags. This can be particularly useful for defining information about how component instances and properties of those instances should be treated. You could, for example, create an editHandler attribute for the &amp;lt;cfcomponent&amp;gt; tag that defined what file should be used to edit instances of that component. You might also use this to determine default values for the properties of your component instance. The &amp;lt;cfproperty&amp;gt; tag will not create the properties for you, but you can use the metadata to initialize them yourself. &lt;br /&gt;&lt;br /&gt;Something like this:&lt;br /&gt;&lt;br /&gt;&amp;lt;cfcomponent displayname="employee"&amp;gt;&lt;br /&gt;	&amp;lt;cfproperty name="minage" type="numeric" value="18"&amp;gt;&lt;br /&gt;	&amp;lt;cfproperty name="maxage" type="numeric" value="65"&amp;gt;&lt;br /&gt;	&lt;br /&gt;	&amp;lt;cfscript&amp;gt;&lt;br /&gt;		init();&lt;br /&gt;	&amp;lt;/cfscript&amp;gt;&lt;br /&gt;	&lt;br /&gt;	&amp;lt;cffunction name="init" access="private"&amp;gt;&lt;br /&gt;		&amp;lt;cfset md = getMetaData(this)&amp;gt;&lt;br /&gt;		&amp;lt;cfloop from="1" to="#arrayLen(md.properties)#" index="i"&amp;gt;&lt;br /&gt;			&amp;lt;cfset this[md.properties[i].name] = md.properties[i].value&amp;gt;&lt;br /&gt;		&amp;lt;/cfloop&amp;gt;&lt;br /&gt;	&amp;lt;/cffunction&amp;gt;&lt;br /&gt;	&lt;br /&gt;	&amp;lt;!--- More methods go here ---&amp;gt;&lt;br /&gt;	&lt;br /&gt;&amp;lt;/cfcomponent&amp;gt;&lt;br /&gt;&lt;br /&gt;The following code will allow you to see how this works:&lt;br /&gt;&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;emp = createObject('component','employee');&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&amp;lt;cfdump var="#emp#"&amp;gt;&lt;br /&gt;&lt;br /&gt;This is a pretty useful feature, but you need to be careful about the time that getMetaData() can take to return data in complex component hierarchies. You should also be aware that you could quite easily do this instead:&lt;br /&gt;&lt;br /&gt;&amp;lt;cfcomponent displayname="employee"&amp;gt;&lt;br /&gt;	&lt;br /&gt;	&amp;lt;cfscript&amp;gt;&lt;br /&gt;		init();&lt;br /&gt;	&amp;lt;/cfscript&amp;gt;&lt;br /&gt;	&lt;br /&gt;	&amp;lt;cffunction name="init" access="private"&amp;gt;&lt;br /&gt;		&amp;lt;cfset md = getMetaData(this)&amp;gt;&lt;br /&gt;		&amp;lt;cfset this.minage = 18&amp;gt;&lt;br /&gt;		&amp;lt;cfset this.maxage = 65&amp;gt;&lt;br /&gt;	&amp;lt;/cffunction&amp;gt;&lt;br /&gt;	&lt;br /&gt;	&amp;lt;!--- More methods go here ---&amp;gt;&lt;br /&gt;	&lt;br /&gt;&amp;lt;/cfcomponent&amp;gt;&lt;br /&gt;&lt;br /&gt;The downside of this way of doing things is that when you use the component browser you will not see what the default values will be in the documentation code.&lt;br /&gt;&lt;br /&gt;Hopefully all that made sense, next time &amp;lt;cfproperty&amp;gt; and webservices.&lt;br /&gt;&lt;br /&gt;Spike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-89810520?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/89810520'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/89810520'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2003_02_23_archive.html#89810520' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-89624351</id><published>2003-02-23T16:58:00.000-08:00</published><updated>2003-02-23T16:58:31.000-08:00</updated><title type='text'></title><content type='html'>kwfu: ['travelling']&lt;br /&gt;&lt;br /&gt;Well, it's been a long time since my last post and a lot of things have happened in that time...&lt;br /&gt;&lt;br /&gt;I've left my job in the Netherlands, been ski-ing in the French Alps for Christmas and New Year, spent a few weeks travelling across Canada, and got to Australia in time to speak at &lt;a href="http://mxdu.com"&gt;MXDU&lt;/a&gt; in Sydney on 19th and 20th of February. The conference was great and many thanks go out to the speakers and organizers who made it as good as it was. Special thanks to Geoff Bowers and the team from Daemon who had all the speakers over for a good ole aussie barbie on Friday night.&lt;br /&gt;&lt;br /&gt;I'm planning on hanging around in Australia for a few months before moving on to Asia for a while. After that, who knows, but it might well involve getting in touch with the Australian authorities for a slightly more permanent visa.&lt;br /&gt;&lt;br /&gt;Spike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-89624351?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/89624351'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/89624351'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2003_02_23_archive.html#89624351' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-83869515</id><published>2002-11-01T03:45:00.000-08:00</published><updated>2002-11-01T04:38:34.000-08:00</updated><title type='text'></title><content type='html'>kwfu: ['english','OT']&lt;br /&gt;I got this in an email from an old college friend of mine today:&lt;br /&gt;&lt;br /&gt;*snip*&lt;br /&gt;We have a logo that says "Research And Development", but the boss wanted to put a hyphen between the words Research and And and And and Development in my Research-And-Development logo.&lt;br /&gt;&lt;br /&gt;I said that the sentence 'I want to put a hyphen between the words Research and And and And and Development in my Research-And-Development logo' would have been clearer if quotation marks had been placed before Research, and between Research and and, and and and And, and And and and, and and and And, and And and and, and and and Development, as well as after Development!&lt;br /&gt;*snip*&lt;br /&gt;&lt;br /&gt;Good old english&lt;br /&gt;&lt;br /&gt;Spike&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-83869515?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/83869515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/83869515'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2002_10_27_archive.html#83869515' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-83123674</id><published>2002-10-17T09:34:00.000-07:00</published><updated>2002-10-17T09:34:43.960-07:00</updated><title type='text'></title><content type='html'>kwfu: ['UI','architecture','slashdot']&lt;br /&gt;&lt;br /&gt;An interesting &lt;a href="http://ask.slashdot.org/article.pl?sid=02/10/15/2352256&amp;mode=thread&amp;tid=156="&gt;thread about UI architecture&lt;/a&gt; popped up on slashdot today. Qute a few of the responses don't answer the question, but a lot of them should be interesting to people building complex systems with CFMX and Flash.&lt;br /&gt;&lt;br /&gt;Spike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-83123674?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/83123674'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/83123674'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2002_10_13_archive.html#83123674' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-83058404</id><published>2002-10-16T05:43:00.000-07:00</published><updated>2002-10-16T05:43:45.773-07:00</updated><title type='text'></title><content type='html'>kwfu: ['CF','Link','advanced']&lt;br /&gt;Stumbled across &lt;a href="http://www.macromedia.com/support/coldfusion/adv_development.html"&gt;this&lt;/a&gt; page on the Macromedia website today. Very useful set of articles on Advanced ColdFusion development all in the same place.&lt;br /&gt;&lt;br /&gt;Spike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-83058404?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/83058404'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/83058404'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2002_10_13_archive.html#83058404' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-83053311</id><published>2002-10-16T01:10:00.000-07:00</published><updated>2002-10-16T07:13:19.000-07:00</updated><title type='text'></title><content type='html'>kwfu: ['super','cfc','extends']&lt;br /&gt;&lt;br /&gt;Continuing the cfc theme of the last couple of weeks, here's a little trick that might be useful to some people.&lt;br /&gt;&lt;br /&gt;Suppose we have a cfc called &lt;b&gt;base.cfc&lt;/b&gt; that has a method called &lt;i&gt;init()&lt;/i&gt;. The purpose of &lt;i&gt;init()&lt;/i&gt; is to set up some initial data and parameters for the component. The use of &lt;i&gt;init()&lt;/i&gt; to initialize an object is common in the Java world, so it makes some sort of sense to follow the same idea in components.&lt;br /&gt;&lt;br /&gt;Now, suppose we have a cfc called &lt;b&gt;extends.cfc&lt;/b&gt; that extends &lt;b&gt;base.cfc&lt;/b&gt;. &lt;b&gt;Extends.cfc&lt;/b&gt; also has a method called &lt;i&gt;init()&lt;/i&gt; to initialize it's data. This could cause a problem because &lt;i&gt;extends.init()&lt;/i&gt; will override the &lt;i&gt;init()&lt;/i&gt; function declared in &lt;b&gt;base.cfc&lt;/b&gt;. In the Java world, we would use the &lt;b&gt;super&lt;/b&gt; keyword to access the &lt;i&gt;init()&lt;/i&gt; method in the parent component. Unfortunately the &lt;b&gt;super&lt;/b&gt; keyword doesn't work with components so there isn't an easy way to call a method that has been overridden by an extending component.&lt;br /&gt;&lt;br /&gt;The little trick that I'm about to show you relies on the fact that you can attach methods to a component after it has been instantiated. If the data in the un-named scope is put into a structure, you can easily access all the data in that structure as long as you know what it is called. For the purposes of this example I'm going to use 'protected' as the name of my structure.&lt;br /&gt;&lt;br /&gt;Take the following code:&lt;br /&gt;&lt;br /&gt;base.cfc&lt;br /&gt;&amp;lt;cfcomponent hint="base component"&amp;gt;	&lt;br /&gt;	&lt;br /&gt;	&lt;br /&gt;	&amp;lt;cffunction name="init"&amp;gt;&lt;br /&gt;		&amp;lt;!--- Create a structure called protected in the un-named scope.&lt;br /&gt;		This structure will act as a pseudo scope for component data ---&amp;gt;&lt;br /&gt;		&amp;lt;cfset protected = structNew()&amp;gt;&lt;br /&gt;		&amp;lt;!--- Add some data to the protected structure ---&amp;gt;&lt;br /&gt;		&amp;lt;cfset protected.a = "value of a"&amp;gt;&lt;br /&gt;		&amp;lt;cfset protected.b = "value of b"&amp;gt;&lt;br /&gt;	&amp;lt;/cffunction&amp;gt;&lt;br /&gt;	&lt;br /&gt;	&lt;br /&gt;&amp;lt;/cfcomponent&amp;gt;&lt;br /&gt;&lt;br /&gt;Extends.cfc&lt;br /&gt;&amp;lt;cfcomponent hint="extending component" extends="base"&amp;gt;		&lt;br /&gt;	&lt;br /&gt;	&lt;br /&gt;	&lt;br /&gt;	&amp;lt;!--- This function is used to get the data from the super object.&lt;br /&gt;	It could be attached to any component instance to access the data in the 'protected' scope ---&amp;gt;&lt;br /&gt;	&amp;lt;cffunction name="getProtected" access="private"&amp;gt;&lt;br /&gt;		&amp;lt;cfif isDefined('protected')&amp;gt;&lt;br /&gt;			&amp;lt;cfreturn protected&amp;gt;&lt;br /&gt;		&amp;lt;/cfif&amp;gt;&lt;br /&gt;	&amp;lt;/cffunction&amp;gt;&lt;br /&gt;	&lt;br /&gt;	&amp;lt;cffunction name="init"&amp;gt;&lt;br /&gt;		&amp;lt;!--- Create a structure called protected in the un-named scope.&lt;br /&gt;		This structure will act as a pseudo scope for component data ---&amp;gt;&lt;br /&gt;		&amp;lt;cfset protected = structNew()&amp;gt;&lt;br /&gt;		&lt;br /&gt;		&amp;lt;!--- Create an object that points to the ancestor of this component ---&amp;gt;&lt;br /&gt;		&amp;lt;cfset super = createObject('component','base')&amp;gt;&lt;br /&gt;		&lt;br /&gt;		&amp;lt;!--- Attach the getProtected() method to our super component ---&amp;gt;&lt;br /&gt;		&amp;lt;cfset super.getProtected = getProtected&amp;gt;&lt;br /&gt;		&lt;br /&gt;		&amp;lt;!--- Fire the init() method of the ancestor ---&amp;gt;&lt;br /&gt;		&amp;lt;cfset super.init()&amp;gt;&lt;br /&gt;		&lt;br /&gt;		&amp;lt;!--- Make the private data from the ancestor component available to this component ---&amp;gt;&lt;br /&gt;		&amp;lt;cfset super.protected = super.getProtected()&amp;gt;&lt;br /&gt;	&lt;br /&gt;		&amp;lt;!--- Add the protected data from the ancestor to this component's protected structure ---&amp;gt;&lt;br /&gt;		&amp;lt;cfset structAppend(protected,super.protected,false)&amp;gt;&lt;br /&gt;		&lt;br /&gt;		&amp;lt;!--- Add some data to the local protected structure ---&amp;gt;&lt;br /&gt;		&amp;lt;cfset protected.c = "value of c"&amp;gt;&lt;br /&gt;		&amp;lt;cfset protected.d = "value of d"&amp;gt;&lt;br /&gt;	&amp;lt;/cffunction&amp;gt;&lt;br /&gt;	&lt;br /&gt;	&amp;lt;!--- This function returns the protected data from the current component instance ---&amp;gt;&lt;br /&gt;	&amp;lt;cffunction name="getAll"&amp;gt;&lt;br /&gt;		&amp;lt;cfreturn protected&amp;gt;&lt;br /&gt;	&amp;lt;/cffunction&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/cfcomponent&amp;gt;&lt;br /&gt;&lt;br /&gt;invoke.cfm&lt;br /&gt;&amp;lt;cfset obj = createObject('component','extends')&amp;gt;&lt;br /&gt;&amp;lt;cfset obj.init()&amp;gt;&lt;br /&gt;&amp;lt;cfdump var="#obj.getAll()#"&amp;gt;&lt;br /&gt;&lt;br /&gt;Now we've managed to create the functionality of a &lt;i&gt;super.init()&lt;/i&gt; in a CFC. &lt;br /&gt;&lt;br /&gt;The caveat to this is that we're not really duplicating what you get with the &lt;b&gt;super&lt;/b&gt; keyword in Java. The important difference is that in Java we wouldn't be creating a separate object instance to access the method declared in the parent, the method would be running from within the context of the extending component. This is important if the method relies in any way on the data that exists in the instance. &lt;br /&gt;&lt;br /&gt;For example: &lt;br /&gt;&lt;br /&gt;You have a generic shopping cart component called &lt;b&gt;cart.cfc&lt;/b&gt; that has a method called &lt;i&gt;sum()&lt;/i&gt; that calculates the total cost for the items in a cart. Say &lt;b&gt;bargain.cfc&lt;/b&gt; extends &lt;b&gt;cart.cfc&lt;/b&gt; and has a method called &lt;i&gt;sum()&lt;/i&gt; that calls the &lt;i&gt;sum()&lt;/i&gt; method in the &lt;b&gt;cart.cfc&lt;/b&gt;, then applies a discount of x% to the result. If the cart items are stored in the un-named scope of &lt;b&gt;bargain.cfc&lt;/b&gt;, the &lt;i&gt;sum()&lt;/i&gt; method in &lt;b&gt;cart.cfc&lt;/b&gt; will not have access to them, and so will most likely return &lt;b&gt;ZERO&lt;/b&gt; as the total cost for the items in the cart!&lt;br /&gt;&lt;br /&gt;Clearly this is not desireable, so although we can get some of the way to emulating &lt;b&gt;super&lt;/b&gt; in Java, it doesn't get us all the way there.&lt;br /&gt;&lt;br /&gt;Spike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-83053311?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/83053311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/83053311'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2002_10_13_archive.html#83053311' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-82969900</id><published>2002-10-14T09:35:00.000-07:00</published><updated>2002-10-14T10:01:05.000-07:00</updated><title type='text'></title><content type='html'>kwfu: ['cfc']&lt;br /&gt;A little update to the 'this' vs 'un-named' scope discussion from last week.&lt;br /&gt;&lt;br /&gt;Sean Corfield posted this nice little snippet on a mailing list:&lt;br /&gt;&lt;br /&gt;test.cfc:&lt;br /&gt;	&amp;lt;cfcomponent&amp;gt;&lt;br /&gt;		&amp;lt;cfset bar = 42/&amp;gt;&lt;br /&gt;	&amp;lt;/cfcomponent&amp;gt;&lt;br /&gt;&lt;br /&gt;invoke.cfm:&lt;br /&gt;	&amp;lt;cfscript&amp;gt;&lt;br /&gt;	function foo() {&lt;br /&gt;		return bar; // not this.bar!&lt;br /&gt;	}&lt;br /&gt;	// create an instance of the component&lt;br /&gt;	x = createObject("component","test");&lt;br /&gt;	// attach the function to the component&lt;br /&gt;	x.abc = foo;&lt;br /&gt;	// Create a variable to hold the return value of the attached method&lt;br /&gt;	y = x.abc();&lt;br /&gt;	&amp;lt;/cfscript&amp;gt;&lt;br /&gt;	&amp;lt;--- Output the results ---&amp;gt;&lt;br /&gt;	&amp;lt;cfoutput&amp;gt;&lt;br /&gt;	&amp;lt;cfdump label="x" var="#x#"/&amp;gt;&lt;br /&gt;	y = x.abc() returned #y#&lt;br /&gt;	&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;"You can add UDFs to component instances and manipulate them &lt;br /&gt;however you want. Because CFMX resolves names at runtime - late binding &lt;br /&gt;- not at compile time, you can add code after the component has been &lt;br /&gt;written that does 'Bad Things(tm)' with the component...&lt;br /&gt;&lt;br /&gt;This is true of any language that does dynamic binding of variables &lt;br /&gt;(until the compiler is specified to add binding restrictions at &lt;br /&gt;compile-time)."&lt;br /&gt;&lt;br /&gt;It turns out that not only can you attach a method to a component to access the variables in the un-named scope. You can also call methods with an access attribute of private...&lt;br /&gt;&lt;br /&gt;test.cfc&lt;br /&gt;&amp;lt;cfcomponent&amp;gt;&lt;br /&gt;	&amp;lt;cfset bar = 42/&amp;gt;&lt;br /&gt;	&amp;lt;--- Create a function that is private --- &amp;gt;&lt;br /&gt;	&amp;lt;cffunction name="hideme" access="private"&amp;gt;&lt;br /&gt;		&amp;lt;cfreturn "You're kidding, right?"&amp;gt;&lt;br /&gt;	&amp;lt;/cffunction&amp;gt;&lt;br /&gt;&amp;lt;/cfcomponent&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;invoke.cfm&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;&lt;br /&gt;	function foo() {&lt;br /&gt;		return bar; // not this.bar!&lt;br /&gt;	}&lt;br /&gt;	// Create a function that calls the hideme() method.&lt;br /&gt;	function bar() {&lt;br /&gt;		return	hideme();&lt;br /&gt;	}&lt;br /&gt;	&lt;br /&gt;	x = createObject("component","test");&lt;br /&gt;	// Attach the method to return a hidden property&lt;br /&gt;	x.abc = foo;&lt;br /&gt;	// Attach the method to call a hidden function&lt;br /&gt;	x.def = bar;&lt;br /&gt;	// Call the functions we just attached and set variables equal to their return values.&lt;br /&gt;	y = x.abc();&lt;br /&gt;	z = x.def();&lt;br /&gt;&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfdump label="x" var="#x#"/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;y = x.abc() returned #y#&amp;lt;br&amp;gt;&lt;br /&gt;z = x.def() returned #z#&amp;lt;br&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Interesting stuff.&lt;br /&gt;&lt;br /&gt;Spike&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-82969900?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/82969900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/82969900'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2002_10_13_archive.html#82969900' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-82806520</id><published>2002-10-10T13:12:00.000-07:00</published><updated>2002-10-14T12:23:53.000-07:00</updated><title type='text'></title><content type='html'>kwfu: ['cfc']&lt;br /&gt;There's been a lot of talk about CFCs recently, and I thought I'd put a few of my ideas and opinions up here.&lt;br /&gt;&lt;br /&gt;The first topic that seems to have been getting quite a bit of discussion is the use (or not) of the 'this' scope.&lt;br /&gt;&lt;br /&gt;For those of you not familiar with CFCs, the 'this' scope allows you to set a variable from within your component and have it available outside the component.&lt;br /&gt;&lt;br /&gt;e.g.&lt;br /&gt;&lt;br /&gt;test.cfc&lt;br /&gt;&amp;lt;cfcomponent hint="simple test"&amp;gt;&lt;br /&gt;	&amp;lt;cfset this.foo = "bar"&amp;gt;&lt;br /&gt;&amp;lt;/cfcomponent&amp;gt;&lt;br /&gt;&lt;br /&gt;invoke.cfm&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;	obj = createObject('component','test');&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;#obj.foo#&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;br /&gt;An alternative to this is to create a method that will allow you to update the value stored in a property. This might be useful in a situation where you have  a product component that requires that the price is always an integer value.&lt;br /&gt;&lt;br /&gt;e.g.&lt;br /&gt;&lt;br /&gt;product.cfc&lt;br /&gt;&amp;lt;cfcomponent hint="simple product component"&amp;gt;&lt;br /&gt;	&amp;lt;cfset this.name = ""&amp;gt;&lt;br /&gt;	&amp;lt;cfset this.Description = ""&amp;gt;&lt;br /&gt;	&amp;lt;cfset this.price = -1&amp;gt;&lt;br /&gt;	&lt;br /&gt;	&amp;lt;cffunction name="setPrice"&amp;gt;&lt;br /&gt;		&amp;lt;cfargument name="newprice" type="numeric" required="yes"&amp;gt;&lt;br /&gt;		&amp;lt;cfif int(arguments.newprice) NEQ arguments.newprice&amp;gt;&lt;br /&gt;			&amp;lt;cfthrow message="Prices must alwasy be integer values"&amp;gt;&lt;br /&gt;		&amp;lt;cfelse&amp;gt;&lt;br /&gt;			&amp;lt;cfset this.price = arguments.newprice&amp;gt;&lt;br /&gt;		&amp;lt;/cfif&amp;gt;&lt;br /&gt;	&amp;lt;/cffunction&amp;gt;&lt;br /&gt;&amp;lt;/cfcomponent&amp;gt;&lt;br /&gt;&lt;br /&gt;updateprice.cfm&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt; obj = createObject('component','product');&lt;br /&gt; obj.setPrice(10);&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;br /&gt;This works just fine as long as you have control over all the code that is interacting with your component, but it is all too easy for someone to write code like this:&lt;br /&gt;&lt;br /&gt;updateprice.cfm&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt; obj = createObject('component','product');&lt;br /&gt; obj.price = '$10';&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;br /&gt;You don't have any way to stop this from happening...&lt;br /&gt;&lt;br /&gt;Enter the un-named scope in components.&lt;br /&gt;&lt;br /&gt;When you create an un-scoped variable in a component it is created in an un-named scope that is only available to the component and any components that extend it. The fact that components that extend it have access is counter to what the documentation says, and it has been entered as a bug #48483, but that's the way it works at the minute.&lt;br /&gt;&lt;br /&gt;e.g.&lt;br /&gt;test.cfc&lt;br /&gt;&amp;lt;cfcomponent hint="simple test component"&amp;gt;&lt;br /&gt;	&amp;lt;cfset foo = "bar"&amp;gt;&lt;br /&gt;&amp;lt;/cfcomponent&amp;gt;&lt;br /&gt;&lt;br /&gt;invoke.cfm&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;	obj = createObject('component','test');&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;#obj.foo#&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;br /&gt;The code above should throw an error because the variable foo is created in the un-named scope.&lt;br /&gt;&lt;br /&gt;If we want to be able to read and write the foo variable in the component we would need to do something like this:&lt;br /&gt;&lt;br /&gt;test.cfc&lt;br /&gt;&amp;lt;cfcomponent hint="simple test component"&amp;gt;&lt;br /&gt;	&amp;lt;!--- create a default value for foo ---&amp;gt;&lt;br /&gt;	&amp;lt;cfset foo = ""&amp;gt;&lt;br /&gt;	&lt;br /&gt;	&amp;lt;!--- This function allows us to get the value of foo from&lt;br /&gt;	outside the component ---&amp;gt;&lt;br /&gt;	&amp;lt;cffunction name="getFoo"&amp;gt;&lt;br /&gt;		&amp;lt;cfreturn foo&amp;gt;&lt;br /&gt;	&amp;lt;/cffunction&amp;gt;&lt;br /&gt;	&lt;br /&gt;	&amp;lt;!--- This function allows us to change the value of foo ---&amp;gt;&lt;br /&gt;	&amp;lt;cffunction name="setFoo"&amp;gt;&lt;br /&gt;		&amp;lt;cfargument name="newval" type="string" required="yes"&amp;gt;&lt;br /&gt;		&amp;lt;cfset foo = arguments.newval&amp;gt; &lt;br /&gt;	&amp;lt;/cffunction&amp;gt;&lt;br /&gt;	&lt;br /&gt;&amp;lt;/cfcomponent&amp;gt;&lt;br /&gt;&lt;br /&gt;invoke.cfm&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;	obj = createObject('component','test');&lt;br /&gt;	obj.setFoo('bar');&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;#obj.getFoo()#&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;br /&gt;The big advantage of this approach is that you have absolute control of the data from within the component itself. This idea is commonly known as encapsulation and is very important when building complex systems. The reason it is important is that you only have to look inside the component itself to see all the possible ways it's data can be changed.&lt;br /&gt;&lt;br /&gt;The downside of using this system is that you have to write a lot more code to create all your get and set functions, and you are likely to have to think carefully about what those functions will be.&lt;br /&gt;&lt;br /&gt;e.g.&lt;br /&gt;&lt;br /&gt;Suppose you have a much more complex product component that has 50 properties stored in the un-named scope. You probably don't want to have to write 50 get methods to retrieve all the properties out of it, and you probably don't want to put 50 set method calls when you want to update the product, or create a new one. You are most likely going to create methods that will update or retrieve multiple properties at once. You might start with getAll(), getDetails(), and getSummary(). Later you find out that someone needs a specific set of properties for some other reason, and later still a few more methods get added for other groups of properties. Before you know where you are you have a big mess in your component that is very hard to maintain.&lt;br /&gt;&lt;br /&gt;You can offset the potential for these problems if you set out from the beginning to plan the application in the same way as many people have been doing for years in the Object Oriented world. There are lots of other places where you can get good information about how to go about planning, so I won't go into it here.&lt;br /&gt;&lt;br /&gt;By now, you may well be wondering why you would ever want to put anything into the 'this' scope, because all I've done is tell you that it's a bad thing.&lt;br /&gt;&lt;br /&gt;Lets look at another example:&lt;br /&gt;&lt;br /&gt;test.cfc&lt;br /&gt;&amp;lt;cfcomponent hint="simple test component"&amp;gt;&lt;br /&gt;	&amp;lt;!--- create a default value for foo ---&amp;gt;&lt;br /&gt;	&amp;lt;cfset foo = ""&amp;gt;&lt;br /&gt;	&lt;br /&gt;	&amp;lt;!--- This function allows us to get the value of foo from&lt;br /&gt;	outside the component ---&amp;gt;&lt;br /&gt;	&amp;lt;cffunction name="getFoo"&amp;gt;&lt;br /&gt;		&amp;lt;cfreturn foo&amp;gt;&lt;br /&gt;	&amp;lt;/cffunction&amp;gt;&lt;br /&gt;	&lt;br /&gt;	&amp;lt;!--- This function allows us to change the value of foo ---&amp;gt;&lt;br /&gt;	&amp;lt;cffunction name="setFoo"&amp;gt;&lt;br /&gt;		&amp;lt;cfargument name="foo" type="string" required="yes"&amp;gt;&lt;br /&gt;		&amp;lt;cfset foo = arguments.foo&amp;gt; &lt;br /&gt;	&amp;lt;/cffunction&amp;gt;&lt;br /&gt;	&lt;br /&gt;&amp;lt;/cfcomponent&amp;gt;&lt;br /&gt;&lt;br /&gt;invoke.cfm&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;	obj = createObject('component','test');&lt;br /&gt;	obj.setFoo('bar');&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;#obj.getFoo()#&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;br /&gt;This time, the name of the argument passed to setFoo() is the same as the name of the variable it is setting in the un-named scope. Unfortunately, it doesn't work. No matter how you try to set the variable in setFoo(), getFoo() will always return an empty string. I'm not too sure what's going on to stop the variable assignment from working as expected. It could be that because there is a variable in the 'arguments' scope one is automatically created in the local scope for the function. It could be one of a number of things, but the bottom line is that you won't get an error, and you won't get the variable being set. This is one of the nastiest types of problem. A bug could go months without being discovered, then like a rake in the grass it hits you in the face when you least expect it.&lt;br /&gt;&lt;br /&gt;There are a couple of ways to get around this:&lt;br /&gt;&lt;br /&gt;The first is to make sure that the variable you are assigning never has the same name as the argument you are using to assign it. This works, but is a bit difficult to maintain and just doesn't seem so elegant as the other option.&lt;br /&gt;&lt;br /&gt;The second is to create a pseudo scope as a structure and put all of the properties into this instead. You might call this pseudo scope 'private', 'protected', 'Instance' or even 'variables' since that doesn't seem to exist inside a cfc. Personally I prefer to use 'protected' as that's what I think it maps to best when comparing to other languages. &lt;br /&gt;&lt;br /&gt;There are some other interesting things when using components as webservices, but I think I've given you enough to chew on for one blog entry.&lt;br /&gt;&lt;br /&gt;Spike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-82806520?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/82806520'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/82806520'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2002_10_06_archive.html#82806520' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-78144857</id><published>2002-06-24T12:44:00.000-07:00</published><updated>2002-09-06T07:45:33.000-07:00</updated><title type='text'></title><content type='html'>kwfu: ['cfupdate','cfinsert','session','application','cfform','cfinput']&lt;br /&gt;&lt;br /&gt;Someone sent me an email today asking what I think is so wrong with cfinput, cfform, cfinsert, cfupdate and session variables.&lt;br /&gt;&lt;br /&gt;Fortunately (or unfortunately depending on your point of view) for them I was in a typing mood. This was my reply:&lt;br /&gt;&lt;br /&gt;The main reason for listing those tags is that they put restrictions on the flexibility of what you can do, and they make future maintainability/modification more difficult.&lt;br /&gt;&lt;br /&gt;Take CFFORM for example. Although it allows you to add some validation to the cfinput tags that are contained within it,  there are several limitations to this. Some examples:&lt;br /&gt;&lt;br /&gt;There isn't an easy way to have the validation fired when the focus moves from one of the form fields.&lt;br /&gt;If you are running a version of CF Server earlier than CF 5, you can't use a regular expression to validate the content of a form field.&lt;br /&gt;Although you can specify a Javascript function to fire when validation fails, this sort of defeats the purpose of using cfform in the first place.&lt;br /&gt;Customizing the behaviour of the validation is relatively difficult, and if you do change the validation scripts in the cfusion directory, the changes will also have to be applied to all servers where the application is deployed.&lt;br /&gt;The cfform tag does not permit a method of get. Only post operations are allowed.&lt;br /&gt;&lt;br /&gt;Admittedly, none of the above problems are insurmountable if you really insisted on using cfform, but I have found that in general it is easier to read and maintain systems that have been written using standard HTML tags.&lt;br /&gt;&lt;br /&gt;In addition to this, the forms generated with cfform can only be used in ColdFusion applications, but the ones which use HTML only can be used in conjunction with any server side technology. I am a strong believer in solving problems properly once, and re-implementing the same solution many times.&lt;br /&gt;&lt;br /&gt;The database tags - cfinput and cfupdate, suffer from pretty much the same sort of problem. Although they do a good job of putting data in a database, they are not so nice 6 months down the line for someone who has to maintain the application. i.e. You can't just look at an action page that uses cfinsert and cfupdate and see what is happening. You will have to look at the form from that is posted to the action page, and almost certainly the database itself. Also, if you make a change to a database table, or split a single table into two tables, you have to go with the native SQL anyhow. If you're going to need to use SQL statements in your application then you might as well be consistent and use them throughout.&lt;br /&gt;&lt;br /&gt;In essence the problems with these tags are not so much in the functionality that they offer, but in the difficulty of maintaining the applications that use them long after their original purpose has been forgotten.&lt;br /&gt;&lt;br /&gt;Session variables I avoid for 3 reasons.&lt;br /&gt;&lt;br /&gt;1. It is not possible to get full information about all the sessions that are active on a particular server at any given time. Such information as how many active sessions there are, when the sessions were last accessed, the usernames of the users who have active sessions etc.&lt;br /&gt;&lt;br /&gt;This sort of information often is not required in the initial application stages, but often it does become a requirement in the application at some point down the line.&lt;br /&gt;&lt;br /&gt;2. Locking. I don't think I have ever seen an application that was completely free of errors with regard to locking access to session (or application) scoped variables. Even turning on the full checking option in the ColdFusion Administrator doesn't catch all the problems. Consider the following code:&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- in application.cfm ---&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- we'll copy the userprofile structure into the request scope&lt;br /&gt;so we don't have to keep locking as we go along ---&amp;gt;&lt;br /&gt;&amp;lt;cflock scope="session" type="exclusive" timeout="2"&amp;gt;&lt;br /&gt;    &amp;lt;cfset request.userprofile = session.userprofile&amp;gt;&lt;br /&gt;&amp;lt;/cflock&amp;gt;&lt;br /&gt;&lt;br /&gt;OOPS!!!&lt;br /&gt;&lt;br /&gt;All we have done here is make a reference to the variable in the session scope. &lt;br /&gt;&lt;br /&gt;Under heavy load, the following code will almost certainly cause the server to crash due to memory corruption in the session scope.&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- in somepage.cfm ---&amp;gt;&lt;br /&gt;&amp;lt;!--- something happened, so we increment a counter variable in the userprofile ---&amp;gt;&lt;br /&gt;&amp;lt;cfset request.userprofile.counter = request.userprofile.counter + 1&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;What we should have done in the first block of code is use the duplicate() function to copy the data from the session scope:&lt;br /&gt;&lt;br /&gt;&amp;lt;cflock scope="session" type="exclusive" timeout="2"&amp;gt;&lt;br /&gt;    &amp;lt;cfset request.userprofile = duplicate(session.userprofile)&amp;gt;&lt;br /&gt;&amp;lt;/cflock&amp;gt;&lt;br /&gt;&lt;br /&gt;The third reason for not using session scopes is to avoid any problems in the future if the application becomes too busy to run on a single server. Once that happens, you have to make sure that users stay on the same server for the duration of their session, as sessions are not shared between servers. This has changed in CFMX where it is possible to share sessions across clustered servers, but for earlier versions of CF it is a bit of a problem.&lt;br /&gt;&lt;br /&gt;In answer to your question about the checklist, I did have a checklist, but it wasn't on a piece of paper. It was a mental checklist of things to look out for.&lt;br /&gt;&lt;br /&gt;It is actually more like a set of guidelines than a checklist. It goes something like this:&lt;br /&gt;&lt;br /&gt;1. &lt;br /&gt;If a tag like cfform,cfinput,cfselect,cftable is used, is there an overridingly good reason for using it over manually doing the same thing with coldfusion code. In other words, if a tag has been used that encapsulates some programmatic logic, that could otherwise have been written using ColdFusion code is there a good reason for doing so.&lt;br /&gt;&lt;br /&gt;The reasons that I feel these tags need to be justified is that they are not so readable when it comes to looking at your own, or anyone elses code in 6 months time, and that they are less flexible should the application need to be changed at a later date.&lt;br /&gt;&lt;br /&gt;Having said that, I won't necessarily always decide that the use is not justified, I'd say it's something like 70-80% of the time.&lt;br /&gt;&lt;br /&gt;2. &lt;br /&gt;If data has been put into a persistent scope such as session, server, or application, is there a good justification for doing this over putting it in a database, or using the request scope. The main reason for doing this is that the persistent scopes all need to be locked, and as the code example above shows, it can be very difficult to track down problems with locking. The second reason for doing it is that if the application ever needs to run in a clustered environment there may be problems as mentioned above.&lt;br /&gt;&lt;br /&gt;3.&lt;br /&gt;If there are calls to tags which reach out from the ColdFusion server to some other system, could those calls become hung threads waiting for a response, or could they cause locking issues. The sort of tags I am thinking of here are cfhttp, cfmail, cfpop, cffile, cfdirectory, cfftp, cfldap, cfsearch, cfcollection, cfobject etc. All these tags can communicate with processes outside the control of the ColdFusion server, and the coldfusion developer. Some of them need to be locked and some of them can cause hung processes which are waiting for a response from the external system. Exactly what can be done with this sort of code is very dependent on the scenario, but it is something I will be looking for as a potential area of problems.&lt;br /&gt;&lt;br /&gt;4.&lt;br /&gt;If custom tags are used, are there a lot of nested recursive calls. This can slow down an application to an incredible degree. I have seen coldfusion applications that were built by very competent Java developers. The problem is that ColdFusion has a 'speed bump' of a few milliseconds each time it has to call a custom tag. Multiply that few milliseconds by a factor of several hundred or even a few thousand and you have an application that may not be particularly complex running at a crawl.&lt;br /&gt;&lt;br /&gt;5.&lt;br /&gt;Databases and queries. Often applications performance can be improved from several seconds per page request to several tens of milliseconds per page request just by adding a database index in the right table, or by creating a lookup table for id values. Depending on the nature of the application, it may or may not be possible to make changes to the database structure, but it is usually possible to add a few indices to the tables that are regularly queried.&lt;br /&gt;&lt;br /&gt;6.&lt;br /&gt;Consistency in naming of variables, naming of files, and structure of the file system. This is so incredibly important for the maintainability of an application that it really should be one of the primary design considerations for all applications. Unfortunately, short of rewriting the entire application there isn't much you can do to change it once an application has been written. The main reason I check this is so I will know for future reference whether or not I should accept any contracts to make changes to the application. It is also useful information for the client for maintaining the application, or for developing new ones.&lt;br /&gt;&lt;br /&gt;There are probably some more things that I'd check, but I think that's enough for you to chew on for now. If you've got this far without looking up award yourself top marks for powers of concentration ;-)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;NOTE: &lt;i&gt;Ben Forta&lt;/i&gt;&lt;/b&gt; sent me a mail pointing out that although these are all valid points you should not forget that the majority of CF applications are not mission critical, they are more like reporting or data entry apps. In these cases it often makes a lot of sense to use all the things I have discouraged above. &lt;br /&gt;&lt;br /&gt;I should have made it clearer that the mail to which I was responding was asking about a checklist I mentioned that I use when travelling around providing ColdFusion consulting. Since most of the applications I encounter in this capacity are mission critical applications it makes sense for me to have this checklist of things that I would discourage. As much as any other reason because it makes my job easier if I ever have to go back to the same company to do more consulting.&lt;br /&gt;&lt;br /&gt;In short, although these things are important for someone like me, that may not necessarily be true for all ColdFusion developers.&lt;br /&gt;&lt;br /&gt;Thanks for pointing that out Ben.&lt;br /&gt;&lt;br /&gt;Spike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-78144857?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/78144857'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/78144857'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2002_06_23_archive.html#78144857' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-78133428</id><published>2002-06-24T07:52:00.000-07:00</published><updated>2002-06-24T07:52:15.673-07:00</updated><title type='text'></title><content type='html'>Been very busy lately, so haven't had time to do much with the blog.&lt;br /&gt;&lt;br /&gt;I've got lots of good material to add when I get a chance which should be sometime in mid July at current rate of mountain shifting.&lt;br /&gt;&lt;br /&gt;Spike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-78133428?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/78133428'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/78133428'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2002_06_23_archive.html#78133428' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-77417647</id><published>2002-06-06T06:47:00.000-07:00</published><updated>2002-06-06T06:51:23.000-07:00</updated><title type='text'></title><content type='html'>kwfu: ['MX','marketing','sales']&lt;br /&gt;&lt;br /&gt;Great presentation on the MX vision from Jeremy Allaire now online:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.macromedia.com/software/mx/presentation/"&gt;http://www.macromedia.com/software/mx/presentation/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-77417647?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/77417647'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/77417647'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2002_06_02_archive.html#77417647' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-77377662</id><published>2002-06-05T08:38:00.000-07:00</published><updated>2002-06-05T08:38:26.976-07:00</updated><title type='text'></title><content type='html'>kwfu: ['wait','sleep','delay']&lt;br /&gt;&lt;br /&gt;Some tricks for getting a page to delay execution for a while on the server side while consuming minimum system resources. As opposed to looping infinitely which will cause processor peaks.&lt;br /&gt;&lt;br /&gt;Force a lock contention and trap the resulting error - This one seems to be the best for versions prior to CFMX.&lt;br /&gt;&lt;br /&gt;&amp;lt;cfset sleep = 2&amp;gt;&lt;br /&gt;&amp;lt;cfset start = getTickCount()&amp;gt;&lt;br /&gt;&amp;lt;cftry&amp;gt;&lt;br /&gt;&amp;lt;cflock name="foo" timeout="#sleep#" type="ReadOnly"&amp;gt;&lt;br /&gt;   &amp;lt;cflock name="foo" timeout="#sleep#" type="Exclusive"&amp;gt;&lt;br /&gt;   &amp;lt;!---waiting... for 20 seconds---&amp;gt;&lt;br /&gt;    &amp;lt;/cflock&amp;gt;&lt;br /&gt;&amp;lt;/cflock&amp;gt;&lt;br /&gt;&amp;lt;cfcatch&amp;gt;&amp;lt;/cfcatch&amp;gt;&lt;br /&gt;&amp;lt;/cftry&amp;gt;&lt;br /&gt;&amp;lt;cfset time = getTickCount() - start&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;#time#&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;br /&gt;Use cfexecute to invoke a process that either runs continuously, or doesn't stop for a while, and doesn't consume many system resources. This could also be done with cfftp, cfhttp, or a bunch of other external calls that are likely to take a while.&lt;br /&gt;&lt;br /&gt;&amp;lt;cfset start = getTickCount()&amp;gt;&lt;br /&gt;&amp;lt;cfexecute name="c:\cfusion\bin\cfstat.exe" timeout="2"/&amp;gt;&lt;br /&gt;&amp;lt;cfset timer = getTickCount() - start&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;#timer#&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;br /&gt;or&lt;br /&gt;&lt;br /&gt;&amp;lt;cfset start = getTickCount()&amp;gt;&lt;br /&gt;&amp;lt;cfset args = arrayNew(1)&amp;gt;&lt;br /&gt;&amp;lt;cfset args[1] = '-n'&amp;gt;&lt;br /&gt;&amp;lt;cfset args[2] = '1000'&amp;gt;&lt;br /&gt;&amp;lt;cfset args[3] = 'localhost'&amp;gt;&lt;br /&gt;&amp;lt;cftry&amp;gt;&lt;br /&gt;&amp;lt;cfexecute name="c:\winnt\system32\ping.exe" arguments="#args#" timeout="5"/&amp;gt;&lt;br /&gt;&amp;lt;cfcatch&amp;gt;&amp;lt;/cfcatch&amp;gt;&amp;lt;/cftry&amp;gt;&lt;br /&gt;&amp;lt;cfset timer = getTickCount() - start&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;#timer#&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;br /&gt;If you're running cfmx I'd recommend this.&lt;br /&gt;&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;function sleep(timeMillis) {&lt;br /&gt;		var thread = createObject("java", "java.lang.Thread");&lt;br /&gt;		thread.sleep(timeMillis);&lt;br /&gt;}&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-77377662?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/77377662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/77377662'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2002_06_02_archive.html#77377662' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-77252402</id><published>2002-06-02T09:01:00.000-07:00</published><updated>2002-06-02T09:01:30.663-07:00</updated><title type='text'></title><content type='html'>kwfu: ('custom tag','images','File upload')&lt;br /&gt;Decided to post this custom tag I wrote a while ago. It reads the information from an image file and retrieves info such as file size in bytes, height, width, and some other file format specific info. Works for a range of file types such as tiff, gif, jpeg, ras, bmp, and png.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.coldron.com/download/imgsize.zip"&gt;Download&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Instructions:&lt;br /&gt;1. Download file&lt;br /&gt;2. Extract to directory under the webroot&lt;br /&gt;3. Browse to index.cfm in the imgsize directory.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-77252402?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/77252402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/77252402'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2002_06_02_archive.html#77252402' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-76899031</id><published>2002-05-23T15:09:00.000-07:00</published><updated>2002-06-03T05:54:00.000-07:00</updated><title type='text'></title><content type='html'>kwfu: ('cfmx','pagecontext','jsp')&lt;br /&gt;I think there are so many features like this in CFMX that there's going to&lt;br /&gt;be a whole lot of re-learning and re-evaluating of  what up to now have been&lt;br /&gt;considered standard practices in CF, and probably more importantly things&lt;br /&gt;which up to now have been considered more or less taboo.&lt;br /&gt;&lt;br /&gt;I have some personal favourites from the 'Things that have changed'&lt;br /&gt;department:&lt;br /&gt;cfimport - allows you to have dynamic custom tag paths.&lt;br /&gt;cftrace - Cuts out 90% of the cases where I'd be using cfdump/cfabort to&lt;br /&gt;debug.&lt;br /&gt;cflogin - allows multiple authentication mechanisms to fire the login code -&lt;br /&gt;This could turn out to be a two edged sword, but there you go.&lt;br /&gt;&lt;br /&gt;There are of course a whole bunch of new features like native XML support,&lt;br /&gt;Flash remoting, CFCs etc.&lt;br /&gt;&lt;br /&gt;As someone famous once said 'We live in interesting times'.&lt;br /&gt;&lt;br /&gt;Originally posted on a closed mailing list. - Thanks Robi&lt;br /&gt;&lt;br /&gt;&lt;b&gt;UPDATE:&lt;/b&gt; Ray Camden pointed out that the multiple authentication mechanism is a feature you don't have to use.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Ray:&lt;/b&gt; you should note that this 'feature' of cflogin is&lt;br /&gt;something you do not have to use. If you do not use the cflogin scope,&lt;br /&gt;then you can restrict logins to just one source (form, url, whatever).&lt;br /&gt;In other words, do not do this:&lt;br /&gt;&lt;br /&gt;&amp;lt;cflogin&amp;gt;&lt;br /&gt;	&amp;lt;cfif isDefined("cflogin.name") ....&lt;br /&gt;&lt;br /&gt;Use this:&lt;br /&gt;&lt;br /&gt;&amp;lt;cflogin&amp;gt;&lt;br /&gt;	&amp;lt;cfif isDefined("form.name") ....&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Spike:&lt;/b&gt; I guess I wasn't clear enough in what I was saying. Of course you could write code to handle this manually, but it's kinda nice to have the ability to accept logins from flash remoting and from form scope without so much as a cfif. This, of course opens up a whole bunch of problems like script kiddies who use dictionary files to attack sites secured with http basic authentication. That's where I see the 2 edged sword thing. In practice I would probably handle things manually for this very reason, but that may not be applicable in every situation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-76899031?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/76899031'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/76899031'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2002_05_19_archive.html#76899031' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-76898858</id><published>2002-05-23T15:04:00.000-07:00</published><updated>2002-05-23T15:05:01.000-07:00</updated><title type='text'></title><content type='html'>kwfu: ('cfmx','class files','compile')&lt;br /&gt;This code will batch pre-compile a complete directory tree of CFMX templates. The original code is credited to an un-named Macromedia employee. He is only un-named because I haven't got round to checking with him if I can publish his name.&lt;br /&gt;&lt;br /&gt;In ColdFusion MX:&lt;br /&gt;&lt;br /&gt;Stick this in a batch file, save as compiler.bat, and pass it a directory to compile:&lt;br /&gt;&lt;br /&gt;@setlocal&lt;br /&gt;set NEO_INSTALL=c:\cfusionmx&lt;br /&gt;set PATH=%NEO_INSTALL%\runtime\bin;%PATH%&lt;br /&gt;java -classpath %NEO_INSTALL%\lib\cfusion.jar&lt;br /&gt;coldfusion.tools.Compiler -webroot %NEO_INSTALL%\wwwroot %*&lt;br /&gt;@endlocal&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;called like so:&lt;br /&gt;&lt;br /&gt;compiler.bat c:\cfusionmx\wwwroot\myapp&lt;br /&gt;&lt;br /&gt;Compiles all files below that directory.&lt;br /&gt;&lt;br /&gt;Spike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-76898858?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/76898858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/76898858'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2002_05_19_archive.html#76898858' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-76898375</id><published>2002-05-23T14:49:00.000-07:00</published><updated>2002-05-23T15:05:46.000-07:00</updated><title type='text'></title><content type='html'>kwfu: ('cflock','cfmx')&lt;br /&gt;&lt;br /&gt;The following code is credited to an un-named employee at Macromedia. The only reason he is un-named is that I haven't go round to getting his permission to use his name here. Suffice it to say that he is one of the core team of engineers who put together the ColdFusion MX engine. What he has to say is probably well worth listening to.&lt;br /&gt;&lt;br /&gt;&amp;lt;!---&lt;br /&gt;    This code will not make Neo explode or turn into a frog&lt;br /&gt;    or anything -- to my mind that is *bad.*  A core dump&lt;br /&gt;    is a better thing than silently corrupted data.&lt;br /&gt;---&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- no CFLOCK ---&amp;gt;&lt;br /&gt;&amp;lt;cfset session.cartTotal = session.cartTotal + currentPrice&amp;gt;&lt;br /&gt;&amp;lt;!---&lt;br /&gt;    There really is enough time between the right-hand side&lt;br /&gt;    read of session.cartTotal and the left-hand-side write&lt;br /&gt;    for another request to get in before us and modify&lt;br /&gt;    session.cartTotal; our CFSET will step on that other&lt;br /&gt;    request's data.  That is bad.&lt;br /&gt;---&amp;gt;&lt;br /&gt;&lt;br /&gt;Make your own mind up if you still want to use cflock.&lt;br /&gt;&lt;br /&gt;Spike&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-76898375?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/76898375'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/76898375'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2002_05_19_archive.html#76898375' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-76898052</id><published>2002-05-23T14:40:00.000-07:00</published><updated>2002-05-23T23:26:25.000-07:00</updated><title type='text'></title><content type='html'>kwfu: ('cf','cflock','full checking')&lt;br /&gt;&lt;br /&gt;In some versions of ColdFusion Server, there is an option in the ColdFusion Administrator related to the locking of shared memory variables. One of the options allows you to tell the ColdFusion Server to check all the code it processes to ensure that shared memory variables do not suffer from memory corruption. The option in the CF Administrator is referred to as 'full checking' in the following ramblings.&lt;br /&gt;&lt;br /&gt;beware of trusting the results of turning on full checking...&lt;br /&gt;&lt;br /&gt;If you do this:&lt;br /&gt;&lt;br /&gt;&amp;lt;cflock scope="session" type="readonly" timeout="2"&amp;gt;&lt;br /&gt;&amp;lt;cfset userprofile = session.useprofile&amp;gt;&lt;br /&gt;&amp;lt;/cflock&amp;gt;&lt;br /&gt;&lt;br /&gt;Then later in your code you do this:&lt;br /&gt;&lt;br /&gt;&amp;lt;cfset userprofile.emailaddress = 'bob@somedomain.com'&amp;gt;&lt;br /&gt;&lt;br /&gt;You are actually modifying the data in the session scope, but the full&lt;br /&gt;checking will not pick it up.&lt;br /&gt;&lt;br /&gt;In order to stop this being a problem you could do 1 of 2 things:&lt;br /&gt;&lt;br /&gt;Option 1:&lt;br /&gt;&amp;lt;cflock scope="session" type="readonly" timeout="2"&amp;gt;&lt;br /&gt;&amp;lt;cfset userprofile = duplicate(session.useprofile)&amp;gt;&lt;br /&gt;&amp;lt;/cflock&amp;gt;&lt;br /&gt;&lt;br /&gt;This will create a completely separate copy of the userprofile. Depending on&lt;br /&gt;what you are doing you might want this.&lt;br /&gt;&lt;br /&gt;Option 2:&lt;br /&gt;&amp;lt;cflock scope="session" type="exclusive" timeout="2"&amp;gt;&lt;br /&gt;&amp;lt;cfset userprofile.emailaddress = 'bob@somedomain.com'&amp;gt;&lt;br /&gt;&amp;lt;/cflock&amp;gt;&lt;br /&gt;&lt;br /&gt;This will safely update the data in the session scope. Again, depending on&lt;br /&gt;your circumstances this may be what you want to do.&lt;br /&gt;&lt;br /&gt;Good luck hunting down blocks of code that need to be locked as in option 2.&lt;br /&gt;&lt;br /&gt;Spike&lt;br /&gt;&lt;br /&gt;Originally posted in response to a thread on the UK ColdFusion User Group mailing list: dev@lists.cfdeveloper.co.uk.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-76898052?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/76898052'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/76898052'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2002_05_19_archive.html#76898052' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-3532843.post-76895715</id><published>2002-05-23T13:34:00.000-07:00</published><updated>2002-05-23T13:54:01.000-07:00</updated><title type='text'></title><content type='html'>kwfu: ('cf','application','cflock')&lt;br /&gt;&lt;br /&gt;Some may find the following mutterings on the ColdFusion application and locking framework useful.&lt;br /&gt;&lt;br /&gt;A variable which is created in application.cfm like so:&lt;br /&gt;&lt;br /&gt;&amp;lt;cfset myvar = "Foo"&amp;gt;&lt;br /&gt;&lt;br /&gt;Does not get created in the application scope. It gets created in the&lt;br /&gt;variables scope.&lt;br /&gt;&lt;br /&gt;Since application.cfm gets auto-included at the start of every page request&lt;br /&gt;this variable becomes available, as myvar, or variables.myvar, to the&lt;br /&gt;template which was requested on the url, and any other templates which are&lt;br /&gt;called by cfinclude. The variable will not be available to any templates&lt;br /&gt;which are called as custom tags unless you explicitly pass it in there as an&lt;br /&gt;attribute.&lt;br /&gt;&lt;br /&gt;If you want the variable to be available to all templates you must&lt;br /&gt;explicitly put it into the application scope like so:&lt;br /&gt;&lt;br /&gt;&amp;lt;cfset application.myvar = "Foo"&amp;gt;&lt;br /&gt;&lt;br /&gt;This will be available to all templates as application.myvar, but not as&lt;br /&gt;myvar, or variables.myvar.&lt;br /&gt;&lt;br /&gt;In order to maintain data integrity, and for stability you must wrap reads&lt;br /&gt;and writes to the application scope in a cflock:&lt;br /&gt;&lt;br /&gt;Setting:&lt;br /&gt;&amp;lt;cflock scope="application" type="exclusive" timeout="1"&amp;gt;&lt;br /&gt;&amp;lt;cfset application.myvar = "Foo"&amp;gt;&lt;br /&gt;&amp;lt;/cflock&amp;gt;&lt;br /&gt;&lt;br /&gt;Reading:&lt;br /&gt;&amp;lt;cflock scope="application" type="readonly" timeout="1"&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;#application.myvar#&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&amp;lt;/cflock&amp;gt;&lt;br /&gt;&lt;br /&gt;In CF 4.5, the Request scope was added so that the gazillions of custom tags&lt;br /&gt;that Spectra uses could all access data safely without having to put cflocks&lt;br /&gt;everywhere, or passing all the data around as attributes to the tags.&lt;br /&gt;&lt;br /&gt;The request scope is also available to all pages which get executed for a&lt;br /&gt;single request, so you could quite safely do this:&lt;br /&gt;&lt;br /&gt;In application.cfm:&lt;br /&gt;&amp;lt;cfset request.myvar = "Foo"&amp;gt;&lt;br /&gt;&lt;br /&gt;In some custom tag:&lt;br /&gt;&amp;lt;cfoutput&amp;gt;#request.myvar#&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;br /&gt;Woo Hoo!!!&lt;br /&gt;&lt;br /&gt;No locking required...&lt;br /&gt;&lt;br /&gt;BUT...&lt;br /&gt;&lt;br /&gt;Since there is a new request scope for every user, you will be having a&lt;br /&gt;separate copy of the data in that scope for each concurrent request. The&lt;br /&gt;default maximum for concurrent requests is 6, so you will probably be having&lt;br /&gt;up to 6 times the amount of data in the request scope in memory on a busy&lt;br /&gt;server. If you have a lot of data in there, this can become siginificant, so&lt;br /&gt;it's something to watch out for.&lt;br /&gt;&lt;br /&gt;Apart from that, it's up to you what you'd prefer. Request or application&lt;br /&gt;scopes are available to all files which get processed in a request, but you&lt;br /&gt;can't read variables from them unless you specify the scope name explicitly.&lt;br /&gt;This is probably a good idea anyhow, but most people, myself included, are&lt;br /&gt;just too lazy to do it for all variables.&lt;br /&gt;&lt;br /&gt;Spike&lt;br /&gt;&lt;br /&gt;Originally posted in response to a thread on UK ColdFusion User Group mailing list: dev@lists.cfdeveloper.co.uk.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3532843-76895715?l=spikefu.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/76895715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3532843/posts/default/76895715'/><link rel='alternate' type='text/html' href='http://spikefu.blogspot.com/2002_05_19_archive.html#76895715' title=''/><author><name>Spike</name><uri>http://www.blogger.com/profile/07580084328734664073</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry></feed>
