The amazing adventures of Doug Hughes

Time To Buck Tradition?

One of the first things I learned when I was first starting to work with Object Oriented Programming in ColdFusion was the concept of a ScopeFacade. A ScopeFacade is an object that encapsulates access to a given variable scope.

For example, you might have a CFC which, for all intents and purposes, wraps the Application scope. This CFC would have methods such as getValue() and setValue() which would get and set the specified values in the application scope.

This is nice because it condenses all your access to these scopes in to one specific location. It also allows you to swap this CFC out for a different implementation in the case that you’re working in an environment where you do not have access to the particular scope.

For many years now I’ve been using a particular CFC (included with ReactorBlog) as a scope faade. When you instantiate it you tell it what scope it’s wrapping. After that you can get and set values to your heart’s content.

The particular ScopeFacade I use makes a reference to the specific scope in its own variables scope. I do this to avoid having to evaluate each variable each time I use the CFC. For example, it boils down to the difference between:

<cfreturn evaluate("#variables.scopeName#.#arguments.name#") />

And

<cfreturn variables.scope[arguments.name] />

In the end, neither are pretty. I chose to go with the reference.

The thing is, about once a month, I make the same boneheaded mistake. I put a SessionFacade into the application scope! For example, I might do this by setting a variable-scoped variable in a Model-Glue Controller. I don’t tend to notice the problem until I move the site to production and my users start screaming about seeing other people’s data. (“It says I’m logged in as the CEO!” D’oh!)

That’s when I realize that to have an effective SessionFacade I need to instantiate it each time I need to use it. That way the reference is always to that particular user’s session. (Well, either that or run evaluate each time I want to interact with values.)

Doug’s Note: The other day Jared was trying to sell me on a ScopeFacade he wrote that uses undocumented methods to get and set values of a variable for a given scope. It may work, but, to me it smells funky. I don’t want to use undocumented features in a production app. The fact that I might need to do it indicates that scope facades might not be the right solution to the problem.

The question then is, if there’s no good implementation then why are we implementing at all?

My opinion on this is because of the lemming mentality. If one of the notables in the community says something then it must be the best way to do things! <cough>Duck Typing</cough>

Really, the primary argument is that a given scope might not always exist. However, if you’re using one of these Facades then you know the scope must exist! The argument seems self defeating.

What I’d rather see is people avoiding direct use of the scopes in their model and services layers. However, I think the use of session variables in controllers is perfectly acceptable!

For example, in Model-Glue, the framework already requires the Application scope and requires the Session scope for stateful redirects. Furthermore, if Session or Application variables are disabled you’ll probably know about that ahead of time and you’d need to so that you could change the implementation!

If you need a value to be provided to a CFC then pass it to the CFC. Or, if you need a collection of unknown variables within a CFC then pass the entire scope into the CFC as a struct. This will let you get whatever values you need without breaking encapsulation.

And, as one last point, many highly visible ColdFusion developers have recently been excited by the concept that maybe you really should use all the features provided by the Language. Mixins? Sure, if you can, why not? Duck Typing? If you can, and need to, then gopher it!

It really boils down to pragmatic programming. If you need to, and you can, then do it!

It’s generally agreed that Controller components serve the purpose of ferrying data around. From that perspective, and the fact that ColdFusion provides easy access to different variable scopes, it’s just fine for your controllers to access this data directly and pass it into your model and services. However, don’t let your model and services touch any scope other than Variables, This or Super directly. That would break encapsulation.

