The Dopefly Tech Blog

<< The Dopefly Tech Blog Main page

ColdFusion and the Session Facade

posted under category: ColdFusion on December 14, 2008 at 1:00 am by MrNate

We've heard it, we may have seen it in action. If you have ever asked yourself "why," this is for you.

(BTW, I'm just going to call it a "facade" because "façade" is too difficult for my keyboard to produce)

The Pattern
A facade is a fake front, like a mask. A session facade hides away the "complexity" of using a session.

The session facade is the point-of-contact for your session variables. Using one, we no longer have a session scope that you can talk to, now we talk to the facade. The facade offers basic bean methods with generic names - get(), set() and delete(), or a variation on the theme.

Dave Ross has pretty much the definitive ColdFusion Session Facade article (2 pages worth and sample code) - how to use it and all. I'm just considering the usefulness of it.

That sucks
Instead of #session.username#, now we can just type #application.objectFactory.getBean('sessionFacade').getData('username')# and the session facade will handle the dirty work of typing the scope name "session" for us. Finally, more typing!

So now that we're typing more, we also have to learn a new API for managing the session scope. What if we use get, put and delete methods and our friend Bob Bobbery uses get, set, remove, clear, search, etc, etc? More to learn equals more complexity.

And what problem exactly did this fix? We had a session scope before, and we technically still have it. Nothing forces the bad coders on our eam to use it. Nothing really changes, assuming the facade just gets and sets variables from the session scope. It just added another CFC to manage and a bunch of extra code.

The final problem is that the session facade doesn't do anything to manage the session, to organize it, report on it, fix problems that could occur or reduce complexity. It's typically just a dumb bean with variables.* replaced with session.*. It's useless.

Oh, that might be cool
We programmers are managing change. That's one of the things that we do, and hopefully, we will do it well. What if the session scope goes away... no not likely, but with a session facade, we have the mechanism to manage every variable in and out of the session scope. We could reroute it to a database.

The session scope could disappear due to an administrative switch. On a hosted server, we may have no choice. The session facade could then be changed to get essential data from the database at every request.

What if, to reduce server memory, we want to put certain variables, or certain types of variables in our database. The session facade could be made to leave some things on disk, some in memory. A little brains can be added without touching the rest of the application.

What if we want to write a log event every time something goes in and out of the session scope? The session facade is basically our only option for this. The only other way would be to search our code for the word 'session' and add a cflog on each event. With a session facade object, we can do logging or any other type of thing all in one place. Not bad.

Perhaps we may want to cflock each session access because of some potentially unsafe code reading and writing to one variable - we can do that easily here by exclusively locking the set method and readonly locking the get method, using a unique session key to name the lock.

In summary
In summary, the choice to use a session facade should be based on the risk of drastic session scope change. The benefits seem to be a lot of 'what if' scenarios, but they could happen, maybe, while the drawbacks seem to pay off right away. Laziness now or laziness later?

Too old to comment!
On Dec 14, 2008 at 1:00 AM ike (info who wouldn't be caught dead at turnkey.to) said:
The Members onTap plugin for the onTap framework has a "membersession" object (a CFC), and you might call it a "session facade" although it's not really, or at least not the way you've described here. Instead of managing the session scope, the MemberSession object actually sits in the session scope (or somewhere else if you prefer - long story) and is a container for arbitrary variables that you might want to stay with the current session. But those variables are stored in the object's private instance variables the same as other "beans" (I hate that word). Moreover the MemberSession "facade" also contains some hooks to the security framework and provides access to the member object for the current logged in member (not the same thing as the session - the member is persisted in the database, the session object is transient and goes away when the session expires). And rather than referencing application.[anything], you refer to it as request.tap.session, as there is guaranteed to be a request scope and that allows us to point to it there without worrying about whether it's actually stored in the session scope (could be stored in the cluster scope for all the rest of the app cares).

On Dec 15, 2008 at 1:00 AM Oscar Arevalo (oarevalo, by way of gmail.com) said:
At my previous job we used the facade pattern but in a different scenario. All our apps were designed to be deployed to clusters (no sticky session or session replication), so the session scope was not an option and all the "session" management was done through the client scope. Now, the applications had a "session facade" component but the difference was that it could be configured to use either session or client scopes to store the data; the benefit was that during development we could use the normal session scope but then once it was time to deploy to a cluster then we changed the setting and transparently moved the application to use the client scope.

On Dec 15, 2008 at 1:00 AM Nathan Strutz (http://www.dopefly.com/) said:
@Ike, thanks for your comment - that's an interesting take on the problem, a good workaround, unique.

@Oscar, thanks as well - it seems you had the exact right reason to use a session facade, switching the session scope based on environment. In fact, I think that's such a good idea, I might pitch it to a project team here, who relies heavily on the client scope.

On Dec 15, 2008 at 1:00 AM Dan Wilson (http://www.nodans.com) said:
I don't use SessionFacades for the exact same reason you mention.

I have a component called CurrentUser that has a load method. Any information about the currently logged in user can be accessed by simply calling currentUser.load() and then running methods on the returned object.

Internally, the currentUser object happens to grab the userID key from the session. Should I need to change the storage of the currently logged in userID to client variables, I can do so inside this currentUser object.


So I guess rather than a sessionfacade to abstract working with a session, I have a current user facade to abstract working with the mechanism of currently logged in users.


DW

On Dec 15, 2008 at 1:00 AM Brian Kotek (brian428 who loves gmail.com) said:
A couple of comments:

I'm firmly against the idea of a generic session facade that allows any value to be get or set. This defeats the whole point to me. So I would not base your evaluation of the usefulness of this pattern on the idea of a generic session facade.

Second, you mention typing, and point out that application.objectFactory.getBean('sessionFacade').getData('username')is longer than session.username. My response would be: how often are you typing this? If the answer is more than one, why? Further, why would you want to store something as specific as "user name" in the session? Why not just store the user ID or a User instance and be done with it?

The reason I use a session facade has nothing to do with concern that I will have to change my session scope implementation. I do it for two reasons that are actually two sides of the same coin: encapsulation and testing.

You want to encapsulate access to the session scope because it is good practice to encapsulate access to any kind of global data. And by encapsulating it, you make it much easier to test because you can supply a mock implementation of the facade that does not require a real session scope.

As Dan points out, he doesn't use a dedicated Session Facade CFC, but rather encapsulates access to the session scope on a per-object basis. Which is also fine (though it still can make testing more difficult). So whether he admits it or not, his User object is acting as a session facade, just for a very specific bit of data.

The bottom line is that however you do it, you absolutely don't want to have references to the session scope littering your entire codebase. So whether you use a dedicated component, or whether you have dedicated methods within individual components that encapsulate the session access, you're far better off than having references to the session scope all over the place. I think that is the core idea behind the session facade that seems to be getting missed here.

On Dec 15, 2008 at 1:00 AM ike (info from turnkey.to) said:
Thanks Nathan. :)

On Dec 15, 2008 at 1:00 AM Allen (stmp692 who wouldn't be caught dead at zenbe.com) said:
Brian...I don't get how one is "far better off". What is the difference if I have 100 references to a session facade than have a 100 references to the session scope directly? What exactly is gained?

On Dec 15, 2008 at 1:00 AM Brian Kotek (brian428 who really likes gmail.com) said:
Here are two articles that touch on the subject: http://en.wikipedia.org/wiki/Global_variable and http://en.wikipedia.org/wiki/Law_of_Demeter, but I can give you two very quick examples from my own personal experience.

First, if I encapsulate access to the session within something that *I* can control, such as a CFC, I am free to change how it works without affecting anything else in the system. A perfect example is that I used to store a User object in the session scope. Later I started using Transfer, which has a cache of objects. This can case major and very elusive bugs because you can update something via Transfer that is not reflected in the User object that the session has a reference to. I won't get into deep details, but the point is that if I have encapsulated this, I can easily change what I'm storing (say, from a User object to a simple userID value), and have the CFC in turn ask Transfer for the relevant User. External code never changes, it still does sessionFacade.getCurrentUser() and gets back the right user. Obviously, if the external code depended on the fact that session.user existed, every one of those reference would have to change.

A second example is testing. If I have a unit test set up, I should not have to create an entire application or session scope every time I want to run my tests. The good news is, I don't have to. I can simply supply a MockSessionFacade to my objects, and they will never know that there is actually no session scope in use (as they should not).

Hopefully that helps explain things a bit more. If you do a Google search on why global variables are considered bad practice you will find many millions of results on the subject.
Too old to comment!