Even though MVC has been "all the rage" now for a good long time and several frameworks have been lovingly and painstakingly developed and shared by the CF community to help facilitate the migration to a more standardized OO approach to development, I do believe that there will always be a need to regularly return to the foundational principles of our craft. For some, an affirmation or further perfecting of their core thought processes; for others, the first exposure to a new way of thinking about and viewing the tools they wield as a problem solver and programmer. After having immersed oneself so deeply in MVC and OO for a substantial length of time and embracing those concepts so completely, these foundational principles can become so much a part of us that we hardly even recognize them as such, and tend rather to simply see them as a part of who we are and how we think. Sometimes, though, the privileged occasion arises when we get to once again see them as the wondrous, shiny ideas that they are, when a person who has had the tenaciousness and fortitude to embark upon that OO journey asks us to share our own insight in order to facilitate the evolution of their own assimilation of these concepts.
Alright, perhaps a bit too poetic a prelude, but I was recently asked to share my own understanding of the relationship between controller objects and model objects and the mechanics there. I couldn't help but get a little excited as I took the time to examine my own understanding of the subject and attempt to relate it to this person and realized just how much a part of my thinking it has become. Of course, it goes without saying that I know for a fact I still have a lot of room for growth in this area, but I do feel at least a sense of satisfaction that the couple of years I've invested so far in this has grown me more technically than I believe I had in the five years prior doing procedural coding.
Okay, enough with the nostalgia already! Here's the question I was asked:
[10:09 PM] hey Doug-
[10:10 PM] thanks so much for all the tutorials and learning materials, can't thank you enough
[10:11 PM] i've got a basic model glue site up and running with one exception, total MVC with not much in the model, totally bloated controllers. Still trying to get my head around calling and using the code from my model via the controller, any blog entries or anecodotal stories to suggest that would guide me?
My Response:
Hey, you're welcome for the tutorials and such. I definitely don't do it for the fame, but rather because I KNOW how painful it can be to traverse a new learning curve, espcially when it comes to frameworks, OO, and the like. If I can spare someone even ten minutes of hair pulling then I've accomplished what I set out to do! :)
Using your model code in your controllers (which is exactly what a person should be doing :) )...this is nothing more or less than giving your controller cfc an instance of your model cfc so it can manipulate it, call its methods, etc. For instance, imagine for a moment that we are attempting to log a person in to our app (framework doesn't matter, all we know is it's one that supports MVC). The user has just filled in their username and password and clicked the submit button, and those two pieces of info are now handed off to our controller via whatever mechanism the framework we're using has provided us. We have created for ourselves a Security.cfc that has a method called "Login".
<cfcomponent displayname="Security">
<cffunction name="login">
<cfargument name="username" />
<cfargument name="password" />
...
</cffunction>
</cfcomponent>
Now, Security is our controller, so by virtue of that fact the general rule of thumb is that the controller's job is to be nothing more than a liaison between the View (our forms and results page) and our model (where the real work gets done!), our controller cfc should have very little code in it and in fact should be using our model object to get the real work done. In order for it to do that, it needs an instance of it's Model security counterpart. In our scenario, we have a CFC living in the Model directory also called Security which performs the actual act of attempting authentication. Here's what our Model/Security.cfc might look like:
<cffunction name="login">
<cfargument name="username" />
<cfargument name="password" />
<cfset var results = false /><!--- set the value of our return variable. by default we're going to return a result of false, meaning the authentication failed --->
<cfquery name="qryLogin">
select username from user_table where username = <cfqueryparam value="#arguments.username#" cfsqltype="cf_sql_varchar" /> and password = <cfqueryparam value="#arguments.password#" cfsqltype="cf_sql_varchar" />
</cfquery>
<cfif qryLogin.recordcount eq 1><!--- we authenticated! --->
<cfset results = true />
</cfif>
<cfreturn results />
</cffunction>
</cfcomponent>
Makes sense to you, I'm sure...same kind of code we've been using for decades to authenticate a person, right? Okay, so now we need for our controller to actually make the login call. Let's give our Security controller access to this functionality. Here's our controller Security CFC again...
<cffunction name="login">
<cfargument name="username" />
<cfargument name="password" />
<cfset var objSecurity = createobject("component","Model.Security") />
<cfset var results = false />
<cfset results = objSecurity.login(username=arguments.username,password=arguments.password) />
<cfreturn results />
</cffunction>
</cfcomponent>
So, within our controller, we have created an instance of our Model security CFC and called its login method. I know this is a very simplified example, but it is precisely the way to think about the relationship between your model and your controller objects! We can get a little fancier if we like and put our object into the variables scope within our CFC so that we only create one instance of it and then let every method in the controller access it as needed, like this:
<cffunction name="init">
<cfset variables._objSecurity = createobject("component","Model.security") />
</cffunction>
<cffunction name="getSecurity">
<cfreturn variables._objSecurity />
</cffunction>
<cffunction name="login">
<cfargument name="username" />
<cfargument name="password" />
<cfset var results = false />
<cfset results = getSecurity().login(username=arguments.username,password=arguments.password) />
<cfreturn results />
</cffunction>
</cfcomponent>
Now any method in my controller that needs to use the model security object need only do a "getSecurity()" call! This is assuming that your Init method is getting called when your controller is instantiated by your framework; it would need to in order for the security object to be present and available.
Now, for many reasons, it is not the best idea to be hard coding object instantiation into your controllers. I mean, what if you did that and then somewhere down the road you had to make a change to your Model/security.cfc that now required the init method to be called upon instantiation? You would have to hunt down every place in your app where the security object was being instantiated and change the createobject line to include the init method call. In this scenario probably not a huge deal to do so; but potentially this could create a LOT of extra maintenance. This specific thing is why I have come to love Coldspring so much. It allows me to "inject" an instance of my model/security.cfc into my controller/security.cfc in one handy place so that I need never (probably) touch my controller when a change is made to my model as I described. Here is my controller when I inject the model/security object using Coldspring:
<!--- Coldspring Autowire methods --->
<cffunction name="setSecurity" access="public" returntype="void" output="false">
<cfargument name="Security" required="true" type="any" />
<cfset variables._Security = arguments.Security />
</cffunction>
<cffunction name="getSecurity" access="private" returntype="any" output="false">
<cfreturn variables._Security />
</cffunction>
<cffunction name="login">
<cfargument name="username" />
<cfargument name="password" />
<cfset var results = false />
<cfset results = getSecurity().login(username=arguments.username,password=arguments.password) />
<cfreturn results />
</cffunction>
</cfcomponent>
By adding Coldspring to the mix, when it instantiates your controllers and finds corresponding SET and GET methods like that, it will look to see if it has a definition for the object the set and get references (in this case, the set and get are for 'Security'...getSECURITY, setSECURITY...so it will be looking for a bean definition named SECURITY). If it does, it will go ahead and create that object and inject it into the controller for you so that it is "present and accounted for" from that moment on. So, I could theoretically define a whole bunch of different objects (aka 'beans') for Coldspring, and then when I need one of those objects in my controller, all i gotta do is create a SET and GET method that matches the object name. Let's say our Security controller ALSO needs to be able to send emails, and our app has an Emailservice CFC in the model. Well heck, let's just inject that bad boy and use it! :
<!--- Coldspring Autowire methods --->
<cffunction name="setSecurity" access="public" returntype="void" output="false">
<cfargument name="Security" required="true" type="any" />
<cfset variables._Security = arguments.Security />
</cffunction>
<cffunction name="getSecurity" access="private" returntype="any" output="false">
<cfreturn variables._Security />
</cffunction>
<cffunction name="setEmailService" access="public" returntype="void" output="false">
<cfargument name="EmailService" required="true" type="any" />
<cfset variables._EmailService = arguments.EmailService />
</cffunction>
<cffunction name="getEmailService" access="private" returntype="any" output="false">
<cfreturn variables._EmailService />
</cffunction>
<cffunction name="login">
<cfargument name="username" />
<cfargument name="password" />
<cfset var results = false />
<cfset results = getSecurity().login(username=arguments.username,password=arguments.password) />
<cfif not results>
<cfset getEmailService().sendAdminEmail(subject="failed login") />
</cfif>
<cfreturn results />
</cffunction>
</cfcomponent>
Coldspring just makes object injection SO simple, don't you think? Setters and getters are one way of injecting objects using Coldspring; it also can do it another way, which I won't get into right now (no need to muddy the waters at this juncture). Now, you should also know that there are times when individual Model objects ALSO need to use instances of other model objects (you may have encountered this already at some point). For instance, the example of an Emailservice object...by virtue of the very defnition of a service object (which I do have a blog post about), it is likely manipulating the methods of two or more OTHER objects. Just like our controller, for our model object to use another object, it has to have an instance injected into it somehow. Either we created that instance manually using a Createobject statement, OR we leveraged Coldspring to auto-inject those instances for us. The manner in which it is done is exactly the same as it is for controllers, no significant differences at all.
Okay, I know I've kinda gone on and on about this, but (if you can't tell) I do tend to have a passion for Coldspring and the beauty it brings to an OO application! But you know, even if you opt not to leverage Coldspring to perform the object injection and choose rather to do it manually (which I, for one, would not frown upon you for doing :) ), the concept is exactly the same: If one object needs to manipulate another object, you must create an instance of the needed object(s) within the controlling object, whether that happens to live in the model or controller. Having said that, there are a few hard and fast rules of thumb when writing these apps that I always follow and which you may want to consider for yourself.
1. A controller's job is to be liaison between view and model, only. Keep controller methods as light as possible, doing as little work as possible.
2. A controller should NEVER talk to the database
3. A controller is the ONLY one who has the privilege of talking to Session or Application scopes (unless you have yourself a session facade object, which I personally have never seen the need for. If you DO have a session facade object, then IT is the only object in the app who has the privilege of talking to session. in that case, the session facade will have a corresponding controller and model object).
4. Model objects should be doing as much of the app's work as possible. In a nutshell, build your model objects as if tomorrow you would be told that you had to change frameworks and your model was the only thing you could take with you.
5. NEVER even consider injecting a controller object into a model object. BLAH! YUK! PTOOEY! In fact, never allow yourself the sacrelige of injecting one CONTROLLER into another. If you're seeing the possibility of a need to do that, then probably you need to refactor some logic and move some code around.
That's about it. Have I helped fill in any gaps? Have I opened any more? Did I address what it is you were needing? Let me know, I don't mind taking the time to share (and learn)!
Doug :0)


) . If I wanted to get even more elaborate, such as routing based on role, or a diversity of messages to match the situation, I would probably add a message dictionary to my global config bean and replace my growing IF statement with a call to a global security object that would perform appropriate evaluations and return the needed responses for me to execute an appropriate redirect and message. One more object in my model that I create as a singleton and have available to my fusebox.init.cfm...why complicate it any more than that? Again, input solicited.