We're speaking at
CFUnited 2008:
CFUnited - The Premiere ColdFusion Technical Conference

Search

Calendar

SunMonTueWedThuFriSat
    123
45678910
11121314151617
18192021222324
25262728293031

Subscribe Enter your email address to subscribe to this blog. You'll receive an email when we write a new post.

Recent Entries Come On In, Rails-The Water's Warm
Shan's Simple Examples: File uploads with Flex and ColdFusion

Recent Comments Google Calendar API - Creating a new Calendar with ColdFusion
Steve Julian said: When and where are you going to post the finished CFC's ? Thanks [more]

Three Phases of Programmer Development
Pat Branley said: I normally think of those phase 2 people as 'programmers' and the phase 3 people as 'developers'. I... [more]

New Job Title: Front End Engineer
Sean Corfield said: Well, there's always the excellent Fusion Authority Quarterly Journal... [more]

Down To The Wire: HTTP Sniffers
Brian M said: I second the mention of the Charles Web Debugging Proxy that Tariq mentioned. It is fantastic. It s... [more]

New Job Title: Front End Engineer
Patrick said: Heya Sean. Good point. I never understood how they did things over there at SysCon, and I understand... [more]

Archives By Subject Business of Software (4) [RSS]
ColdFusion (318) [RSS]
Conferences (6) [RSS]
Databases (87) [RSS]
Flex & Flash (109) [RSS]
Fusebox (87) [RSS]
General Development (29) [RSS]
Google (9) [RSS]
Hardware (5) [RSS]
JVM & Java (132) [RSS]
Linux (20) [RSS]
Miscellaneous (254) [RSS]
Performance (8) [RSS]
SeeFusion (36) [RSS]
Shan's Simple Examples (6) [RSS]
User Interface (3) [RSS]
Windows (5) [RSS]

Archives By Poster Daryl Banttari (10)
Nat Papovich (29)
Patrick Quinn (36)
Shannon Hicks (22)
Steve Nelson (21)
Tyson Vanek (3)


bottom corner

Evils of Global Variables when Unit Testing

Let's jump right to some code.

<cffunction name="somefunction">
   <cfargument name="email">
   <cfset var getsomething="">
   
   <cfquery name="getsomething" datasource="mydsn">
      select *
         from sometable
         where email='#arguments.email#'
   </cfquery>
   <cfreturn getsomething/>

</cffunction>

versus:

<cffunction name="somefunction">
   <cfset var getsomething="">
   
   <cfquery name="getsomething" datasource="mydsn">
      select *
         from sometable
            where email='#session.user.getEmail()#'
   </cfquery>
   <cfreturn getsomething/>

</cffunction>

They look pretty similar right? Near identical. Neither is really easier or harder to read. Performance wise, I suspect you couldn't see much of a difference. If you're thinking to yourself, "Aww geez Steve Nelson is about to go on a week long rampage about something." You would be right!!

Here's the problem that I see and it's pretty simple. Unit Testing.

The first one is dead simple to create a unit test for. You cfinvoke the method, pass in an email. Boom! You're done. Hell you could write a bunch of different unit tests in a matter of minutes to try out different types of email addresses. Maybe throw in some Japanese kanji just to see what happens. Maybe do a SQL injection test since I didn't use cfqueryparam in my example. Then setup your testing process to continually test them with a test harneness runner.

The second function is dramatically more difficult to unit test. You can try the same thing, cfinvoke the method (no arguments). Damn. Error. It doesn't know what session.user is. So now you have to create another CFC. (Which you were going to do anyway right? I guess we need to unit test that one too) Create the CFC with at least one method getEmail. Great. Run the first test it works. Beautiful. But now let's try our Japanese kanji test. How do we change that value returned by getEmail? We have two choices. The obvious choice is to edit the original getEmail method and have it return the static Japanese kanji string. Fine. But now you're no longer testing the english string. So the better choice is to create ANOTHER method called updateEmail which modifies the email address returned. Then the second unit test has to call the updateEmail() before it calls getEmail(). Great it works! Now run the first test again... aw damn it! It's still displaying the kanji. What the heck? Oh right, the first one ALSO has to call the updateEmail() method because it's a session scope variable. The Session scope is a persistent global variable. One unit test affected another unit test when global variables are used.

