By Peter Bell

What Does the Controller Do? (Advanced)

Usually when we talk about controllers, we mean the HTML controller whose responsibility is to mediate between the language of the browser and API of your model. What would happen if we looked at controllers as the code responsible for mediating between any request and the underlying model API? What would that model API look like? And how can we generate the darn things so we can all stop writing code and start watching Lost?! . . .

Types of Requests
If you look at a web application as a closed system, it can be seen as a system with state. Any external (or internal - e.g. scheduled tasks) input can affect the state and/or return a view of part of the state.

What are common classes of input to a non-trivial web application? Typically an end user via a browser requesting a page, Flex or AJAX calls requesting and/or returning data outside of the page model, remote API calls from other systems using some combination of URI along with URL or form scope for a simple, JSON, XML or full blown SOAP request, emails, text messages, changes to the file system (e.g. an image or comma delimited text file to import) and arguably changes to the monitored environment (running short on disk space) or the occurrence of internal scheduled tasks. I'm sure there are other classes of input a web application might need to take, but I'm hoping that a system designed to support the above classes of inputs could fairly easily be generalized to handle other classes of input. (Any other classes of input that come to mind? Input appreciated!)

The Model API
So, what kind of Model API would be able to interface with controllers for all of those classes of input?

The first question is whether a model API should be purely object based or whether it should support higher level abstractions. Should all model calls be against a single type of business object or should there should be "features" in the model wrapping behavior that may not fit well using an object metaphor? Up to now, while I've found a use for "features" in my HTML controller (I have a Catalog feature that wraps certain Category and Product calls, a Checkout feature that wraps Order calls an Admin feature that wraps CRUD calls to all administratable business objects and so on), most use cases I've seen for the other classes of inputs are based on altering and/or accessing state for a single object (which of course can include composed object via simple ORM principles - so a cart containing cart items or a category containing products is not a problem). For now I'm going to assume that the model API should be "object" based and I'm going to use the common idea of a collection of service methods (one for each type of business object) as the API to the model. So you can PageService.new() to get a new (blank with defaults) page, UserService.add() to register a new user or CartService.delete("ExpiredCarts") to clear out all old shopping carts.

Types of Response
The next question is what the model should return. There are broadly two classes of model calls. Those whose primary intent is a query (to access state - which should be without side effects other than those introduced by logging of requests) and those whose primary intent is a command (to modify state - which should only return state directly relevant to the modification implemented). While it is a bit of overhead, it is really important to me to be able to wrap all responses with smart getters to handle calculated properties, so I'm going to return a single Iterating Business Object from all query methods (based on getbyFilter(), getByPropertyName() or new()). In the case of the HTML controller, those will be passed to the view. In the case of Flex and AJAX calls they'll be generically looped through to create the appropriate XML or JSON output allowing for calculated properties in data sets passed to remote calls using the exact same smart business object getters as used elsewhere in the system. For all commands, I'll return a status code and message, and perhaps an optional IBO containing before and/or after data for any modified records for use cases where that is important.

Securing the Model
In such an environment, clearly there has to be some kind of security functionality within the model, with the various classes of controllers translating that into the appropriate format for their requests. For example, a directory watcher would be automatically assigned a role with appropriate permissions, an HTML page controller would wrap the necessary pages with login requests and Flex and AJAX controllers would expose some kind of optional authenticate method for calls requiring security permissions that didn't pass a valid authentication key from the cookie scope based on an earlier client login.

Given that security can be applied to all types of calls but may not affect any or all of them (you *could* have a system where certain deletes didn't require security and another one where even simple article access was secured), all model calls should support an optional security key and all model responses should include a simple security code communicating something along the lines of "all OK", "authentication required" or "insufficient permissions to proceed".

The HTML Page Controller - Handling Multiple Content Areas
One of the challenges when building an HTML page is that often multiple model calls are required for different content areas within the page. You might need a list of pages for the sidebar, a list of testimonials for the right hand content area and a category with its composed subcategories and products for the main content area. Personally I solve that problem by just calling a single controller method for the main content area and then calling a page template. If it finds any other dynamic content areas each one of those can make their own independent controller method call. This is important as the template displayed (and hence what dynamic areas are required and what type of content they should contain) can depend on the page, user roles, time of day, or a bunch of other things so instead of having to keep track of which view template will be run (and hence which content areas will be required and what content will be required for each), the views can just say "get this content area" and a generalized content area controller can call the appropriate model methods to get the data that they need depending on the business rules.

What Does an HTML Controller Do?
In the general case, an HTML controller method will be called based on some combination of URI and URL and/or form scoped variables. It then may need to perform some logic based on page, URL, form, session, cgi and/or cookie scopes and then either call another controller method or a model method. Based on the response from that model method (was the save successful, etc.) possibly combined with other state information (cookie, URL, form, session, etc.) it'll either just return the data along with a screen name to the method that called it, or it'll call another controller method or cflocation to another page (such as "if edit successful, go to list page").

At first I despaired being able to generate such code. If ORM is the Vietnam of computer science, freely structured logic is the Vietnam of code generation - you can write a language to generate such logic, but then you're writing your own (suboptimal) general purpose language. However, as with model methods, when you go verb searching a combination of parameterization and conventions allows you to generate most of the functionality required.

Verb searching? Well, think about most of the actions you write in your controller. If you were to describe them a huge amount could be described using the format: Verb & optional-modifier & ObjectName. Add Page, Approve User, List New Articles, Delete Expired Carts, List All Products, Search Products, etc. So the vast majority of them can be specified in terms of ObjectName, VerbName and ModifierName, with an object controller being called which will run the appropriate verb on the appropriate object. In this way, most "feature" methods can be described using simple parameters (feature name, action name, object name, object action name) and unless the code for editing a product is different than for editing a user, it can just call the edit method in the base object controller.

[Apologies if this is becoming heavy going - it's been a long day and right now I'm just trying to make this clear enough that *I* can understand it - feel free to post a comment if any specific questions . . .]

So, what would this kind of application look like? Firstly there would be a set of sub-directories under "Controller" with one for each class of controller implemented. Under HTML there would be a BaseFeature and any features that had methods that couldn't be generated based on parameters. There would also be a BaseObjectHTMLController with all of the generalized add/edit/delete/list/search/approve/(add your other favorite verbs here) controller code for HTML requests and with actual object controllers for any objects that need to overload any of the base controller methods (so if you needed to have a UserHTMLController because you had to hard code special edit controller code for users, that'd be there - if you didn't need a ProductHTMLController, it'd just instantiate the BaseObjectHTMLController instead).

OK, I think that's enough for one posting and it gets me close enough to start refactoring towards this and sketching out the DSLs to start writing the generator and metadata API for controllers. Any thoughts always appreciated thought . . .

Comments
Peter, this didn't mean to come out as a rant....sorry, it just sort of happened. Not saying anything with any antagonistic intent, just exactly honest responses that are what I would say to anyone I was working with who raised these issues.

----

Seeing this much text about controllers worries me!

> So, what kind of Model API would be able to interface with controllers
> for all of those classes of input?

None! A model shouldn't know anything about "classes of input," its format, etc. Keeping this intact is what a controller does, and that's really about all that needs to be said about controllers!

> The next question is what the model should return.

Either a simple type or a domain object. Nothing interface specific, like XML or JSON or anything crazy like that. Translating to this is the job of a controller/service tier - remember, controller = knowledge of view & view format, not the model!

I'm almost feeling like you've confused the terms "model" and "controller" with all the talk about data transport formats the model is "aware" of.

----

Your model should no nothing about whether it's dealing with any given format of presentation. To answer your question, shifting model data to a format understood by the client is the job of the controller - whether that's a controller in a Web framework or a control layer spread across clients (e.g., a ColdSpring Aspect translating domain objects to JSON for consumption by an Ajax framework).
# Posted By Joe Rinehart | 5/9/07 9:44 AM
Hi Joe,

Apologies - it was late last night (I'm on British Summer Time right now) and I probably didn't make the posting as clear as it should have been. Just to clarify:

I wasn't suggesting that the model API have any awareness of any of those classes of input. I did want to make sure that it was appropriately designed so that I would be able to write controllers for all of those classes of input and that the model API would still be up to the job. For instance, there clearly need to be support in the general case for passing some kind of optional "session key" as part of all model calls so that if the call requires permissions, the appropriate user authentication can be performed within the model call. Right now I don't have that in my model API and it isn't a problem for calls from my HTML controller, but it could be for SOA web service calls.

As for returning, I return an IBO which is a simple domain object supporting smart getters and setters but that encapsulates a collection of 0..n items to handle the performance issues in CF with returning large collections of transient objects. I absolutely agree that XML and JSON and the like would be the responsibility f the appropriate controllers that would iterate over the IBO to compose the appropriate message package.

So, thanks for the input. I agree 100% - sorry it didn't come across very clearly!
# Posted By Peter Bell | 5/9/07 10:46 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.005.