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 cf.Objective() 2012 (Minneapolis, MN) with:

Giving My ColdFusion Components And My JavaScript Components The Same Structure

By Ben Nadel on

As I've been writing more and more JavaScript, I've come to notice two things: First, my ColdFusion components and my JavaScript components are often very similar in nature. And, Second, they each have a completely different structure. This latter point isn't driven by some well-thought-out methodology; rather, it's carried forward by the momentum of thirteen years of JavaScript programming. To try and bring some method to the madness, I wanted to see if I could make my JavaScript components look like my ColdFusion components; then, at the very least, I would have consistency driving my methodology.

Now, my ColdFusion component structure hasn't always been the same; like everything else, it has been evolving over the years, influenced by whichever team I am working with. As of today, this is how I structure my ColdFusion components:

  • <cfscript>
  •  
  • component
  • output = false
  • hint = "I represent a friend."
  • {
  •  
  • // I return the initialized component.
  • public any function init(
  • required string name,
  • required numeric age
  • ) {
  •  
  • // Store properties.
  • variables.name = name;
  • variables.age = age;
  • variables.firstName = getFirstName( name );
  •  
  • return( this );
  •  
  • }
  •  
  •  
  • // ---
  • // PUBLIC METHODS.
  • // ---
  •  
  •  
  • // I return a greeting.
  • public string function sayHello() {
  •  
  • return( "Hello, I am #firstName#; I am #age#." );
  •  
  • }
  •  
  •  
  • // ---
  • // PRIVATE METHODS.
  • // ---
  •  
  •  
  • // I get the first name, delimited by white-space characters.
  • private string function getFirstName( required string fullName ) {
  •  
  • return( listFirst( fullName, " " ) );
  •  
  • }
  •  
  • }
  •  
  • </cfscript>

The general structure of the ColdFusion component consists of the constructor followed by the public methods followed by the private methods. I now try to remove all the scoping from my method and property references (when possible) such that public and private status is somewhat seamless.

JavaScript is a fairly different language; but, it has many of the same constructs. As such, it's not too difficult to make my JavaScript components mimic the structure of my ColdFusion components. Here is the JavaScript version of the same code:

  • // I represent a friend.
  • function Friend( name, age ) {
  •  
  • // Store properties.
  • var firstName = getFirstName( name );
  •  
  • // Return the public API to the component.
  • return({
  • sayHello: sayHello
  • });
  •  
  •  
  • // ---
  • // PUBLIC METHODS.
  • // ---
  •  
  •  
  • // I return a greeting.
  • function sayHello() {
  •  
  • return( "Hello, I am " + firstName + "; I am " + age + "." );
  •  
  • }
  •  
  •  
  • // ---
  • // PRIVATE METHODS.
  • // ---
  •  
  •  
  • // I get the first name, delimited by white-space characters.
  • function getFirstName( fullName ) {
  •  
  • return( fullName.split( " " )[ 0 ] );
  •  
  • }
  •  
  • }

Since JavaScript components don't have a nested init() method - the component IS the init method - the JavaScript component body does all the initialization and returns the public-facing API. This approach is known as the Revealing Module Pattern. However, unlike many implementations of the revealing module pattern, my return statement comes directly after the initialization logic and not at the bottom of the module.

The return statement can precede the public methods due to "Function Hoisting." This feature, which is also available in ColdFusion, implicitly moves all of the Function declarations to the top of the current scope.

NOTE: Function declarations and function expressions are two different constructs; JavaScript does not hoist function expression, only declarations. That said, JavaScript will also hoist variable declarations; so, just be very mindful when you try to leverage this "feature" of the language.

While this structure works and has some advantages, it also has some clear disadvantages. First and foremost, this structure prevents this component from being extended using JavaScript's prototypal inheritance. That said, I find that in my current programming, I am using inheritance less and composition more.

NOTE: If you think you can extend this component by creating an instance of it and setting it as another object's prototype, you're probably doing prototypal inheritance wrong.

Second, it's not very memory efficient. Without proper use of the Prototype, each instance of this component defines its own set of functions. This means that each instance of this component takes up more memory and has more overhead than it might otherwise. That said, I feel that what you sacrifice in footprint you make up for in simplicity.

