Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at BFusion / BFLEX 2009 (Bloomington, Indiana) with:

Fusion Authority Quarterly Update - Volume II, Issue III

By Ben Nadel on
Tags: ColdFusion

This weekend, I finished reading the latest issue of the Fusion Authority Quarterly Update (FAQu). It was the "ColdFusion 8 Special Edition". And yet, ironically, the article that hit me hardest had nothing to with ColdFusion at all; it was Hal Helms' article on Javascript. Now, I know you might have noticed that I've been giving Hal a lot of press lately, but honestly, it's all just coincidental - there's no hidden agenda here. Hal's just a bright guy and I've learned a lot from him. Anyway, it's one thing to learn about something totally new; but, it's a completely different thing to learn something new about something you know very well. Such is the case in Hal Helm's article, "Javascript: The Misunderstood Language." He covers something called "very late binding" and how it can be used to create single and multiple class inheritance in a language that doesn't formally have classes. I like to consider myself somewhat of an advanced Javascript programmer, but I have never seen anything like this before and it looks very awesome. As Hal mentions in the article, this kind of technique would be overkill for any kind of small application, but I have to imagine that for any large-scale, thick-client applications, knowing this kind of programming is going to be hugely useful (mental note: I should really start reading Pro Javascript Techniques).

The rest of the issue did focus on ColdFusion 8 and its new and powerful features. I was glad to see Sean Corfield clarify the use of the new OnMissingMethod() handler since I totally misunderstood what it was for. During his discussion, he brings up the concept of thinking in messages rather than method calls. At first, I didn't really follow what he was talking about? But then, once I start to think of objects as communicating entities rather than targets of invocation, the messaging concept really cleared up some mental roadblocks. In fact, when you think about communication rather than invocation, the idea of an OnMissingMethod() handler seems quite natural. Once Sean sets you up with this new way of thinking, he also covers how it can be leveraged to create features such as generic getters / setters and aspect oriented programming (AOP).

Peter Bell's article on exposing the service layer of the application was very interesting. I don't want to say that it was exactly about creating a remote API for your applications, but that was definitely part of the discussion and the part that intrigued me the most. He discusses come important points about code organization and maintaining sessions across multiple API requests when cookie persistence is not available. I want to get more into writing APIs; I feel like as I get more into object oriented programming (OOP), these two will go more hand in hand and definitely assuage the difficultly of writing either. Definitely good food for thought.

Michael Dinowitz gives a good overview of the OnMissingTemplate() event handler. I am not sure how I feel about the OnMissingTemplate() method just yet. I programmed the NYCFUG web site to run off of it and it was definitely harder than working with just a 404 handler. In fact, you can't really rely solely on the OnMissingTemplate() handler since it only works for explicitly requested ColdFusion pages. If you try to request a non-existent directory with no file, the 404 handler fires, but if you request that same non-existing directory and the index.cfm file, the OnMissingTemplate() event handler gets invoked. I feel like its a very 80% complete piece of functionality. Until they can somehow give it more hooks into the requested file execution pipeline (which may never happen), I almost feel that 404 handling or URL rewriting is still the better approach.

The rest of the articles were good, but I don't want to give away all the secrets :) Wally Kolcz gives a good overview of dynamic presentation creation using the CFPresentation tag. I'm glad that someone is finally talking about this stuff as I don't think it has gotten nearly enough of the spotlight. Ray Camden writes a good article on CFAjaxProxy and how it can be used to call ColdFusion components directly from your Javascript code. And, while it is nothing that I can try out at this point, it was definitely good to see Terrence Ryan go over ColdFusion 8 and Microsoft Exchange server integration. Charlie Arehart also does a good walk through of the interactive step debugger features that can be accessed through Eclipse.


 
 
 

 
Fusion Authority Quarterly Update (FAQu) Volume II, Issue III - ColdFusion 8 Special Edition  
 
 
 

Note: Girl not included with FAQu purchase.




Reader Comments

Ben, thanks again for the kind words.

I especially liked Sean's article on the onMissingMethod handler. I already have dynamic getters and setters in my base Object class, but I thought I'd make use of it to allow me to have this kind of syntactic sugar:

person.firstName() or
person.firstName('Hal')

It was pretty simple:

<cffunction name="onMissingMethod" access="public" output="true">
<cfargument name="missingMethodName" required="true" />
<cfargument name="missingMethodArguments" required="true" />
<cfif StructIsEmpty(missingMethodArguments)>
<cfreturn get(missingMethodName) />
<cfelse>
<cfset set(missingMethodName, missingMethodArguments[1]) />
</cfif>
</cffunction>

I'm not totally sold on this: I may later rue my impetuosity, but I do like the way it looks. Time will tell if this is a case of image over substance...

Reply to this Comment

@Hal,

A number of the jQuery methods work that way. For example:

jQuery.attr( name [, value] )
jQuery.val( [value] )
jQuery.html( [value] )

... I have to say, they are extremely easy to use. I have not run into any issues with them yet.

Reply to this Comment

Right, Ben. I think I got the idea from Ruby and then liked it a lot in jQuery. By putting that code in my Object class, it saves a lot of code in individual classes. I guess the only thing I worry about is what happens if a genuine missing method is called? I love the syntax part; I'm just not sure if I like my implementation...

