Designing Framework-Agnostic Models with CFCs, by Brian Kotek

Notes from Brian Kotek’s talk on Framework-Agnostic Models at Frameworks 2007.

To get a good handle on what constitutes a model, Brian starts by going over just where the model lies in the MVC pattern relative to frameworks. Adding queries to your machii listeners directly, or act pages in fusebox, or controllers in model glue is a way your models bleed into your controller. Logic is only reusable by cut and paste, and it’s coupled to the database implementation. The end result is that your controller contains your model logic, when it should really only be controlling your model calls. A better way involves calling the service call here and passing in the values you need. On the other side of the coin you wouldn’t want to pass in a machii event to your model, as that couples your model to your controller as well. Passing values provides a cleaner way, and doesn’t depend on the framework.

SO where exactly does the controller end? In MachII it ends at the listener CFCs. In Model-Glue, it’s the controller CFCs. As for Fusebox, he agrees it’s the Circuit.xml file (hey, that’s 3 people hinting at using circuit.xml instead of act pages).

Queries, references to session scope and business logic should all be in the model. Any framework specific things like the event and the form elements should be handled in the controller with their values passed into the model. For session scope Brian mentions using a session facade in the model, which allows it to be treated like any other object.

With this form, things are properly encapsulated making reuse easier, dependencies minimized and changes much easier in the long run. By adding a service layer to encapsulate a model, it exposes a set of services to be used by any external system. This provides a stable API to the model that keeps it independent of the controller. Think of it as the gatekeeper.

Why bother with all this? You’ll be able to switch frameworks (as noted in Matt’s talk earlier), you’ll be able to easily allow flash remoting, web services and ajax calls using the model, as well as easier team development, debugging, testing and maintenance.

In his example he uses the same model in MachII, Model-Glue:Unity and Fusebox 5.1. All of these also use Coldspring which allows for automatically creating remote facades which is very slick. Framework independent service layers that are only dependent on coldspring? I didn’t realize how this worked, but it’s actually a form of code generation. You declare a cs bean of class coldspring.aop.framework.RemoteFactory and provice the target, servicename, the relativepath (where the generated file will go), the method names and the beanFactoryName. I think Chris Scott went over this a little yesterday.

His example also uses a custom made service layer, but DAOs and Gateways generated by reactor. In the end with all this almost all the code is generated! Basically you’re creating the service layer, telling coldspring how to get the supporting objects (bean, dao, gateway) and letting it go from there. I was expecting some static gateway/dao methods actually, so this was a nice surprise usage of Reactor and probably the cleanest form of a service layer I’ve seen. I’m not sure why this presentation was in the beginner room, but it’s one of the most popular talks I’ve been to by the room size and amount of questions alone.

If you enjoyed this post, please consider to leave a comment or subscribe to the feed and get future articles delivered to your feed reader.

Comments

Hi,
Interesting post…as something of an OOP noob, this may be off track, but any ideas, in your opinion, on whether it really is that cool to refer to session scoped variables (even using a facade) within a model, if flexibility is the main goal…what about pulling apart the session scope in the controller and then passing in the required values/objects, keeping the model API as clean as possible…essentially taking the session scope out of the picture completely before getting down to the model? Would this not allow better reuse of the model API in terms of Flex, AJAX, WebServices, etc.

This is really more of a clarification request, as I’m just getting my head ’round MVC on the server - not something I’m overly convinced about yet :-)

cheers,
stigg

[...] Brian Kotek also posted code samples from his talk on Framework Agnostic Models on his blog. Just check out the link on the right side to “Framework-Agnostic Models Code and Presentation (Frameworks 2007 Conference)”. I felt like this presentation brought together ideas from just about every other talk at the convention and not only unified them by presenting the same code in multiple frameworks, but expanded on them with by introducing the service layer as the unifying API to the models. Definitely worth a look! Tags: Coldfusion, fusebox [...]

In the past I’d always put my session logic in the controller as well. Only recently I started using a session facade, which in my case was the same one used in Doug Hughes used that’s included in the sample blog application that comes with Reactor. Basically it’s a generic facade in the coldspring declaration where you pass in the scope you want to make a facade for (in this case the string “session”, and it provides generic getters/setters that match up with model-glues syntax (ie, getValue(”somevarInSession”) which will return an empty string if that value isn’t found).

Brian Kotek had a different take on the session facade though. Instead of linking it to a scope in coldspring, the sessionFacade is the only place in the application where you use the global session variable directly. For instance, asking the session facade for getRecentlyViewedProducts(), gives back session.recentProducts. Likewise the only place values in the session scope are set is in this object as well. It does seem like there is a good deal of business logic associated with controlling the session scope that would otherwise have to go in the controller, but maintaining that in the sessionFacade object clears all that out.

As for when the session facade is used in this case, it’s easy enough too. It’s only used in the service layers it’s associated with. So for instance, the product service layer will have the sessionFacade object passed in via coldspring and be able to call things on it. For instance, the CartService which controls what shows up in the users cart works with the session service to control that by calling things like getCart(), addToCart() and clearCart() on the session facade. Looks like this turns the session facade into just another business object.

Great stuff Adam, plenty of food for thought there…thanks.

[...] Putting it all together To be realistic though, you have to take into account a few more things. Obviously this shouldn’t be run when they call the user/create page, it should be run when thy submit the form. Also, what if there are errors? What if we have more related fields so it’s not just dealing with the user but a few other things? Well, I’m not quite there yet in some of those cases, but we can make it a little cleaner. As I said, this version of cfwheels has no model components, it is ONLY a controller. The question is what do you want in your framework? Brian Koteks presentation on Designing framework agnostic models showed just how little the framework can handle, and how important it can be to have things defined in a service layer. So what if you use Cfwheels with this service layer? Turns out it plays pretty well. [...]

Leave a comment

(required)

(required)