Wheels MVC "Best Practices"

50 views
Skip to first unread message

Chris Peters

unread,
Mar 30, 2009, 9:24:27 AM3/30/09
to ColdFusion on Wheels
One thing that I love about Wheels is that it's very flexible. We
mention in the documentation that you don't even need to use all of
its features (for example, the model stuff is optional).

But if you're anything like me, you may sometimes wonder if you're
doing everything the best possible way. So I thought it might be
interesting to discuss some "best practices" for doing things in those
"gray areas" that Wheels sometimes leaves open. Sometimes we give you
the rope so you can hang yourself. :)

My biggest question is when it's appropriate to use certain tags, CFML
features, and parts of the Wheels framework itself. Also, here are
some other random thoughts.

* My inclination so far has been that only the controllers should be
accessing session data. Those values should be passed to views via
other variable names.
* Is it appropriate for view files to access config variables, or
should those values be passed as different variable names from
controllers?
* What if I want to consume a web service, be it SOAP, RSS, or some
other flavor of XML/JSON? Should I create a model that handles that
data interaction?
* Helpers are pretty cool because they act as a standardized UDF
library. I see a lot of potential of downloading UDFs from places like
CFLib.org and just pasting them into the helper file(s). This is
getting me pretty stoked about writing a chapter about helpers.
* Does Wheels make custom tags obsolete? I've found myself taking
custom tags and doing some work to turn them into helpers/controller
methods. I've done this with the reCAPTCHA tag on cfwheels.org Docs
section. (http://recaptcha.riaforge.org/) The part that displays the
tag is a helper, and the part that does validation is a method in my
base controllers.Controller.

Has anything else similar to this been nagging at you? If you start
thinking about it, does anything nag at you?

raulriera

unread,
Mar 30, 2009, 10:42:01 AM3/30/09
to ColdFusion on Wheels
I would go with:

1 - Yes
2 - No
3 - I would do this in the controller (the calling the XML, JSON,
etc)
4 - Oh yeah
5 - I dream of the day that view functions will be custom tags :) (I
will do this someday)

<wheels:form>
<wheels:input type="text" name="hi" />
</wheels:form>

rip747

unread,
Mar 30, 2009, 3:33:48 PM3/30/09
to ColdFusion on Wheels
* My inclination so far has been that only the controllers should be
accessing session data. Those values should be passed to views via
other variable names.

Views should be completely "isolated" from your "applicationlogic" or
global variables which sessions consist of. While some people don't
totally agree with that approach, it makes it easy to use the view in
other areas of your application and "layer" them onto one another.

* Is it appropriate for view files to access config variables, or
should those values be passed as different variable names from
controllers?

See answer #1

* What if I want to consume a web service, be it SOAP, RSS, or some
other flavor of XML/JSON? Should I create a model that handles that
data interaction?

Web services are to me considered business logic and as such belong in
models. having them at the controller layer is not very DRY as other
controllers might need the functionality as well. When consuming most
web services you need to "massage" the data and response to fit your
application logic and that is what your model is for. Also ask
yourself this: isn't retrieving data from a web service basically the
same thing retrieving data from a databases? Sure there different
setting and methods of retrieval, but the idea is the same: your
requesting data so it should go in the model layer.

* Helpers are pretty cool because they act as a standardized UDF
library. I see a lot of potential of downloading UDFs from places like
CFLib.org and just pasting them into the helper file(s). This is
getting me pretty stoked about writing a chapter about helpers.

There is no reason why we couldn't use the basic logic behind the
pluginmanager and tweak it to work with cflib.org. all your doing is
cfhttping a page, grabbing data from it and throwing it into a file.
Which brings up an interesting thing: you could host something on
cfwheels.org that bridges the pluginmanager to different sources, such
as cflib.org, the wheels plugin page, riaforge.org or other resources.

