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() 2009 (Minneapolis, MN) with:

Typing Checking Errors In ColdFusion are RUNTIME Errors, NOT Compile Time Errors

By Ben Nadel on
Tags: ColdFusion

I have been reading several posts lately about the benefits / pitfalls of strong typing in ColdFusion. One of the things that keeps coming up is that people love using strong / strict typing because it allows errors to be found at compile time, not run time. Here's a comment I took off of Sean Corfield's blog:

... there is no question about this of course, strong typing is always the favour over weak typing. Basically, when you design a weakly typed language your shifting the problem from compile time to runtime. Yes, your language might be more approchable by non-programmers (or the not so good programmers among us) but does that realy solve the problem? When you get stuck you get stuck. I'm rather stuck at compile time then runtime, any day.

This was a general programming comment (not ColdFusion specific), but this type of argument I think is being used a lot when it comes to OOP and ColdFusion. Aria Media explains how in ColdFusion run time type checking is not really happening, but I thought I would illustrate this point. And, unless I am completely misunderstanding how ColdFusion works, allllll type checking errors in ColdFusion are thrown at RUNTIME, and never at compile time. Let's look at a small example. I am going to create three small components, Ben, Girl, and Dog.

Girl.cfc

  • <cfcomponent
  • displayname="Girl"
  • output="false"
  • hint="I am a chicka.">
  •  
  • <cffunction name="Init" access="public" returntype="Girl" output="false"
  • hint="Returns an initialized Girl instance.">
  •  
  • <!--- Return This reference. --->
  • <cfreturn THIS />
  • </cffunction>
  •  
  •  
  • <cffunction name="MakeOut" access="public" returntype="string" output="false"
  • hint="I makeout with who ever called me... I am sooo easy!">
  •  
  • <cfreturn "We are sooo making out and it is hot!!!" />
  • </cffunction>
  •  
  • </cfcomponent>

Dog.cfc

  • <cfcomponent
  • displayname="Dog"
  • output="false"
  • hint="I am a pooch.">
  •  
  • <cffunction name="Init" access="public" returntype="Dog" output="false"
  • hint="Returns an initialized Dog instance.">
  •  
  • <!--- Return This reference. --->
  • <cfreturn THIS />
  • </cffunction>
  •  
  •  
  • <cffunction name="Slobber" access="public" returntype="string" output="false"
  • hint="I slobber on who ever called me... Ewww gross!">
  •  
  • <cfreturn "You just got slobbered! Ha ha ha ha ha!" />
  • </cffunction>
  •  
  • </cfcomponent>

Ben.cfc

  • <cfcomponent
  • displayname="Ben"
  • output="false"
  • hint="I am El Ben. That is Spanish for 'The Ben'">
  •  
  • <cffunction name="Init" access="public" returntype="Ben" output="false"
  • hint="Returns an initialized Ben instance.">
  •  
  • <!--- Return This reference. --->
  • <cfreturn THIS />
  • </cffunction>
  •  
  •  
  • <cffunction name="MakeOut" access="public" returntype="string" output="false"
  • hint="I make out with who ever I can get my hands on.">
  •  
  • <!--- Define arguments. --->
  • <cfargument name="Girl" type="Girl" required="true" />
  •  
  • <!--- Make out with girl. --->
  • <cfreturn
  • ARGUMENTS.Girl.MakeOut()
  • />
  • </cffunction>
  •  
  •  
  • <cffunction name="PetDog" access="public" returntype="string" output="false"
  • hint="I pet any dog that I can get my hands on.">
  •  
  • <!--- Define arguments. --->
  • <cfargument name="Dog" type="Dog" required="true" />
  •  
  • <!--- Pet dog. --->
  • <cfreturn
  • ARGUMENTS.Dog.Slobber()
  • />
  • </cffunction>
  •  
  • </cfcomponent>

As you can see, both methods in the Ben.cfc, MakeOut() and PetDog(), expect strongly types arguments. If I call these methods with the appropriate type argument, I get valid responses. This code:

  • <!--- Create a ben, girl, and dog instance. --->
  • <cfset Ben = CreateObject( "component", "Ben" ).Init() />
  • <cfset Girl = CreateObject( "component", "Girl" ).Init() />
  • <cfset Dog = CreateObject( "component", "Dog" ).Init() />
  •  
  • <!--- Pet the dog. --->
  • #Ben.PetDog( Dog )#<br />
  • <br />
  •  
  • <!--- Make out with the hottie. --->
  • #Ben.MakeOut( Girl )#

... produces this output:

