In Praise of Pages
For most applications, a major goal for developers is to program in a language that is relatively comprehensible to the client who has to specify the requirements. If you're coding for loops and they're talking insurance coverage rules, that mismatch will typically make both specifying and maintaining the code more difficult than it needs to be. This is one of the big drivers of Domain Specific Languages - allowing programmers to write solutions that (at least at a high level) are described in terms of the problem domain.
One of the big trends in ColdFusion frameworks has been the move from a page controller model to a front controller. In this posting I am going to argue that for many use cases this is not a great choice.
For true web applications, an event metaphor works quite well. I like the Fusebox style naming convention of circuit.fuse that a number of MG and M2 developers also use. So URLs like index.cfm?event=cart.add are quite appropriate for web "applications".
However for web "sites", I find that most users think of a site with sections (often relating to topbar links) that are comprised of a number of pages and I often get requirements such as "in the about-us section, have a list of testimonials in the right hand sidebar" o all of the pages to describe secondary content area functionality.
Of course, there are a number of ways of implementing this in a front controller, but because events don't have a natural hierarchy (I guess you could have an n-dot notation with event=about-us.history.founders.peter.moreinfo but I haven't seen that in the wild).
However, given that the user already thinks in terms of pages which have a parent, section, display order and the like, why not just have a page object and use that to drive the functionality to present?
The main downside of traditional page controllers (such as those common in .NET applications) is that if they aren't designed well you actually have real controller code in each page, so if you want to have three pages all of which implement an article list, you'd have to replicate the controller code or make all three requests go to the same file. To me this is an unacceptable coupling between file system and functionality, but it is very easy to implement a "page controller" (in the past I called it a pseudo page controller) where you just use pages as a metaphor and then route to a front controller that takes the properties of the requested page and uses that to drive the functionality to display.
Such a solution allows for the conceptual comfort (for users) of a site with pages while still allowing for the code reuse benefits of a front controller as a page doesn't include any code - it just sets some properties that will affect what code to run.
So, how does this work in practice? Well, firstly you need to have a way to represent pages. You could just create files manually in a directory structure, make them set a few properties (Page.Title, Page,SectionName, etc.) and then include the front controller, but we keep pages in a database to make them easy to use and then either generate stub pages or (preferably) use URL rewriting to pass a file path to the front controller (say filepath=about-us/history) which then asks the PageService to return a loaded Page object with the necessary properties.
For the primary content area we allow a page to define a feature to use (a controller - catalog, cart, article-list, etc.) and a default method to run (cart.list, catalog.categoryview, etc.) as well as any properties to configure the feature if you'd like the article list on this page to be a little different from the article list elsewhere in your site. In this way a non technical user can easily add pages to a site and select pre-built features, so if you've coded a calendar for the about-us/events page and they want to add it to a new contact-us/holidays page then they can do so without help from a programmer.
More importantly, with a page model, you can easily write controllers for secondary content areas (maybe a right hand sidebar) saying things like "If Page.SectionName EQ 'about-us' then call the testimonial-list feature" which makes for a really expressive set of controllers for any secondary content areas.
The page controller model provides for extremely search engine friendly *and* meaningful URLs, allows end users to manage the URLs (so you don't have to be involved in changing all the event names to make them better match your new key word optimization strategy when the new marketing guy comes in), provides for the reuse of functionality within a site by non-technical users and makes it easy to describe secondary content areas using concepts like pages and sections that are fairly intuitive to business users. And because the pages don't actually have any code, there are none of the downsides experienced with old style page-controllers.
Of course, if you are building true web applications where a page metaphor is inappropriate or meaningless to the business users, an event based metaphor makes more sense, but for the applications I build I have found a page controller to be much more flexible and maintainable.
I know that you can conceptually implement any of this using an event based model, but I really don't see why you'd bother! Any thoughts?



I think you have some good ideas here, but I cringe at your mention of using URL rewriting. I know this method is popular, but it seems to me like it's an unweildy and cumbersome solution. But, I've never tried it so I'm speaking from inexperience here.
/section/page.cfm
to:
/index.cfm?fuseaction=section.page (or the M2/MG equivalent)
Would that address your concerns (since you talk about routing from pages to a front controller behind the scenes)?
Not really, because that assumes a single level of page hierarchy. There is no elegant way to express fuseaction=section.page.subpage.sub-subpage and so on. There is no question that it is possible to use a front controller style to replicate anything you can do using a page controller. The question is which is most elegant for the class of use cases where you want to be able to describe a site as a tree of pages.
My requirements:
- Non technical user can add new pages to site using web based admin (which uses same code to manage pages as to manage users, products, categories, etc. - no reason to create a special case here) and just select from a list of pre-programmed features for each page.
- It is possible to express the functionality required in secondary content areas as a function of the page name, parent name, and/or section as this maps to how many end users think about a site. (Not saying you shouldn't also be able to make it based on time of day, whether they have registered, or a bunch of other things, but I *also* want to support this).
- Non technical users can easily move a page from one section to another just by editing the Page.Parent if they decide to move the founders bios from About us to History and any appropriate changes to secondary content area will be taken care of automatically.
- Non technical users can change the URL to get to a piece of functionality just by changing the page title (page name is generated based on page title by making all lower case, removing all special characters and replacing 1..n spaces with a single hyphen) so they can change page and section names as they SEO or other requirements vary without bugging a programmer.
- All URLs are search engine friendly and technology independent (I make everything .html so if I regenerated a site in a different language that wouldn't affect the URLs at all).
I'm not saying these problems could not be solved using a front controller, it just seems like a more elegant fit to use a page controller. The only downsides (I see) with a page controller are those I listed above and with this implementation where there is no actual controller code in any given page effectively removes all of those issues.
Anything I'm missing (for the set of use cases where these are a valid set of objectives - I admit that a true web app as opposed to web site may not fit as well with this model)?!
I think URL rewriting is actually a pretty elegant solution. I've always been in a rush and run into some bumps with ISAPIRewrite (I run IIS) so I haven't actually implemented URL rewriting and use a page publishing tool to crate stub pages, but I actually find URL rewriting a much more elegant solution that I'll get to as soon as I get a moment - especially when people start renaming top level pages and you have to go ahead and rename directories and the like - it becomes a pain.
Great posting. I really agree with the "page" metaphor being appropriate to many situations. I used to use Fusebox and I did use SES URLs (though no rewrites). Still, it wasn't as easy for the users or editors of a site as it has been since I dropped Fusebox and moved to a page metaphor.
I'm sure that there is a point where a system is sufficiently complex that this model can break down, but I have written some fairly large sites and that has yet to be the case for me.
I just started using page controllers a weeks ago (after having not had a real controller for a it), and I have found that they are really useful. Certainly the point about duplication of functionality is well taken and I can see the advantages of a front controller - but I worry that unless that is done carefully you could lose the very valuable page metaphor which is so natural on the web.
PAGE VS FRONT CONTROLLER
I have also been thinking about page controller for ColdFusion recently (Learning ASP.NET). Page controller and front controller solve the *same* problem, and as you mentioned, one may be more appropriate that the other depending on the application. For those who are not familiar with page controller, it might help to think of it like this:
User.cfm – User display logic
UserControl.cfc – Controller for the page. It maps the view to your model components.
When a browser requests User.cfm, UserControl.cfc processes the request and gives the view what it needs. The controller also handles events related to the page (CreateUser, EditUser,Etc)
My experience with page controller is that it makes it easy to duplicate code and put business logic in the controller (not that it’s not possible with front controller). That said, page controller does have some benefits. It eliminates the need of big xml files, provides an easy way to organize code, and can be really powerful when implemented in a framework (See .NET page controller model).
Sorry for the long rant on this…I’d love to see a hybrid! “Frage Controller?"
SES URLS
URL rewriting has become a major concern for me when developing applications, but I’m not sure that a framework has to be specifically designed to support it. Take a look at the site below. I am using standard Mach-II and a combination of plugins and filters to achieve this result.
http://cnm-albuquerque-nm.irecess.com/sharing/dr_r...
-Mitch
I am in agreement with pretty much everything you said in this post. I adopted Adam and David Churis' Plum framework a couple years ago, which is essentially a page controller
framework (before everybody rolls their eyeballs, hear me out). Even though Plum never gained widespread adoption for several reasons, as a framework it did certain things very
well. One of these was in the way they used a pages.
Plum has a built in CMS, which is pretty functional, although nowhere in the league of a FarCry or something like that. They use page templates which have 3 lines of code in them, which call the header and footer, with the page content in between. All display content is driven through a custom tag calls which handle display logic and CFCs which handle the model stuff, much in the same way that Mitch stated previously. You could turn this into a front controller with a little work, but I haven't seen a compelling reason to do so yet. I am another one who doesn't like SES url rewriting.
Allowing, users to create 'website' pages to their hearts content and preview them is nothing new. Where it really gets neat is when you start to embed CMS content
into forms, lists and reports. It is very easy to create content sections that allow the user to manipulate dynamic text content on forms. This allows them to maintain their own form instructions or system wide context-sensitive help for instance.
The page controller handles this type of funtionality very well, because the user can point the content at the template, and preview it until they get it right, form and all. I haven't seen this kind of functionality in any sample apps for any of the current MVC frameworks, although it may exist out there somewhere. If somebody can point me to one, I'd love to see it. I have spent a lot of time reading and playing with Fusebox and Model-Glue, but I can't grok how to implement this kind of functionality in those frameworks using the front controller and/or MVC, and that has kept me from moving on. I like the page controller model and haven't seen a compelling reason to change to this point, although I am all ears.
I really like these pragmatic vs academic arguments that you keep yacking about. Keep it up.
Couldn't agree more. Front controller is usually a bad fit for section/page-centric web sites. Without URL rewriting, it becomes even more of an issue with search engines and especially statistics tracking as most stat packages are based around reporting page level data as opposed to query string parameters. Simply using cfm "pages" as markers while still retaining much of the request/response control in a behind-the-scenes front controller is a much better fit than depending on a front controller explicitly. With that said, I still think front controller is ideal for web "applications" as you put it. Many of the sites we develop for clients are usually broken up into two separate applications both working off of the same data. One being the page controller based web "site" and the other being the administrative app which is usually a good candidate for front controller.
@Mitch - my approach is indeed a "Frage controller". Pages don't include code so no possibility of code duplication but still get benefits of the page metaphor. A framework doesn't have to be specifically designed to support URL rewriting and I seem to remember Matt or Peter making a really cogent post about why it wasn't part of M2 and shouldn't become part of M2. I agree. That said, as Ruby on Rails has shown, if a framework "knows" URLs and URL rewriting it can provide you with a bunch of easy conventions for simplifying your application.
@Jeff - There in nothing you can do in a page controller that can't be done in a front controller so it isn't a reason *not* to use MG/M2/FB, but equally I don't find a compelling reason to use a traditional event driven front controller when - for my use cases - this approach gives me the best of both worlds!
@Tom - Great point. You can actually include web applications quite easily within the pages of a "page" controller, but I am playing with an alternate REST inspired admin interface as then you always know that /user/edit/23 will allow you (assuming sufficient priviledges) to edit user 23 which is kind of cool for an admin URL convention.