* Does Wheels make custom tags obsolete? I've found myself taking
custom tags and doing some work to turn them into helpers/controller
methods. I've done this with the reCAPTCHA tag on cfwheels.org Docs
section. (http://recaptcha.riaforge.org/) The part that displays the
tag is a helper, and the part that does validation is a method in my
base controllers.Controller.

I was thinking the same thing, but after reading raul's response, I
sort of salivated a little. What i think he is dreaming of is a
template language for wheels. While I wish we could do this is
straight cfscript and functions, we can't since cf doesn't support the
concept of blocks at the function level, but it does at the tag level.
This means if we wanted to write something of a template language, we
would have to do it in tags, which to me isn't such a bad thing. That
said, whoever uses or codes CFX tags nowadays should be SHOT!

Chris Peters

unread,
Mar 30, 2009, 3:46:26 PM3/30/09
to cfwh...@googlegroups.com
I'm with you on the web services in the model layer, Tony. I guess in practice though, it depends on how far you want to go with your abstractions. The call to the web service technically *is* an abstraction of its own, as long as the web service never goes away. I guess it depends on how "safe" you want to be and where you want duties to be divided in your app.

It's tough to strike that balance, so I always try to remind myself of this interesting post by 37signals' Jamis regarding "future creep":
http://www.37signals.com/svn/posts/1324-beware-of-future-creep

Raul's idea about using custom tags in views makes me salivate too. I know I've started a thread about that in the past and that someone made a quick attempt at doing it (maybe it was Raul?).

Allen

unread,
Mar 30, 2009, 5:42:28 PM3/30/09
to cfwh...@googlegroups.com
As for Web Services, my question would be how is it a big deal to put them in the model?   Setting aside the more academic side of things, that it represents properties of objects for your application, on a practical level what sort of extra work is involved? 

Usually when getting or sending data using a web service, you'll want some sort of validation, just like with data coming or going to your db.  And validation often involves enforcing business rules.  So what I see one doing in putting that in the controller from a practical side is creating a mess from the start.  It may not seem messy but how often do you use that data for just one flow right from the start let alone in making enhancements just down the road?  At best someone's going to either have to duplicate that code in another controller, likely during the same iteration if not soon after.  And exactly how much, if any, more time did it take to put the WS in the model in the first place?

I don't see how anything is gained at that moment.  And any chances that occur, which they will, will very likely become problematic.  I don't see putting that in the model as being academically correct that real world practicality is why it's considered academically correct.

But that's just my two-bits worth on that one.

--Allen

Chris Peters

unread,
Mar 30, 2009, 8:32:28 PM3/30/09
to cfwh...@googlegroups.com
That's a great point as well. I haven't had any need to connect my Wheels apps to any web services so far, so I haven't put a lot of thought into it.

So the validation logic would make a lot of sense in the model, adding errors to the model's validation if anything fails.

ch...@clearcrystalmedia.com

unread,
Apr 7, 2009, 2:08:38 PM4/7/09
to ColdFusion on Wheels
Here's a question. Is it appropriate for a model to access a config
variable or should the controller pass that in?

Allen

unread,
Apr 7, 2009, 2:21:23 PM4/7/09
to cfwh...@googlegroups.com
Chris,

Bless your heat for asking this.  I relish ever opportunity I get to say "loose coupling".  **SMIRK**

If you want your objects to be loosly coupled, I would pass it in.  Will the world end if you don't?  I don't think so.  Sure, that variable name could change at some point.  But what are the chances of that?  Personally, I do pass it in since it gives me more flexibility.  I like to my variables fully spelled out and named for what they represent.  I've found in re-factoring I occasionally find the variable name isn't appropriately named and I'm going to change it.  This means I only need to change it in 4 place instead of .... well, probably 4.  I mention that to show why I don't think it is a big deal.

There are of course situations where it's handy.  But when it comes to config variables I don't see it happening often.  Most of the advantage in this case is consistancy.  If you're normally passing in other variables, keep it consistant and do the same with config variables.

Just my two-bits worth.

Allen

raulriera

unread,
Apr 7, 2009, 3:30:42 PM4/7/09
to ColdFusion on Wheels
A wheels config variable? sure, just use get("variableName") if its a
variable of your own, then pass it in ;)

Per Djurner

unread,
Apr 7, 2009, 4:44:15 PM4/7/09
to cfwh...@googlegroups.com
What kind of config variable?
Do you have an example... it's always easier to answer when you have a real world situation :)

Chris Peters

unread,
Apr 7, 2009, 5:28:56 PM4/7/09
to cfwh...@googlegroups.com
So let's say in config/settings.cfm, I do:

<cfset application.encryptionKey = "i.love.peanut.butter">

And then in the base model at models/Model.cfc, I do:

<cffunction name="encryptData">
    <cfargument name="data" type="string" required="true">

    <cfreturn Encrypt(arguments.data, application.encryptionKey, etc...)>

</cffunction>

My guess would be that everyone would say WRONG, but I wanted to open it up to discussion, being the evil marketing guy that I am. >:)

rip747

unread,
Apr 7, 2009, 6:54:53 PM4/7/09
to ColdFusion on Wheels
@chris

here is my personal rule on loose coupling and models.

if the model is a model, then you don't have to worry about it.
if the model is really a library, then yes you should use loose
coupling.

now what is the difference between and model and a library you ask? a
model is code that will be used for ONLY this application and not
reused in another. a library is the opposite, code that will be
included in this application and can be reused in others.

a simple example of a model would be a component for that abstracts a
table in your database (the basic wheels model). will you ever use
that model in another application? chances are you won't, so what do
you care if you're accessing application wide variables or loose
coupling.

now a library that creates a CSV file should be loosely coupled.
chances are you'll want to use that code again in another application
and maybe even share it with others. how would that happen if it's
accessing variables that are only specific to your application?

hopefully this wasn't confusing as my logic sometimes is.


On Apr 7, 5:28 pm, Chris Peters <ch...@clearcrystalmedia.com> wrote:
> So let's say in config/settings.cfm, I do:
>
> <cfset application.encryptionKey = "i.love.peanut.butter">
>
> And then in the base model at models/Model.cfc, I do:
>
> <cffunction name="encryptData">
>     <cfargument name="data" type="string" required="true">
>
>     <cfreturn Encrypt(arguments.data, application.encryptionKey, etc...)>
>
> </cffunction>
>
> My guess would be that everyone would say WRONG, but I wanted to open it up
> to discussion, being the evil marketing guy that I am. >:)
>
> On Tue, Apr 7, 2009 at 4:44 PM, Per Djurner <per.djur...@gmail.com> wrote:
> > What kind of config variable?Do you have an example... it's always easier

Per Djurner

unread,
Apr 8, 2009, 8:09:25 AM4/8/09
to cfwh...@googlegroups.com
I agree with Tony, that sounds like a good approach.
/ Per

Chris Peters

unread,
Apr 8, 2009, 10:19:39 AM4/8/09
to cfwh...@googlegroups.com
If a model is a library, then should it even extend the base Model? If it's a library, then we're adding the dependency on Wheels. What would be the pros and cons of each approach?

I'm not seeing much value in defining a CFC as a Wheels Model if it doesn't interface directly to a database. Maybe you can prove me wrong.

rip747

unread,
Apr 8, 2009, 11:20:53 AM4/8/09
to ColdFusion on Wheels
@chris

"If a model is a library, then should it even extend the base Model"

no it shouldn't.

thing is, that in wheels we have the "model" directory where i've seen
in past posts that we tell people to put all their model components in
even though they aren't really model components but libraries. now in
rails there is actually a lib directory where you would put these
components. this separates your "models" (which only really deal with
database abstraction via activerecord) and libraries (which are
components that you reuse; you also have gems, but that's another
thing entirely). maybe wheels needs a lib directory to separate model
and libraries on a physical level and make this less confusing, who
knows.


On Apr 8, 10:19 am, Chris Peters <ch...@clearcrystalmedia.com> wrote:
> If a model is a library, then should it even extend the base Model? If it's
> a library, then we're adding the dependency on Wheels. What would be the
> pros and cons of each approach?
>
> I'm not seeing much value in defining a CFC as a Wheels Model if it doesn't
> interface directly to a database. Maybe you can prove me wrong.
>
> On Wed, Apr 8, 2009 at 8:09 AM, Per Djurner <per.djur...@gmail.com> wrote:
> > I agree with Tony, that sounds like a good approach./ Per

Chris Peters

unread,
Apr 8, 2009, 1:41:03 PM4/8/09
to cfwh...@googlegroups.com
Perhaps that what "miscellaneous" should be renamed to?

raulriera

unread,
Apr 8, 2009, 2:52:48 PM4/8/09
to ColdFusion on Wheels
Why aren't libraries plugins?

GCopley

unread,
Apr 11, 2009, 12:13:24 AM4/11/09
to ColdFusion on Wheels
Hey everyone, what say you to having a page in the documentation
called "Best Practices" or "Good Practices" that list some of the
things discussed here. I think it would be very helpful especially to
people like me who have been programming for some time but are just
now learning/using the MVC design pattern and methodologies.
> > > > >> > >> > thinking about it, does anything nag at you?- Hide quoted text -
>
> - Show quoted text -

Chris Peters

unread,
Apr 11, 2009, 9:12:55 AM4/11/09
to cfwh...@googlegroups.com
That's a great idea, actually. And I'm glad you're finding this discussion useful. I figure that there are probably a lot of lurkers out there who are getting some value out of it.

raulriera

unread,
Apr 11, 2009, 7:29:06 PM4/11/09
to ColdFusion on Wheels
Ok, Im pro that too, how do you want to handle this Chris? a page in
the Wiki? who determinate what gets written in there?

Chris Peters

unread,
Apr 11, 2009, 7:48:04 PM4/11/09
to cfwh...@googlegroups.com
I could start it out based on what we've come up with in this conversation. I'll let everyone know when it's there...

Per Djurner

unread,
Apr 13, 2009, 5:57:30 PM4/13/09
to cfwh...@googlegroups.com
I like the idea of a "lib" folder.

What if Wheels looked for CFCs in the "lib" folder on start-up and just made them available for you in the application scope?
Would that make sense?

As an example, let's say you find a useful PayPal CFC on RIAForge.
You can just drop it in "lib" and then call it with application.payPal.someMethod() from anywhere inside your app.
Or maybe application.lib.payPal to avoid clashing with other items in the application scope.

/ Per

Chris Peters

unread,
Apr 13, 2009, 7:56:21 PM4/13/09
to cfwh...@googlegroups.com
I'm for the idea. The application scope idea is good and bad, especially bad if for some reason you wanted to create more than one instance of a CFC.

One idea that seems interesting to me would be the idea of Wheels creating mappings for folders put into the lib folder. So if I put a "paypal" folder in there that had multiple CFCs, then Wheels would create a mapping on application start for "paypal." That way I could call CreateObject('component', 'paypal.ComponentName').

Or maybe it could do both, and everybody wins!

Just throwing ideas out there. I'm not committed to one idea over the other. And my idea could be pushing it too far.

Per Djurner

unread,
Apr 14, 2009, 10:58:22 AM4/14/09
to cfwh...@googlegroups.com
Yeah, sounds like a good idea too.
The most common use of a 3rd party library I would think is to get it as a CFC and put it in the application scope though, right?

/ Per
Reply all
Reply to author
Forward
0 new messages