By Peter Bell

Generalizing the Controller

Imagine if you could look at every page request as a type of parameterized action on a specific object. So, you would come up with a list of types of actions (list, displayForm, save, confirm, delete, associate, publish, import, export, report, etc.) each of which would have its own set of parameters (a list would include things like a property name list, default records per page and the default order by, a save would include the list of properties to save, etc.). An inheritance hierarchy would allow you to set defaults at a system level (by default all lists display 25 records) but to overload those at a object level (by default Products display 50/page), an action level (the MasterAdminList displays 30 records per page) and for certain parameters, at a request level (if exists URL/form.RecordsPerPage, use that instead of the default value).

If this was true, what kind of metadata and/or code would be required to implement Controllers to solve the majority of use cases? . . .

I have the idea of a "feature" (the controller associated to a given page in my pseudo-page controller) which can have n-methods. While some of those methods would need to exist to handle edge cases, the vast majority could be described using metadata in terms of their name, the object they relate to and the name and type of action to perform on that object (for example, object=User&action-type=List&action-name=NewUsers) along with n- parameters allowing a feature method to overload some of the default properties for a given object controller method and the name of the view to display. In this case, you could have a BaseFeature.call() method that'd start by seeing if the method requested existed in the code base. If not it'd look for the methods name in metadata and if that didn't exist it'd give up and say that the requested method didn't exist.

I see "features" as a very thin wrapper around object controllers as it seems to me the vast majority of actions you want to implement for a web application can be described in terms of a common collection of classes of operation (list, displayForm, save, confirm, delete, associate, publish, import, export, report, etc.) on a specific object. Can you think of an action one of your controllers that couldn't be described in this manner?

The benefits of this approach are that the class of functionality required for a controller to list users is similar to that for listing products. The kind of functionality required to add CartItems to cart is similar as to adding articles to a newsletter. So, by creating a small number of base classes in a BaseObjectController, they can handle all of the heavy lifting, relegating the vast majority of object controller methods to metadata parameterizing the base methods (but if you had an object where save was fundamentally different that for any other object - say for Article, you could create an ArticleController and provide it with a save() method to overload the base class). Equally, while most controller methods would just parameterize base methods (ExpiredCartList would just parameterize "List"), if you needed to hand code CartController.expiredCartList() you could do so and the hand coded methods would be executed when that object controller method was requested.

Thoughts?

Comments
"Imagine if you could look at every page request as a type of parameterized action on a specific object."

That's how I've seen it since I first realized what Rails was doing. Of course, Rails doesn't actually send url variables/form variables as parameters to methods, but the idea remains.

I guess its rather easy to send parameters to the methods in CF. Just name the arguments and they will come through the arguments scope. I didn't think of doing that until now... I may consider it - then we come one step closer to divorcing views from controllers, with the possibility of plugging in your model and controller to a desktop application, for instance.
# Posted By Sam | 5/29/07 7:41 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.005.