Did I lose you? Good. I was trying. Chew on that a bit. I'll come back to some unit testing code soon. Personally I prefer passing in every argument my method needs.

-Steve Nelson

By the way, if you're looking for CF Architects or simply some extra CF hands, send us an email or give us a call at +1-970-223-2278. We're about to finish up a few projects and will have some free time shortly.

Use CFArgument For... Everything

In my new effort to rid my life of global variables, I've been focusing on the arguments scope. I think the arguments scope is the key to solving this problem.

With my MVC-CFC framework I find it is easy as pie to live without global variables. In a nutshell, EVERYTHING is passed in through a <cfargument>. No more request scopes for me.

It takes a little more work to do this, but in the end I think it's worth it. The cfarguments help validate the data and ultimately make auto-unit testing fairly simple to do by calling the getMetaData() function. I'll post more about that another day. So for example. I used to name my datasources with #request.dsn# I'd set the variable in some settings file, then use it directly in my cfquery tags. Now it takes a few more steps.

1) Instead of the request scope I use the arguments scope and set it in a file that is called with every request (such as Application.cfc).

<cfset arguments.dsn="somedatasource">

2) The controller methods have a cfargument.

<cfargument name="dsn" type="string">

3) The controllers then call the model methods, the dsn is passed down to the models, each of those model methods ALSO have a cfargument.

<cfargument name="dsn" type="string">

4) Finally it is used in the cfquery:

<cfquery datasource="#arguments.dsn#">

What do you think?

Btw, I KNOW someone is going to focus on my dsn variable instead of seeing the bigger picture. If you want I can use variable names of "foo" or "bar". CS students LOVE this layer of abstraction. I think it's an awful way to explain programming. So, I beg you, before you tell me how you deal with datasources, see the forest through the trees. This isn't about datasources, it's about global versus local variables.

-Steve Nelson

A New Reason to Not use Global Variables

It's been 10 years since I first heard someone say that global variables are bad news. To be truthful I didn't really understand the reason back then. The most common reason not to use global variables is the namespace argument. Basically the problem is that you can accidentally overwrite another variable. Yeah ok, I guess that's a problem, but it so rarely affects me I don't think about it much.

But who can argue with computer scientists? Not me that's for sure. Whenever I try, I end up feeling stupid.

Well, I have a new reason not to use global variables: Unit testing. Unit testing affects me every day.

Don't get me wrong, you can use global variables when unit testing, of course you can. The issue is that when you introduce global variables you suddenly break the rules of unit testing, which is to test small portions of the codebase on its own. Global variables mean you need to test multiple units together. This complicates the testing process, something we do not need.

That's two reasons not to use them, which is enough for me. Now how to break the habit? Cold turkey? The patch?

-Steve Nelson

Steve's MVC Framework a year later

A few people have asked me if I've done anything with my MVC framework that I presented a year ago at the CF Frameworks conference. The short answer. Yes, but very minor. I admit it. I'm an addict. Mostly it's the utter simplicity that I love. It takes the power of CFCs with the simplicity of Fusebox 1.0 (yes, the original Fusebox). Sure there are lots of little things you need to do when working with CFCs. But you have to do those with any framework that uses CFCs. What I like about this framework is that it's about code organization, not extending some codebase or mastering yet another set of XML tags.

I'll do a bunch of posts explaining what I've found. For those of you that don't know what I'm talking about, let me see if i can explain a framework to you in one paragraph. I'd love to see if any other framework can do the same. So here we go (this is for an HTML app, Flex apps are a teeny bit different)... Organize your code into 3 top level folders. "Controller" "Model" and "View" In each of those 3 folders contain subfolders. In each subfolder under the View folder contains a single CFC file and one or more CFM files. The methods in that CFC file do two things, deal with cfarguments and cfinclude one of the cfm files. These CFM files contain HTML code. The model folders are structured in a similar way. The model methods have cfarguments a cfinclude to a cfm (or put the code right in the cfc) and cfreturn some data. It is all tied together with the controller folders. These folders have a single CFC, each of the controller methods simply cfinvokes methods from the model and view cfcs. That's it.

Ugggh, it sounds a lot more complex when I type it out. Wait! Let me try again!

Three groups of folders: Controller, Model, View. Each folder has a CFC and one or more CFMs. View methods cfinclude a display CFM file. Model methods cfinclude an action CFM file. Controller methods cfinvoke model and view methods. All web requests go to the controller CFCs first.

I like that definition better. If you want to try this out on one of your projects, I've posted some more info on it here. Or if you'd rather not mess around with framework theory and have us architect your next project, send us an email or give us a call at +1-970-223-2278

-Steve Nelson

My (Other) Frameworks Presentation: Best Practices for Integrating CFCs, Flex and Fusebox

I was more excited about the FB3 to FB5 presentation than this presentation, but a lot more people have requested the materials for this one, so here it is.

Download here Integrating.zip

The presentation didn't have a working sample application, but inside, you will find the handful of example files I showed, as well as a PowerPoint

Comments welcome, and let me know if you get it installed!

My Frameworks Conference Presentation: Making the Jump from FB3 to FB5

I've had a few people ask for the materials from my "Making the Jump from FB3 to FB5" presentation at the Frameworks Conference from earlier this month. Sorry for the delay, but I finally put together all the materials fit for consumption.

Download here turkeylogin.zip

Inside, you'll find the PowerPoint along with a sample application which, although I did not demo at the conference, does carefully highlight the differences between Fusebox 3 and Fusebox 5.

Comments welcome, and let me know if you get it installed!

CFCs are the Framework

This CFC framework is too simple for you. It has too much power without enough work. It doesn't even have a really clever name. Frankly, you're not going to like it.

But in case you're still curious, you can download my presentation, the codebase and a 5 page code walk through here:

http://labs.webapper.net

I am Concerned about my Presentation Tomorrow

I have to be honest, I'm a little concerned that my presentation at 12:30 tomorrow. My new CFC framework/methodology/method (whatever you call it) is just too simple. I'm concerned that it won't confuse enough people tomorrow.

I mean, this conference is about frameworks, the attendees are the smartest of the smart people in the CF community. They're going to understand 99% of everything I say and probably finish my sentences for me. My idea for how an application should be built using CFCs is just too easy.

I need help thinking up something really confusing that I can talk about. Any suggestions?

Interview: Steven Nelson on CFC-only Fusebox

For those of you who haven't seen it yet, this is an interview between Michael Smith at Teratech and Steve Nelson here at Webapper, about Steve's upcoming presentation at the Frameworks Conference, entitled "CFCs ARE the Framework".

============================================

Michael Smith: Since you created the original Fusebox methodology, can I assume you're speaking about Fusebox 5?
Steve Nelson: Nope, not this year. I'm talking about an experimental pure-CFC framework. It's a concept I've been playing with for about a year now, and I love it.

Michael Smith: Let me get this straight, you created a new framework?
Steve Nelson: No, not exactly. The code looks and feels exactly like an MVC-style Fusebox application from a conceptual level, but it doesn't use Fusebox 5 XML or core files. It uses CFCs. My original idea for Fusebox, 10 years ago, was to come up with standard concepts for architecting an application, not come up with a single soup to nuts product. In a nutshell, I've created an entirely new implementation of Fusebox. My implementation still uses the concepts of "circuits", "fuseactions", "fuses" etc. It just doesn't use XML files to define circuits, fuseactions, or fuses. Nor does it have any external core files that need versioning and maintenance.