I'm sure that there's more to consider than what I've laid out above; however, I do appreciate that I can provide my ColdFusion components and my JavaScript components with a similar structure. What can I say - I'm a sucker for consistency.



Reader Comments

This is very similar to how I was taught to write C++ objects, though you'd usually have just the declarations in the header file and the definitions in a source file. Since you don't tend to have that separation of declaration from definition in ColdFusion or JavaScript, you have both the declaration and definition in one place. (Code-folding comes in really handy.)

I've found that, as I've gotten more familiar with ColdFusion and JavaScript, I've started emulating some of the coding patterns I learned in C++. By having the constructors and public functions at the top, the interface gets priority. The rest is only for those who want a look under the hood.

Some might have a knee-jerk response: "This is ColdFusion, not C++. Quit trying to turn it into something it isn't!" We aren't trying to turn ColdFusion into C++; we're simply applying the lessons we've learned over the decades in other languages to this one. He who can't learn his lessons from other languages is doomed to repeat them in his language of choice.

Reply to this Comment

Pretty much how I do my stuff, tho I omit the cfscript tag and use pure script components.

hmmm, I do however use annotations to clean up my method declarations (which railo stupi-- stubbornly does not support last I looked)

ex:

/**
* @output false
* @accessors true
* @ExtDirect true
*/
component foo extends bar {

/**
* @getter true
* @setter false
*/
property string a;

variables.a = '';

/**
* @output false
*/
public any function init(){
return this;
}

/**
* @output false
* @roles "admin,poweruser,coolguys"
* @ExtDirect true
* @RequiresCSRF true
*/
public void function doThing( required string txt="" ){
variables.a = arguments.txt;
}
}

The annotations are code folded up and out of the way, leaving a nice clean method declaration with the truly important parts visible, ex:

/**...
public void function doThing( required string txt="" ){}

-Jim

Reply to this Comment

The memory and performance penalties for working around prototypical conventions are more pronounced than you let on in this post. In particular on the v8 engine used in Chrome, this approach would also negate the memory lookup and management gains the engine provides through its 'hidden class' mechanism.

http://thibaultlaurens.github.io/javascript/2013/04/29/how-the-v8-engine-works/

Context is important, as only dealing with a handful of Friend objects at one time would probably not produce much in the way of poor behavior, but this approach puts a significantly lower performance ceiling on your application should you have even a single function of the scale that it would need several hundreds or thousands of Friends simultaneously in memory.

I don't think that, in the vast majority of contexts, the gain in consistent code aesthetics with indirectly related backend code, which is admittedly a pretty subjective value, is worth taking on the resulting performance constrictions where it really counts: in the experience for your end user. I'd suggest rethinking your advocacy of this approach.

Reply to this Comment

@Chris,

Thanks for the link - I have not seen that before and I, admittedly, do not know all that much about how memory is managed behind the scenes. I know that sharing method references is good and that re-creating methods is bad... and that's about as deep as I understand.

That said, I agree that context is definitely king with something like this. As you say, it depends on how many instances you have; and, also, how your code is intended to be used.

If I was intending to build a class to be sub-classed (for lack of a more technically appropriate term), I would definitely go with the prototype so that others could add code as needed. When I think of that, I tend to think of sub-classing the EventEmitter in Node.js (which can be done using the prototype ... just pops to mind because I have worked with it).

All in all, I suppose that this code is shaded by how I use a lot of JavaScript - creating singletons that provide service-level features. It's not too often that I create large instances of anything.

In the end, I guess I would concede that I don't want people to use this approach across the board; but, rather, consider the pros/cons. After all, there are things that this approach allows for that prototype does not facilitate (ex, passing method references around without bind'ing them to the appropriate "this" method, ala Deferred in jQuery).

Excellent feedback!

Reply to this Comment

@Paul,

I tend to agree; if you can keep familiar style without sacrificing clean code, then I think it's probably good. After all, code that is more consistent will naturally be less bug-prone since it requires fewer mental models.

Reply to this Comment

@Jim,

The component will work without the CFScript tags. I include the CFScript tags because GitHub cannot seem to properly color-code .cfc files without them. And, since they don't hurt, I just add them when I know a Gist is going to be created behind the scenes.

I know that's a really lame reason ... but I'm very shallow :D

Reply to this Comment

@Ben,

This jsbin illustrates two major reasons why following prototypical patterns should be preferred in all but the most specialized of special scenarios:

http://jsbin.com/oKUzowo/4/edit (Open the console tab at top, and then reload to see what the script logs.)

The biggest gain in memory usage and management can be seen here; this is the reasoning underlying the 'reference good/re-creation bad' mantra. Implementing a 'revealing module' pattern in javascript, while it performs the task of information hiding quite well, does so at a significant performance and memory expense that increases in a linear fashion with the size of the object's definition, and then linearly again with the spin-up of more instances.

Each instance of the original Friend above hoists it's own copy of every method included inside; that they're functionally identical is irrelevant to the runtime, getFirstName in one Friend is completely different than the getFirstName in another Friend, having their own separate addresses and spaces in memory.

A prototypically-constructed object, like protoFriend in the jsbin, instead will hoist that function into memory once and reference it at that position thereafter. This makes new object spin-up faster, as it doesn't have to hoist the entire object and all its methods again, and it makes using that new object faster, as it doesn't have to wastefully pull up identical functions stored in many different places across memory.

An ancillary point, but terrifically important in some contexts, is that instances created from a 'revealing module' pattern have no inherent connection with each other as objects of a particular type unless you explicitly bake that functionality back in somehow. In short, it breaks the native`instanceof` functionality, as what returns is nothing but an instance of `Object` and not `Friend` as might be expected. This is also illustrated in the jsbin above.

That JS doesn't have natively the ability to denote variables and methods as private is a bit of a drawback, especially if you've grown accustomed to those protections being there, but I'd argue against short-circuiting other core features of the language to get JS to behave in a similar manner, especially when those bits are central to performance and memory management.

Thanks for the conversation. :)

Reply to this Comment

@Chris,

Ironically, the "information hiding" isn't even the reason I have, as of late, gravitated to this format in code. Honestly, until about a year ago, I was flat out against the revealing module pattern; for the 10-years prior, definitely ALL the object creation I did involved the Prototype.

In fact, just a year ago, I was talking about using Prototype constructs in AngularJS controllers:

http://www.bennadel.com/blog/2421-Creating-AngularJS-Controllers-With-Instance-Methods.htm

... and then, that's where things changed.

One day, I had to inject "underscore" into an AngularJS controller:

  • function Controller( $scope, _ ) {
  •  
  • this._ = _;
  •  
  • }

... when I wrote this, it took a huge emotional toll. This was so ugly that I simply couldn't deal. And, in the instance methods, I didn't want to start using "this._.each()" (and the various methods). It didn't look right, it didn't feel right.

So, I started gravitating to the revealing module patterns where I could reference the "_" variable in a much cleaner fashion:

  • function Controller( $scope, _ ) {
  •  
  • function someMethod() {
  • return( _.find( ... ) );
  • }
  •  
  • }

So, I guess it was AngularJS that really had a big impact on the way I structure my code now, especially since I work so often with AngularJS as my front-end library these days.

When I hit this hurdle, I tried to find a way to use a Factory to create my Controllers (where the Factory could inject the "_" and then the Controller could use Prototype; but, I couldn't find a way.

Wow, upon reflection, it's kind of crazy how much history / experience goes into code formatting decisions :D Talk about the tip of the iceberg!!!

Reply to this Comment

For scoping demonstration purposes only (in other words, the logic doesn't make sense in this example), If I had:

  • component {
  • Variables.X = 1;
  •  
  • function Junction(X) {
  • local.X = arguments.X;
  • }
  • }
  •  
  • Y = new myComponent().Junction(2);

Then I would similarly scope variables in JavaScript like this:

  • (function() {
  • var Variables = {};
  • Variables.X = 1;
  • function Junction(X) {
  • var local = {};
  • local.X = X;
  • }
  • $(document).on('click','#myID',Junction(2));
  • })();

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.