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).
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):
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.