OOPhoto - Thoughts On The Massive Shift To Object-Based Controllers

Posted July 21, 2008 at 9:47 PM

Tags: ColdFusion

The latest OOPhoto application can be experienced here.

The OOPhoto code for this post can be seen here.

As a next step in my OOPhoto application, Peter Bell and I thought it would be a good next step to convert from a standard CFM controller scheme to CFC-based controllers in which each controller is represented by a ColdFusion component (CFC) with some sort of execution function (ex. Execute(), Call(), etc.). On first thought, this seems like a relatively small shift; just like creating the Service Objects, as a first step we can simply move our procedural code into ColdFusion components, right?

Wrong! Moving our page-flow from ColdFusion pages to ColdFusion components is actually a massive shift in functionality and best practices. I say "best practices" because there are liberties we could take to make this step easier, but those would violate some of the most fundamental rules of object usage. Specifically, I am talking about the idea of low-coupling. When it comes to object usage, we want the object to have low coupling to the environment in which it is used. This makes it more portable (not an issue in our case) and much more resistant to change in the application (that's what we want).


 
 
 

 
Sexy Girl Jumping In The Air To Demonstrate The Principle of Low Coupling In OOPhoto  
 
 
 

In order to ensure that this low coupling is achieved, an object should not assume anything about the way it is being used; an object should know what is going on inside of it and nothing more. The concept is simple, but when it comes to object-based controllers, things get very sticky very fast. If you look at what our controllers are doing you will see references to the following objects (off the top of my head):

  • APPLICATION.Factory
  • APPLICATION.Config
  • REQUEST.UDF
  • REQUEST.Web
  • REQUEST.Attributes
  • REQUEST.Controller
  • REQUEST.APIResult
  • REQUEST.Errors
  • REQUEST.Do
  • FORM
  • URL
  • CGI

This is all well and fine when you are dealing with CFM pages, but when you have the above wrapped in a ColdFusion component, suddenly each reference above represents a high degree of coupling to the application environment; each reference to APPLICATION, REQUEST, CGI, FORM, URL, etc. requires the Controller object to know about the world greater than itself. This is a huge no-no and one of the most often-seen violations of object usage.

Could we leave the code as-is? Yes. All of the above scopes are globally accessible scopes and can be referenced inside of any ColdFusion component. But the point here is not just to get it to work (the existing code already does that!), the point it to get it to work better.

So how do we proceed? We need to come up with a way to pass these values into the Controllers such that we can lower the coupling. But at the same time, we don't want to have to explicitly pass in every object - this would mean that every time we needed a new variable, we would need to update the signature of our execution methods. The easiest way to accomplish this is wrap all of the above data into a single object and pass that object through to the controllers. I think, although I could be mistaken, that this pattern is often seen in other MVC frameworks as the Event object or the View state or PageRequest or whatever other "bag" is created to store variables.

Once we have our variables bag, we can easily pass through variable data with a low(er) amount of coupling; the object is still highly coupled to the structure of the variables "bag", but at least it is no longer coupled to the greater application. But this is only the first step of the transformation - now we have to worry about the rest of the code. Every place that references the REQUEST scope or the FORM scope or the URL scope (etc.) needs to be updated to refer to this variables bag or to objects explicitly pulled out of it.

As you can see, this seemingly simple step is actually a rather large undertaking. In an application of this size, I am almost 100% convinced that this will not be seen as a useful step after the fact. However, since I do see the benefits of it in larger applications and because I think other MVC frameworks use this methodology as well, I will implement it to get a taste of how it is done.

Post Comment  |  Ask Ben  |  Other Searches  |  Print Page


You Might Also Be Interested In:



Learning ColdFusion 9 - ColdFusion 9 tutorials, samples, examples, demos

Reader Comments

Jul 22, 2008 at 10:03 AM // reply »
24 Comments

Great stuff Ben. I finally took the time to read through all of your posts and all of the comments in this series, and it's a fantastic resource. It took me a few hours, but was definitely worth it. I think your description and example of DI in the last article are probably the most accessible I've ever seen.

I'm looking forward to the rest of the series. Keep up the good work!


Jul 22, 2008 at 10:08 AM // reply »
7,572 Comments

@Bob,

Thanks for the fantastic feedback. I am really excited to be learning this stuff, but it always makes it twice as nice to know that my explorations are helping other people as well.

I think this next step is gonna be a big one :) I'll keep you all updated.


Jul 22, 2008 at 10:42 AM // reply »
45 Comments

You know . . . you really should write a book. You've got a lot of good, usable material right from this blog.


Jul 22, 2008 at 10:43 AM // reply »
111 Comments

@Ben,

Just to confirm your suspicions, you are correct about other frameworks encapsulating other object references into a standard package to be passed into each controller instance. Model-Glue uses the Event object. Also as you deduced, this loosens coupling with the application but at the same time creates a new coupling to the framework. In other words, in a Model-Glue application, every method in the controllers expects an Event argument and it knows that information comes out of arguments.event and goes back into arguments.event. The controller absolutely reflects the framework, but in the process it needs to know nothing about the application ... how the Event got populated prior to the controller call is unimportant to the controller object.

All of which is just to say: I think you've boiled down the essence of where you're trying to go with the Controller now, and it seems like it's all moving in the right direction. It's very cool to see some of this stuff actually worked out piece by piece, rather than just seeing the finished product, like a Model-Glue or Mach ii framework. The 'why' of it all is coming much clearer to me in the process.

Thanks!


Jul 22, 2008 at 10:54 AM // reply »
12 Comments

Ben,

I have been reading through this series over the past few days and I must say this is fantastic work. The way you write your thoughts out is what makes it an extraordinary series of posts. Good work man!


Jul 23, 2008 at 8:25 AM // reply »
7,572 Comments

@Lola,

Thanks for the encouragement. We'll see where this series ends up :)

@JFish,

Good to know that I am heading in the right direction. Now, I have to come up with a good name for my variables bag. This is actually harder than it seems because it will contain such a huge mix of data that will be used for so many different purposes.

@Anuj,

Thanks man.


Jul 23, 2008 at 10:27 AM // reply »
7,572 Comments

Just finished my conversion to very basic CFC-based controllers. The code is not yet posted. Hopefully I can post at lunch. That was stressful :)


Jul 23, 2008 at 9:29 PM // reply »
7,572 Comments

The updated code with CFC-based controllers have been posted:

http://www.bennadel.com/index.cfm?dax=blog:1296.view

I am exhausted.


Post Comment  |  Ask Ben

Recent Blog Comments
Mar 22, 2010 at 11:32 AM
FLEX On jQuery: Handling Mouse-Down-Outside Events
A few comments: First, you said: "In FLEX, there doesn't appear to be much of a difference between a component and the UI that it composes." For all intents and purposes, Flex is a UI Framework. ... read »
Mar 22, 2010 at 10:20 AM
POIUtility.cfc Examples For Reading And Writing Excel Files In ColdFusion
Can you please show me how to write to multiple sheets of a workbook? Thanks for your cool cfc. Khoa. ... read »
Lee
Mar 22, 2010 at 10:08 AM
Javascript's Implicit Boolean Conversions
I would certainly still use if(strValue.length > 0) over if(strValue) simply because I believe it makes the code more self-documenting. Not everyone knows that an empty string evaluates to false. ... read »
Mar 22, 2010 at 7:43 AM
Terms Of Service / Privacy Policy Document Generator
Thankyou for this very helpful form. You've made my life much easier today. I'll have a look around your site... I'm sure there's some more good stuff here..Thanks Dave ... read »
Mar 22, 2010 at 7:21 AM
Encountered "(. Incorrect Select Statement, Expecting a 'FROM', But Encountered '(' Instead, A Select Statement Should Have a 'FROM' Construct.
I got this exception now. In case you're using var-es local struct, CF gives you couple of "new" exceptions: Encountered "local. and Encountered "id. Incorrect Select List, Incorrect select colum ... read »
Mar 22, 2010 at 3:08 AM
Ask Ben: Selecting XML Attributes Given Other XML Attributes
Thanks for the response. I finally discovered that I was getting this error because I had cfsetting enablecfoutputonly="yes" in Application.cfc, and was neither setting it to false elsewhere nor brac ... read »
Mar 21, 2010 at 8:57 PM
The Bourne Ultimatum Starring Matt Damon And Julia Stiles
late to the party, but my observation is this: rewatch carefully for the platonic nature of the relationship between nicki and jason. she never flirts with him. he never comes on to her. they alway ... read »
Mar 21, 2010 at 7:40 PM
Is Simulating User-Input Events With jQuery Ever A Good Idea?
A couple of things. One you embed the initial state of of more-info in the CSS. IMHO, that behavior should be in jQuery: moreInfo.hide(); It shows that the behavior your toggling and closing is mor ... read »