A few minutes ago Mike Henke asked an interesting question on Twitter. I suggested a Google+ post to allow others to hash it out, but as he isn't a big user of it, he suggested I blog it. I thought it was an interesting question, and I definitely have an opinion on it, but I'm very curious to see what others think.
Ok - so his question was simple:
Is it "bad" practice to put functions in Application.cfc? Does it pass a smell test?Since an Application.cfc file normally has methods in it, we should clarify the question a bit. Mike is asking if it makes sense to put additional methods in there. In other words, methods that aren't called by the server (onApplicationStart, onSessionEnd, etc).
My opinion is that you should not put additional methods in there unless they directly relate to the "documented" core events. So for example, I can see a case where onRequestStart and onRequestEnd may need to use similar logic. It makes perfect sense to abstract out that logic into a method they can both call. In all things try your best to follow the DRY (Don't Repeat Yourself) rule.
Outside of that though I would not put other methods in there. Keep the file focused on what it should be - handling the events for your application.
Archived Comments
What was that again? Oh yeah! KISS :>)
I don't see a problem with putting private methods in there if you have a lot of stuff going on inside OnRequestStart or OnApplicationStart etc in order to encapsulate code.
I see no issue in placing small methods in Application.cfc, for use by other methods of Application.cfc. In one instance it's DRY, but otherwise it's encapsulating your code into small, organized blocks of code that are easier to maintain. (I've seen some very long onApplicationStart and onSessionStart methods)
As Ray said, "Outside of that though I would not put other methods in there. Keep the file focused on what it should be - handling the event handlers for your application."
Yep, that about sums it up for me!
I'm pro-additional methods in Application.cfc provided they are:
1. Private and only called from within Application.cfc,
2. Are called meticulously with appropriate locks where thread-safe code isn't guaranteed.
The most common private method in my Application.cfc's is a method that constructs the model, caches it in a struct, and appropriately it returns to be either placed in REQUEST directly, on each page request (for development modes), or locked-then-written into APPLICATION once (in production modes).
Interesting starting consensus. I would think it would be over-kill since the cfc is ran each time a request happens. I did mark the function private as several suggested :-)
So from the group so far, something like cleanmystring() function won't pass the smell test. A private function to "get" settings in OnRequestStart is ok. Am I correct?
I would call it something like GetVariable or something more explanatory unless it actually cleans your string.
IMO, yes.
FWIW - as you know, you can load in UDFs for a request using a include and onRequest. I'm not a fan of that technique.
I'll normally make a CFC called util for all my random crap. I'll then put an instance in the Application scope. It's a bit more typing, but it means I can do my random crap like so:
<cfoutput>The date/time is #application.util.dateTimeFormat(now())#</cfoutput>
It also means that if my other CFCs need random crap I can just inject them in via ColdSpring.
I have only ever done this for functionality as it relates to Application events - as others have suggested, I will create a private function that gets called only from within another method in Application.cfc. And only for functionality that relates to one of the events.
Mike - it sounds like you want to create a method that will fetch data from the database, is this correct?
If it is, I am not sure that would pass the 'smell test'. I would not go so far as to say its 'wrong', but probably not something I would do.
I agree as well. I like to keep the application.cfc as clean as possible.
In the current big app I'm working on, we added one additional private method to application.cfc that builds our sites session structure and is only ever called from the onRequest method when needed.
But that's it. Keep it simple.
> I suggested a Google+ post to allow others to hash it out.
Who would see it if a Google+ post got started? Are we supposed to subscribing to something in Google+?
I don't want to be left out!
I have a hybrid wheels app & wanted the get function in on-request-start but the function wasn't defined so I decided to copy the function to the Application.cfc as a private function. I noticed a "cleanmystring" function in the Application.cfc. Didn't seem correct but then I practically did the same thing :-)
cfwheels get function
https://github.com/cfwheels...
Whenever I find myself adding a private method to Application.cfc I always stop and ask myself, would this server the application better in a Utility class. Sometimes the answer is "no", most of the time the answer is "yes".
What I usually end up doing is creating a private function in application.cfc that only serves as a proxy call to a utility function in another component.
@Phillip Senn: Heh, I originally thought this wouldn't spark so much attention. ;) I should know by now - the blog posts I think will get no comments get a butt load - and vice versa.
I agree with Ray's guidelines, I just wish there was somewhere good to put all of the utility type functions I end up needing in my application... I get tired of making utility.cfc files and needing to use them everywhere.
@Scott - it is getting an "environment" setting stored in the application scope. Basically, on request start, do this security check if "production".
Mike - that muddies the waters a bit. In a Model Glue application, that is something I would check in the Model Glue onRequestStart event handler. Not sure if there is an equivalent in CFWheels.
I don't like the idea of actual functions in application.cfc, other than those that directly interact with the core functions. For something like "cleanString", I usually have a utilities.cfc (really just a collection of UDFs) that I've substantiated and put into request scope.
I've extended the Mura practice of putting things like that in the $ scope. Short, consistent, managed by application.cfc, but the code is elsewhere.
I have an Application.cfc where I catch exceptions, long running requests, and missing templates using onError(), onRequestEnd(), and onMissingTemplate(), respectively. In each of these methods, I send an email to a notification email address, and I like the email content to include some scope variables and other information about the request. So, I created a simple private method in Application.cfc to return the email content that is shared. I think this ties in with your idea of keeping functions in Application.cfc related to the functionality of Application.cfc. I wouldn't put UDFs or anything else in there. I feel like Application.cfc should be viewed as an Object and you shouldn't put random functions in an Object that are not essential to that Object. If you need a function that is going to be used throughout the application, make it a UDF and keep your UDFs together - accessible through the REQUEST scope. That's my 2 cents.
I do not like application spam, I do not like it Sam I am.
:>)