Comments on: "Time To Buck Tradition?" (9)

  1. Kurt Wiersma said:

    I to don’t usually a scope facade. When I do it when I need specific functionality for an application that uses the session scope. So if I write a session facade it is always different from one app to the other.

    Like

  2. Joe Rinehart said:

    I agree with both of you (Doug and Kurt) 100%! The last thing people need when learning MG or M2 is one more scary sounding concept like “ScopeFacade.”

    I’ll refactor to one when a force dictates its necessity (such as recovering sessions in a cluster) – otherwise, YAGNI and KISS win.

    Like

  3. Jacob Munson said:

    I like your comment Joe. I’ve been kind of vocal about some of the framework attitudes lately, and one of them that bothers me is the use of such ‘head in the clouds’ words. I know it’s just a matter of learning what it means, but it really is annoying when you are honestly trying to learn a new framework, and people are constantly throwing around abstract terms like ScopeFacade, Interfaces, Factories, Duck Typing etc. I know most of these terms come from the Design Patterns community, but it’s still daunting for the average joe trying to get his feet wet with this stuff.

    Like

  4. Jared Rypka-Hauer said:

    LOL!

    You coulda warned me you were going to tell me I stink!

    And, for the record, I’ve successfully gotten around the issue of needing to use “undocumented features” of the PageContext and am still able to use a string value to get a reference to the correct scope. Since it comes from the current PageContext, it gets a handle on the RIGHT scope, so having a session facade in the application scope is very effective, much faster than intantiating every time, and safer (theoretically) than having a handle to a shared scope in the variables scope of a CFC instance.

    I’ll blog about it shortly here…

    In the mean time, just to be clear, the doco for the PageContext isn’t clear and makes it appear that the methods within it are there to be used. So “undocumented” isn’t exactly accurate, but neither is “yeah, fine, go ahead”.

    I like to use a facade for several reasons, not the least of which is consistency and clarity… readable and maintainable code shouldn’t (IMO, and just IMO) take a “well we do it this way sometimes and that way at other times” sort of an approach.

    Laterz!

    Like

  5. Jeff Howden said:

    As a long-time CF developer, I consider myself to be at the master level. However, I’ve hedged against stepping away from our in-house framework to one of the newer OO frameworks simply because of all of the fancy verbage. All my programming knowledge is via OJT. I don’t have any schooling (other than hardknocks) to fall back on when a concept isn’t sticking. So, the leap to OO is already a bit daunting for me. Adding in all the (what amounts to me as) buzzwords is overwhelming.

    Like

  6. Jeff Houser said:

    [start quote]
    “Really, the primary argument is that a given scope might not always exist. However, if you’re using one of these Facades then you know the scope must exist! The argument seems self defeating.”
    [end quote]

    The given scope should always exist for the CF server, but might not always exist for the client, which may be a web service or Flash Movie, as opposed to CF template running on the same CF server in the context of the same CF Application.

    I have found Session Facades particularly useful when trying to maintain state across multiple remote calls.

    However, I wouldn’t consider using them for ‘local’ development.

    Like

  7. Mark Mandel said:

    Doug,

    I’m hoping I’m not missing the point here – but this is the way I implement my Facade, in a way in which you can store it as a singleton, and not end up with shared data and the like.

    I implement my ScopeFacade by having an
    AbstractBase Facade that has a virtual method called ‘getScope() : struct’.

    In the case of a session facacde, it simple reads (I’ll make it cfscript for ease of typing)

    function getScope()
    {
    return session;
    }

    from there in my sessionfacade I can do things like

    function setUser(user)
    {
    getScope().user = arguments.user;
    }

    This way, by not setting the scope into the variables scope of the CFC, you can avoid issues with scopes being shared across threads when they aren’t meant to be.

    I hope that made sense.

    Like

  8. Peter Bell said:

    Hi Doug,

    Great post! I was playing around with controllers recently and I tend to agree. I don’t like models that depend on scopes that may not always be there, but it seems perfectly appropriate for a controller to be able to speak to scopes like session as long as it doesn’t start smelling bad.

    I think we’re all guilty of premature optimizations. We put in patterns to solve problems we don’t even have yet. That’s one of the reasons I’m doing my series on “building the framework” to bring up the forces that drive framework decisions and to try to work up discussions around when and where the different patterns are appropriate.

    Best Wishes,
    Peter

    Like

  9. Cedric Villat said:

    Doug, this same issue bit me once, and it took me a while to figure out what was going on! Once I figured it out, I promised to never make the same mistake again, but I also thought of why I was using the ScopeFacade in the first place.

    Thanks for the informative post.

    Like

Comments are closed.

Tag Cloud

%d bloggers like this: