Object Controllers and Inheritance
I’ve been thinking a lot about these kinds of controller requirements and will be fully supporting them in LightBase by the end of the year (promises, promises :->). But for now, I want to talk about a very simple solution to a very simple problem.
The vast majority of single content area, stateless page views (which is what a lot of us deal with a lot of the time) can actually be implemented quite nicely using an “object controller” pattern. I’m sure this isn’t even vaguely original as it seems a very obvious approach, but I though I’d post on what I’m doing so that I can get feedback on how other people are implementing similar system and any limitations/issues they have run into. I need to clarify that this is NOT a complete solution to any kind of controller requirement, but does seem to be a fairly elegant way to handle simple single content area stateless controllers.
Current ColdFusion MVC frameworks are pretty much model agnostic. They don’t care what kind of object model you have and don’t limit you in terms of the events/actions that you can describe and configure listeners for. This provides for a great deal of flexibility, but I wondered what would happen if I created a more object oriented controller (where events are inherently applied to objects – I’m not saying MG and M2 don’t use CFCs or OO best practices – they do!). So far it seems to be working well for a nice set of use cases.
The concept underlying this was that there are only so many actions required to describe most of the events you need to implement a web application. I have found that I can describe all of my “single event” actions for a given application using an object name, a manageably small list of actions (usually 5-15) and an optional modifier.
Let’s take an example. Want to build a simple admin system for a newsletter? Events you need for managing are list, add, edit, delete, view, report, send and publish. Want to manage users? You might need list, add, edit, delete, view and authenticate methods. What about managing a product catalog? Main screens are the ability to list, add, edit delete and view both products and categories. Seeing a pattern yet?! Even for the front end of a catalog we want things like view category (which displays the category, any associated sub categories and any products within the category using the magic of ORM) and view product. Even a shopping cart is primarily about add item, update item (quantity), remove item and the like.
Of course, you also need support for an identifier as you may have a list of admin users and a list of all users, a simple registration user form and a full sign up form. So, a controller event would be fully specified in the documentation by #ObjectName# #ActionName# and an optional #ActionIdentifier# giving you fully qualified event descriptors such as User List Admin, User List All, User Form Registration, User Form Signup where the objectname describes which object and hence which controller to call, the actionname is the method you need to call, and the action identifier describes the specific set of properties for the controller to use to call the appropriate list or save method, to load the appropriate property names, to direct to the appropriate view screen and so on. Clearly there are a large number of object independent actions and usually they can be implemented using the same code with just declarative differences (the property name lists to process, the object name to create a bean for, etc.). There are also a small number of actions that are object specific (most websites don’t require you to publish a user or send a product although I suppose you could come up with arguments for supporting both features if you had a mind to). Hmmm, a set of methods common to most objects and a subset of object specific methods. Starting to sound like a problem that would be well suited to a BaseController and a set of virtual or physical object specific controllers for NewsletterController, UserController, etc.
In practice I’m finding that this approach provides a lot of flexibility for reusing controller logic based on parameterization while still allowing for custom logic for “difficult” objects. It also means there is a nice connection between the controller model and the underlying business model and by using virtual objects it stops the number of classes from getting out of hand. You don’t NEED to create a NewsletterController if it doesn’t have any unique code – just create a bean definition in LightWire and set the class path to the BaseController so you don’t end up with a bunch of empty cfcs. Then if you do need to create an object specific method, just create the controller file (say NewsletterController.cfc), make it extend BaseController, add the custom method to it, and change the class path line in the bean definition within LightWire to the new NewsletterController.cfc and you’re done!
A few comments. Firstly for this to solve all problems you often need to be open to having orchestration objects as part of your domain service layer where a specific action is dependent on multiple objects that are not related (if the objects are related you can just call the primary domain object and use an ORM to handle returning an order containing a collection of order items or allowing you to manage the addresses for a user or whatever). This is a good thing, though as they are the perfect place to implement a declarative model for specifying web flows/workflows/continuation server style concepts that I’ll be playing with later in the year.
Of course, none of this works for handling multiple events per page request. In LightBase I’ll be implementing a pseudo page controller and support for multiple independent stateful content areas per page request. But that is a higher level of abstraction that would then use the object controller to implement each of the individual component/content area requests so it is an extension rather than a replacement for the object controller approach.
I’ve also not really thought through implicit invocation as it relates to this as I find most of my requirements for implicit invocation are driven by business rules that should be in the model, not in the controller, so I’ve never yet had a problem where I felt implicit invocation in my controller would be a good solution (although I’ve implemented implicit invocation in my model for notifications and the like on a regular basis). I’ll blog a little more about this in the moment and am quite open to the likelihood that it is a function of the limited set of use cases I’ve been exposed to rather than anything else!
That said, this seems to me like a pretty obvious approach to controllers, so I’d appreciate any thoughts from anyone else who has gone a little further down this road about anything I may be missing or any roadblocks I haven’t thought through yet. That said, I’ve been using this kind of pattern for a number of projects and it seems to be working quite nicely so far. It is also a step towards a RESTful approach (more REST influenced than anything) by allowing a combination of object, action and (where appropriate) object ID to specify a URI for a specific action on a specific object.
Any thoughts much appreciated!


