Controlling the Catalog
According to DHH's recent comments, I should simply expose CRU and D methods (/product/view/7 or /category/view/12). But I've already decided that four verbs don't a controller API make. So my biggest question is whether to expose my service objects and verbs or whether to add a "feature facade" . . .
Service Objects Exposed
A very simple and clean approach is to create a base controller and one controller per service object (here are some previous thoughts on base classes). For a simple catalog you end up with a CategoryController and ProductController, both extending BaseController, so you can just use base methods for list, admin list, view, add, edit, delete, search, import, export and simple reports – just setting a little metadata in the object specific controllers and only overloading methods where you need a completely custom implementation or adding methods where an object has unique verbs (perhaps checkInventory for a product). While you are not exposing the service objects per se, the very fact that you are creating one controller per service object means that fundamental changes to your object model will not be encapsulated as they should.
A Feature Façade
In the past I have always used a feature facade where I could add one controller per purchasable feature to my projects. You wanted a catalog, cart, checkout, newsletter or discussion group? I added a configurable controller for that feature and then provided non-technical site admin users with the ability to associate that feature to any page(s) they wanted, setting certain properties on a per page basis. This made it very easy for a non-technical user to drop a newsletter into two different pages on the same website and to manage two different newsletters with different properties just by filling out an auto-generated configuration screen. Given that I use a software product line approach to development (I'll blog MUCH more on this later - this design pattern stuff is just the necessary prelude to the application generation content), I really like the flexibility and configurability this provides.
So, for front end functionality, I'm going to create one controller per "feature" as this has been really useful in the past. In the case of a catalog, I'm going to provide a catalog controller with viewCategory(), viewProduct(), searchProduct() and advancedSearchProduct() methods as a very thin customizable facade over the service objects which will do the heavy lifting.
But What About the CRUD?!
While my clients are extremely picky about the configurability of the front end, they are usually much more pragmatic about the interface and functionality of the administrative interface (given how inexpensive the solutions are, they should be!). In the past I had an "administrator" controller but I always found that to be a little clunky. Instead I'm going to go for the much more discoverable and intuitive service object controllers described above for administrative functionality. It'll mean I can generate basic CRUD functionality very easily and with a bit of URL rewriting down the line (for now I'll just use URL/form variables as I've had problems getting a URL rewriter to play nice with IIS although I know it's possible) I'll be able to offer a very Railsy /#verb#/#object#/#attribute_value# admin URI interface (e.g. edit/product/12). Of course, discoverability makes administrative security a much more serious concern, but that's a topic for another post!



There are no comments for this entry.
[Add Comment]