You just got slobbered! Ha ha ha ha ha!

We are sooo making out and it is hot!!!

This is what strong typing is (I think... maybe I am waaaay off here). If I attempt to pass the wrong type of object into a method an error get's thrown. Let's say I tried to make out with the dog:

  • <!--- Make out with dog... Hey the dog was asking for it. --->
  • #Ben.MakeOut( Dog )#

... I get the following error:

The argument GIRL passed to function MakeOut() is not of type Girl. If the component name is specified as a type of this argument, the reason for this error might be that a definition file for such component cannot be found or is not accessible.

Ah ha! Strong typing saves the day! But wait, was that a compile time error? Heck no! That was a run time error. How can I prove this? Execute this code:

  • <!--- Exit page. --->
  • <cfexit />
  •  
  • <!--- Make out with dog... Hey the dog was asking for it. --->
  • #Ben.MakeOut( Dog )#

And ta-da... No errors at all. What happened? The CFExit tag tells the ColdFusion process to not run the rest of the code on that template. The template itself was still SUCCESSFULLY compiled even though not all of it ran. Still don't believe me? Ok what about this:

  • <!--- Randomly attempt to run this part of the page. --->
  • <cfif RandRange( 0, 1 )>
  •  
  • <!--- Make out with dog... Sometimes. --->
  • #Ben.MakeOut( Dog )#
  •  
  • </cfif>

Now, the page errors only a theoretical 50% of the time. Are you saying that the template only fully compiles half the time? Of course not. The template is always fully compiled. Face it, type checking is at run time, never at compile time.

Ok, so people, from now on, you can make all the arguments for or against strong typing in ColdFusion, but you are not allowed to say anything about Compile time vs. Run time. Compile time has nothing at all to do with type checking. Calling the MakeOut() method on Ben and passing in Dog or Girl, or, heck, even StructNew() is never going to be caught at compile time... that's right, I said never!



Reader Comments

Nice illustration - although of course it's always possible that the compiler sees the cfexit tag, recognises that there's no execution path that will result in the code after that tag being run, and just optimises that redundant code out.

My personal take on the strong-vs-dynamic typing issue is this - dynamic typing is one of the reasons that CF is so easy to pick up and run with, but it's also one of the things that can cause big headaches on more complex projects. For me the main value of strong typing - and interfaces - is not so much that you can catch errors at compile time vs. runtime, but that it means you have less to worry about at design time. On small projects, you can often keep a good picture of the whole app in your head, but as the project grows, that's just not possible, and if you're getting errors in someone else's code, what's easier to trace through:

cfargument name="blah" type="Any"
(do some stuff that causes an error)

or

cfargument name="blah" type="ADefiniteCFCType"
(do some stuff that causes an error)

...at least with the second, you can go straight to the CFC in question and start hunting from there.

Reply to this Comment

Al,

You make an excellent point, and I think that is best point that people can make about strong typging. I think a lot of people have trouble seeing the usefulness of many things because most people only work on small projects where the feeling is "This solves a problem I don't have."

There is something very nice about seeing an error in real-time as opposed to setting values and then waiting around for an error to occurr. And if you are using persistent objects that are not accessed all the time, you might not even see the error for some time.

Reply to this Comment

You are very right that ColdFusion does all of its type checking at runtime, but that is because all of ColdFusion's typing is dynamic so its an impossibility to do it at compile-time.

One side of this issue that I haven't heard argued out yet is why we have to have one (strong or dynamic typing). I think Macromedia / Adobe have made a great step in proving that these two typing paradigms can absolutely coexist.

I'm kind of making this a regular comment now, but check out Actionscript! It has strong and dynamic typing both very elegantly available to the developer.
EX:
// Actionscript Starts Here

// Dynamic Typing (These all work)
var test = "cheese";
test = 4;
test = false;

// Strong Typing
var test:String = "cheese";
test = 4; // Throws a COMPILE time error
// Actionscript Ends Here

In my opinion this would be well within the scope of CF's capabilities given that it is providing a layer with dynamic typing on type of a strongly typed language. In fact, I would arguably say it is in the perfect situation for a feature like this.

By the way...I think I'm going to title this mini-rant my "Look at AS!" rant

Mike.

Reply to this Comment

Mike,

While I am not a master Action Scripter, and know nothing about the AS3 stuff coming out, I have definately used both the Strong and Weak typing in Flash Action Script. I love the way it really hooks nicely into the Flash IDE insight notes.

It would be kind of cool to do both in CF. But, this goes beyond my really mastery of higher-level progamming philosophy.

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.