Michael Smith: That's sacrilegious! All ColdFusion frameworks are organized with XML files.
Steve Nelson: That's true. The popular CF frameworks today do utilize XML files to organize the architecture code. Which is fine. But that in no way means that's the only solution. In my opinion, using XML files to create a new framework programming language has more drawbacks than benefits. The biggest drawback is that the developer needs to learn yet another series of tags and syntax and keywords in order to use a framework. That's a big hurdle to jump, which is why many developers say "[insert framework name] - one of these days I'm going to learn that!". Fusebox XML has about 20 tags and over 100 attributes of those tags. Many of these tags are 1 to 1 correlations to existing CFML tags with slightly different attributes. i.e. fuseaction==cffunction include==cfinclude. Which makes me question the benefit of using XML to define a framework's architecture.

Michael Smith: So how does it work?
Steve Nelson: Basically, this Fusebox implementation uses CFCs to manage themselves. This is easier than you'd think. Basically, I use 3 types of CFCs: Model, View and Controller CFCs. Model CFCs run "action" code (cfinclude "qry/act" files). View CFCs run "display" code (cfinclude "dsp" files). Controller CFCs determine which model and views to run (cfinvoke function in other CFCs). That's about it. My presentation will go into the details of organizing the CFML so this all works together.

Michael Smith: Seems simple enough, but how is this an implementation of Fusebox?
Steve Nelson: There are three main concepts in Fusebox: Circuits, Fuseactions and Fuses. These concepts translate directly over to CFCs. A "Fuseaction" in a URL like: index.cfm?fuseaction=users.listUsers lets the application know what the user is trying to do. In my CFC implementation of Fusebox, it is letting the application know that the user is trying to access the file: c:\inetpub\myapplication\controller\users\users.cfc and to run the cffunction: "listUsers". That cffunction may cfinvoke other cffunctions in the model and/or view folders in the application. Those cffunctions may cfinclude files.

Michael Smith: So a "Fuseaction" is just a cffunction in a CFC?
Steve Nelson: Yep.

Michael Smith: And a "Circuit" is a CFC itself?
Steve Nelson: Well, kind of. I like to think of a circuit as the entire folder that a CFC is in. Because a circuit contains both fuseactions AND fuses.

Michael Smith: Oh, right. So that means a cfincluded file is a "Fuse"?
Steve Nelson: You got it.

Michael Smith: How about performance, is this method fast?
Steve Nelson: It's VERY FAST. Since there are no core files, nor do the CFCs extend other CFCS, a page request may only call 2 or 3 cfcs and a couple included cfm files. At this point the performance of the application is up to the architect, not the architecture itself.

Michael Smith: But there has to be some overhead, a couple hundred milliseconds?
Steve Nelson: Pfff no way! Maybe 10 milliseconds because it uses CFCs instead of only CFMs. But I think that's debatable.

Michael Smith: I think I see where you're going, but I don't really grasp how you make this all work.
Steve Nelson: Well that's a good reason to come to the Frameworks Conference on February 1st, in Bethesda, MD. You'll be there, won't you?

Michael Smith: No, I'm busy that day. I'm going to be at a Frameworks Conference in Bethesda, MD on February 1st.
Steve Nelson: Oh, that's too bad. I'm planning on demonstrating all the details of making this work. Well maybe we'll meet up next year.

Michael Smith: Wait, did you say February 1st?
Steve Nelson: Yes, Thursday 2/01/07 through Friday 2/02/07.

Michael Smith: And you said it's in Bethesda, Maryland?
Steve Nelson: Right. Bethesda is about 20-30 minutes north of Washington DC (depending on traffic).

Michael Smith: Oh right! Yes, I'll be there.
Steve Nelson: Well then I'll see you there.

Frameworks Conference 2007 - See You There

Hey all. Just a quick shout to remind everyone about the Frameworks Conference next week in DC (Bethesda). We're happy to be Bronze Sponsors, and Nat and Steve will be speaking, too. And, of course, we'll have swag in hand to give out to our comrades. Keep your eyes peeled for another witty Webapper t-shirt.

Here are the topics we're speaking on:

* Best Practices for Integrating CFCs with Fusebox (Nat)
* Making the Jump from FB3 to FB5 (Nat)
* CFCs ARE the Framework (Steve)

And here's the conference site (not too late to sign up!):

http://www.frameworksconference.com/

Hope to see some of you there.

Best, Patrick

More Entries

bottom corner