Application/Session scopes in Flex

As a new Flex developer-in-training my default learning path is to mimic what I can do in other languages.  In ColdFusion we have very convenient built-in "scopes" that one can use to share information to other parts of an application, persist data for a user session, etc...  One of the scopes that I use most often is the application scope.  This is where I would typically load CFC's that perform application wide duties and that will be used often.  I also store information there that is used in decision making or for caching, etc....  So naturally when going beyond the "hello world" examples and tutorials and getting down to building real world applications I started to explore different ways of replicating an "application" scope. 

Out of the box there appears to be a void when it comes to internal scopes (and by internal scopes I mean as it compares to the server, application, session, request scopes found in ColdFusion).  If you research the topic most will say it is bad design to have globally shared data (but then don't offer alternatives).  I guess it breaks encapsulation because your classes/functions will need to know that there is a global scope and therefore will not work without one.

That makes sense to me, however in my 12 years of development I have used "global" scopes in many languages building many successfull applications that have been growing and maintaining quite well.  So with that said, my application is going to have a global scope.  Not only that, but I will be using a singleton to do it.

If this post is ever read, I am sure people will attack this and give me many reasons why this is bad, but hey it works.  Like I mentioned I have been using this type of development for years and I have never had problems with maintenance or expansion.  Maybe there's good reason to shy away, but when used properly (not saying I always do, just "when") I think they bring some efficiency to the table.

The application I am developing is an Air desktop application that will use the online/offline features to keep the client and server databases in sync.  So my global scope really is more comparable to ColdFusion's session scope.  For my first run at creating a "session scope" in my application I decided to use a singleton dynamic class I call Global.  The physical file is in my /src/model/globlal/ folder as I use this class as a model, or something that stores information.  This Global.as class is never instantiated using the "new" keyword like other classes, but is instantiated using Global.getInstance().  For more information about singletons in Flex/AS3, just google it.

Here's the basic shell of my Global.as (Note, I totally ripped this off from this blog post, but added the dynamic keyword, more on that later):

package com.myproject.model.global
{    

    /*
    You can extend anything you need - in most of the cases, you will extend EventDispatcher
    because a manager is supposed to be a dispatcher too
    */

    [Bindable]
    public dynamic class Global{
        /*
        this private static variable is supposed to keep a self reference to this class, once
        it has been created.
        */

        private static var _instanceKeeper : Global;
                
        /*
        as promised, inside the constructor, if we do not have a valid parameter provided
        we'll gonna throw an error for developer to see
        */

        public function Global(privateEnforcer : Enforcer = null){
            if (privateEnforcer == null) throw new Error('Developer, this is a Singleton : do NOT use new to instantiate!');
            Global._instanceKeeper = this;
                        
        }                    
        /*
        now, this is the static method which creates the single instance this class will ever have
        and return it to whom it might make use
        */

        public static function getInstance():Global{
            if ( _instanceKeeper == null ) _instanceKeeper = new Global(new Enforcer());
            return _instanceKeeper;
        }
    }
}
class Enforcer{}

In my Main.mxml (my main application file) I have an onCreationComplete function as such:

public var global:Global;
public function onCreationComplete():void
{
   //Initialize Global variable model
   global = Global.getInstance();
}

So now I have a place to share data/objects with my entire application (global).  The reason why I've made the class dynamic is so that I can add variables at will without having to declare them statically in the class itself.  For instance, I can create an isLoggedIn variable as easily as:

global.isLoggedIn = false;

You do loose compile time checking and strict typing so it's best to use this sparingly.  I think I'll use it more like:

var syncmgr:SyncManager = new SyncManager();
syncmgr.cfServer = "test";
/*register into global scope*/
global.syncmgr = syncmgr;

That way I get the FlashBuilder helps as well as compile time checking.

As an example of how this will be used in my application, this is where my SyncManager will live so that from anywhere I can gain access to the SQLite session and read/write data from/to my local SQLite db as well as handle synchronization to/from the server.  Syntax would be something like:

saveToken:SessionToken = global.syncManager.session.saveUpdateCache(resultsCollection);

(I know, too many dots)

I'm sure there are lots of gooder ways to do this, but I have yet to find one.  If you stumble apon this post and have any suggestions, feel free to comment.

Comments

Leave a comment

Tell us about yourself
(required field)
(required field)
Comment and preferences
Leave this field empty: