Ask a Jedi: What is the proper way to handle session/cgi variables in CFCs?
Samer asks:
I know CFCs should never access SESSION/CGI variables, and these variables should be passed as arguments. In my case i have a lot of CFCs that calls another CFC "for logging" which reads SESSION and CGI variables, is there a way not to pass these variables as arguments in all CFCs?
I think you touch on multiple things here - and each thing you touch on will have multiple answers with a lot of it being "it depends." So get ready Samer for an overload from me and my readers. Let me begin by breaking this up into what I see as the main concerns.
- CFCs and accessing Session/CGI variables
- Multiple CFCs using some common other CFC
Let's start with issue one. First off - I know I've done it myself, but I try to refrain from saying never. The issue isn't with Session variables in a CFC, but with outside variables in general. You should try to make your CFCs as encapsulated as possible. I assume most folks 'get' that concept so I won't cover it a lot - but I bring it up to remind folks that it isn't just Session variables you wouldn't want to use (normally), but anything that hinders encapsulation.
That being said, from time to time I've used Session variables in my Controller CFCs in Model-Glue applications. I kept my model layer as pure as possible, but found a need to directly reference session items in the controller layer. I did try to make it as 'nice' as possible. So for example, any time I needed a user object stored in the session scope, I'd call a getCurrentUser() method. That method directly accessed the session scope. That way in case things changed I'd only have one thing to change.
I'd also argue that a logging CFC is a good example of something that can break encapsulation. I certainly wouldn't bother passing in CGI info when setting up a logger CFC as the CGI scope is always there.
Point 2 - this is exactly where something like ColdSpring comes into play. Whenever you get an application that has multiple CFCs and CFCs that depend on each other, you want to look into a framework to make the dependencies easier to handle. Do not do like I did and delay picking it up. As I've said before, I wish I had picked up ColdSpring a lot earlier as it would have made my life a lot easier.
Comments
HTH
http://www.iknowkungfoo.com/blog/index.cfm/2007/2/...
We now have a base SessionFacade.cfc and each application has their own that extends the base. We pass the SessionFacade into other objects as needed so that no other object is directly accessing the session scope.
This gives us focal points for managing session variables across applications and it makes sure that everything is locked correctly for reads and writes.
Our old site read from and wrote to the session scope anywhere it pleased. People would log in and get someone else's session info so often, we just told them to log in again and see if that helped.
Another common practice we have which isn't as nice but gets the job done, is pass the variable as an argument to functions but give it a default value of value="#session.whatever#" so it only needs to be passed in by functions that don't have access to the session scope.
I tend to agree with Ray, however that dependency injection is really the way to go here with a session facade.
1. Session Facade is also a J2EE pattern that provides a stateful facade in front of a set of stateless beans. IOW, the client interacts directly with the session facade, which then talks to the back end system. This sounds like a facade to me. The "Session facade" that CFers talk about is just plain old encapsulation. Yep, I told you it was nitpicking!
2. Name the object for what it represents, not how it's implemented. I don't call my Invoice object InvoiceDatabaseRecordFacade, I just call it Invoice. This thing is an abstraction that represents a user's session, so what's wrong with UserSession.cfc? Or even just Session.cfc.
Ok, gripe over. Apologies for the inconvienece, we now return you to the scheduled programming...