Reply to this Comment

@Hal,

I suppose you could make use of something like Sean talked about with the list of "Readable" properties and do some sort of check before you actually get / set the property.

One of the things that always bugged me about this idea of generic getters / setters is that you lose the ability to just quickly look at a CFC and figure out what methods exist. I suppose with something like a list of readable properties, this might be just as good.

Reply to this Comment

On the subject of generic getters/setters, if you have this code:

<cfset variables.instance.x = null />
<cfset variables.instance.y = null />

Don't you know that you'll have accessors for these? Is there any reason I need an explicit getX(), setX(x), getY(), setY(y)?

Reply to this Comment

@Hal,

I think you are correct. If you can't look at the functions to get the list of available methods, then you should be able to look at the list of instance variables. I think the key is just to have some explicit list.

Reply to this Comment

After convincing myself I didn't like my implementation, I added this to the top of the method:

<cfif NOT StructKeyExists(variables.instance, missingMethodName)>
<cfreturn />
</cfif>

That, at least, will make sure that we have an instance variable by that name before trying to read or write to it.

Reply to this Comment

@Hal,

Do you know if this can be used to extend built-in objects. For example, I was playing around with this idea:

function CustomArray(){
Array.call( this );
}

var arrCustom = new CustomArray();

alert( arrCustom.length );

In this example, however, the last alert says that the value is undefined; so, clearly, it's not getting the property from the built-in Array class.

Any ideas on this one?

Reply to this Comment

Arrays are a bit weird -- and they vary from browser to browser. Try this, though:

function CustomArray() {
this.push=Array.prototype.push;
this.length=Array.prototype.length;
this.introduceYourself = function(){
return "I am a custom array";
};
}

var coolGuys = new CustomArray();
coolGuys.push('Ben');
coolGuys.push('Hal');
coolGuys.push('Clark');

alert(coolGuys.length);
alert(coolGuys.introduceYourself());

Reply to this Comment

@Hal,

Very cool! It would never have occurred to me that "length" was in the prototype of the Array. Actually, it would never have occurred to me that you could actually see reference the prototype values of other objects. Very cool.

I wanted to try it using the prototype scope:

function CustomArray() {
// Constructor.
}

// Prototype values.
CustomArray.prototype.push = Array.prototype.push;
CustomArray.prototype.length = Array.prototype.length;
CustomArray.prototype.introduceYourself = function(){
return "I am a custom array";
};

That works fine too. I guess you just have to use the push/pop methods. It doesn't seem to like using array notation (ex. coolGuys[ 1]). I guess that's too "core" the Array object to extend.

Reply to this Comment

Ben, you can still use regular array notation with this. For example, if I suddenly become uncool (ridiculous, I know!), you could replace me with -- who's that ColdFusion evangelist guy? Oh, yeah: Ben.

So, referencing my first post,

alert(coolGuys.length);
alert(coolGuys.introduceYourself());
alert(coolGuys[1] == "Hal"); --> true
coolGuys[1] = 'Ben';
alert(coolGuys[1] == "Ben"); --> true

Or am I missing something?

Reply to this Comment

@Hal,

I tried it and after setting values using [] notation, the "length" property came up zero. I tried it in HomeSite (which i think previews using IE6). I will try later in FireFox.

Reply to this Comment

@Hal,

To be honest, push() / pop() are probably the better way to do things. I think its more descriptive an action than doing something like:

myarray[ myarray.length ] = value

Plus, myarray.push( value ) is actually less typing :)

Reply to this Comment

Hmmm...you could also do this.

function CustomArray() {
var self = new Array();
self.introduceYourself = function(){
return "I am a custom array";
};
return self;
}

That will give you push/pop plus standard array notation.

Reply to this Comment

@Hal,

Oooh, I like that. I was looking for a way to augment the Array class without modifying the base Array type. That looks pretty good.

Reply to this Comment

Going back to Hal's wonderfully readable jQuery style getter/setter syntax earlier in the comments, you could do away with the base "get()" and "set()" methods altogether and just use the onMissingMethod handler with less code and (probably) more speed:

<cffunction name="onMissingMethod" returntype="any" access="public" output="false">
<cfargument name="missingMethodName" type="string" required="true">
<cfargument name="missingMethodArguments" type="struct" required="true">
<cfscript>
var local = {};
if(NOT structKeyExists(instance,arguments.missingMethodName))
this.throw("BaseObject.NonExistantVariableOrMethod",arguments.missingMethodName & " is not defined either as a method or variable in " & getMetaData(this).name);
if(structIsEmpty(arguments.missingMethodArguments)){
// GET the instance variable
local.returnValue = instance[arguments.missingMethodName]; //NB: don't return directly (otherwise may throw complex object error)
return local.returnValue;
}
// SET the instance variable
instance[arguments.missingMethodName] = arguments.missingMethodArguments[1];
</cfscript>
</cffunction>

NOTES:

1) Assumes a) a "variables.instance" struct holding data, and b) a throw() method is defined in the cfc

2) I tried to shave off another line by returning instance[arguments.missingMethodName] directly, but found that CF throws a "complex object" error when putting the getter method call in # signs. So it has to be returned via an intermediate variable (local.returnValue).

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.