I am following pretty well with your posts. I think I get the basic idea but the engineer in me is constantly wondering how all this is sensibly implemented.
Once upon a time, I got the idea to build view components for subsections of the page. I had methods to output the header, footer, generate the body of content and the like. All the components met a consistant API signature and worked quite well. I was pleased with the outcome and with how quickly I could add and remove subsections.
In a later phase of the same project, lots of little one-off requirements began to be revealed. As I accounted for each one-off in the application, my cute little components began to get heavier. Having the need for an extra bit of data in my component meant dragging a value through several layers and functions. Once I met the requirements, I had a look at the final blueprint in code and was not happy.
On a whim, I knocked down all the components and simply made the sections into templates of HTML. The end result was a much easily understandable system.
Perhaps I could have stared at the componentized code a little longer and found a nice clean refactor for this particular use case. Perhaps not.
I too feel there is a lot of upfront replicatable code in the beginnings of a project. I am using a framework, and some generative programming techniques. This helps a lot. However, I am still reevaluating my processes and can't say I have a stable set of solutions for every project. I am excited to get a look at LightBase this weekend. Not only for the abillity to generate other portions of applications, but to be able to more closely analyze your concepts and ideas.
I would love to give you more direct feedback on your posts. I find them all entertaining and engaging. At times, however, I am unable to fully comment on a subject without some sort of case study or example code. For it is when the abstract meets the practical that I can offer the most insight.
Keep up the good work on LightBase this weekend..
DW
I agree - this stuff is fundamentally hard - it is why I spend so much time thinking and so little coding. It's like DI. It took me weeks to really get what a DI engine was and coded a rough cut engine in less than a day and am to date only 2 man days into LightWire in terms of coding.
I'm blogging and coding in parallel so I'll get you some sample code over the next couple of days so you can comment on the implementation rather than just the conceptual ideas!
FYI, the answer I'm finding to the object based view rendering is the appropriate relationship between objects and templates. Templates are where you put all of the little tweaks, but I won't say that something like a table rendering object (even with template support) ends up with a simple API - it doesn't. It is also a case of having simple templates (for designers), complex templates (for coders) and objects (for pure scripting such as creating URLs and template independent paging functionality). It is definitely taking a while to get right and I don't expect to be happy with all of this until the end of the year.
Still, it's a fun journey!
I would assume you have some system for keeping the last few weeks (and maybe beyond) in your head. I would kill (only if I couldn't get caught, tho) to see something like a mind-map with output outline results as each branch that follows your blog. Most of your posts are a fantastic read, but unless you (meaning me) happened to have the time or current relevant project in the works, I find it hard to keep some of the "rules" around beyond about the 3rd or 4th level down your logic spirals (in terms of depth).
In any case...praise and loyalty to your words so far.
One of the reasons I blog so much is to try to keep all of this stuff straight in my OWN head! The search link on the right of the blog works and I use it frequently to remember what I was thinking about.
I have played with Mind Maps, but still haven't really got comfortable with using them, but once I've got a good base of interesting ideas together, I'll try to put together some tools for making them more comprehensible.
Good starting point will be the documentation (when I write it) for the Lightbase framework (when I finish it) as that will pull together most of the ideas. I'm also going to try to go through and reindex all my posts to the appropriate categories, but for now, "search" is about all I've got!
Still playing with implementation of custom data types. I don't like ANY of the solutions I've found as they're either too bitty or too bad in terms of separation of concerns, but continuing to play with that.
Also got a nice approach to object based rendering including UI components and templates included into rendering cfc's. Sounds funky but seems to work out quite nicely and provide a simple elegant language for designers to use in their templates (stuff like #Render.contentArea("Main")# in the page template where you want the main content area to go), so that needs a lot of clean up but is getting there. Once I have the above (without ORM) - probably tonight I'll release a first conceptual cut. Still missing continuation/workflow servers, no AOP in LightWire let for cross cutting concerns, no support yet for multiple dynamic content areas, but I should be able to drop those in as the month progresses.
Getting there, but just taking a while (and lots of project work to do :-<).