Archive for the 'Adobe Flash' Category

Accessing private class members in AS3

Tuesday, March 11th, 2008

Reflective programming is a very common, powerful, yet expensive software development practice. In most modern programming languages reflection can not be utilized to modify private members of an object, which is to be expected. However in certain circumstances, such as when developing very high level frameworks and automation APIs it may be beneficial at times to be have the ability to access private members of an object from outside of the public API of the class.

For instance, consider the following class definition:

// User class does not define setter functions for
// the private members _username and _password
package com.ericfeminella.example
{
    public class User
    {
        private var _username:String;
        private var _password:String;
       
        public function User(username:String, password:String)
        {
            this._username = username;
            this._password = password;
        }      
        public function get username() : String
        {
            return this._username;
        }
       
        public function get password() : String
        {
            return this._username;
        }
    }
}

The above class defines two private members: _username and _password. The public API of this class exposes these properties via the read-only accessors get username and get password. Per design assignments to these properties can only be made via the instance constructor.

So how can these values be modified once the object has been instantiated? More importantly, should this be allowed as the properties have not been publicly exposed? Theoretically they can not, philosophically they shouldn’t. All of this is debatable; however as a dynamic programming language ActionScript can easily accomplish accessing and modifying private members of an object which have not been exposed.

To do so is simple: define a method which provides an interface into the private members of the class instance, as in the following example:

// static method which provides a mechanism allowing
// private properties to be modified
public static function modifyMember(instance:User,
                                    property:String,
                                    value:*) : void
{
    try {
     instance[property] = value;
    }
    catch(error:ReferenceError)
    {
        throw new ArgumentError(property+not defined by+User);
    }
}

The above example is pretty straightforward. It is simply a static method which requires 3 arguments. The first being the instance of the class, the second is the property in which to assign a new value, and the third is the value to assign to the property. This static method can be defined in any class and will work fine - you only need to change the type of the instance argument and error message to match the type of the class in which the method is defined. All methods in a class definition have access to any member of the class therefore assignments can be made to an instance of the class via a static method. This is possible in most object oriented languages such as C# and Java, however ActionScript takes this approach into the dynamic realm thus making it much more robust as the actual properties which are to be modified can be specified at runtime.

This approach can just as easily be accomplished on the instance level as well via an instance method, as in the following:

// instance method which provides a mechanism allowing
// private properties to be modified
public function modifyMember(property:String, value:*) : void
{
    try {
       this[property] = value;
    }
    catch(error:ReferenceError)
    {
       throw new ArgumentError(property + not defined by+this);
    }
}

A client implementation for each would be as follows:

var vo:User = new User("foo", "bar");

trace( vo.username ); // foo
trace( vo.password ); // bar

// static implementation
User.modifyMember( vo, "_username ", "efeminella" );
trace( vo.username ); // efeminella

// instance implementation
vo.modifyMember( "_username ", "admin" );
trace( vo.username ); // admin
 

This approach is best suited for assigning values to simple types, or for pointing reference types to other object instances. This does not allow nested properties of a member to be accessed or modified (although it could easily be refactored to do so). Most importantly, (as you may be thinking) this breaks encapsulation and violates information hiding; therefore I do not recommend utilizing this approach for general use, however it is a convenient and efficient way to modify objects when developing complex APIs which use reflection and also for implementing Unit Tests directly against private members.

Initially I was introduced to the static implementation of this technique by a .Net developer on my team, and admittedly I was somewhat skeptical at first, however given the dynamic nature of ActionScript I realized this could open up some interesting possibilities under unique circumstances, similar to how mixins open up many possibilities - when used with discretion in a good design they both provide powerful advantages over other languages.

Food for thought. Enjoy.

LocalPersistenceMap

Sunday, March 9th, 2008

When developing browser based Flex application SharedObject provides just about everything one needs to facilitate local persistence of application data. SharedObject is restricted by certain rules governed by the Flash Player Security Model, however it is very efficient for general use.

The data property of a SharedObject provides read/write access to the underlying data which is persisted to the SharedObject. Personally, I prefer to have a consistent API available when working with dynamic objects, thus I developed the IMap interface.

LocalPersistenceMap provides an IMap implementation into the data property of a SharedObject instance. It allows clients to work with the underlying data of a SharedObject just as one would with a HashMap, ResourceMap, etc.

Below is a basic example which demonstrates how LocalPersistenceMap can be utilized to provide an IMap implementation into a SharedObject:

var map:IMap = new LocalPersistenceMap("test", "/");
map.put("username", "efeminella");
map.put("password", "43kj5k4nr43r934hcr34hr8h3");
map.put("admin", true);

The LocalPersistenceMap constructor creates a reference to a local SharedObject based on the specified identifier and optional local path. A reference to the underlying SharedObject can also be retrieved via the sharedObjectInstance accessor.

In addition to the new LocalPersistenceMap, I have also packaged the Collections API which can be downloaded here. Complete documentation and code examples for the Collections API are also available here.

Using Namespaces to provide context in AS3

Monday, December 17th, 2007

Namespaces in ActionScript 3 are particularly useful for providing context in an application. They also provide an added clarity to APIs outside of the typical language specific access modifiers.

For instance, let’s say we have an application which requires slightly different behaviors depending on a specific type of user. If the user is a guest, the application need only display a fairly basic view, however, if the user is an administrator the application must display a slightly more complex view.

Based on the type of user we can deduce context and from this context we can provide a contextual namespace. The contextual namespace can then be utilized to invoke different methods with the same name on an object.

To help facilitate the management of a contextual namespace I have created a ContextNamespace API.

ContextNamespace is a Singleton class which can be utilized to set and retrieve a contextual namespace based on context. Additionally, ContextNamespace implements INamespaceManager which defines various convenience methods for retrieving information about a contextual namespace, comparing a Namespace against the contextual Namespace and comparing a URI against the contextual Namespace URI.

Below is a simple example which demonstrates how to utilize the ContextNamespace API.

The class below utilizes two custom namespaces; admin and guest. Two methods with the same name are defined in the Class, each of which is under a different namespace.

package
{
    import com.domain.namespaces.admin;
    import com.domain.namespaces.guest;
 
    public class UserViewHelper
    {
        // define the admin implementation of renderView
        admin static function renderView() : void
        {
            // admin implementation code…
        }

        // define the guest implementation of renderView
        guest static function renderView() : void
        {
            // guest implementation code…
        }
    }
}

To utilize ContextNamespace to retrieve a reference to the current contextual Namespace is simple.

import com.ericfeminella.ns.ContextNamespace;

// define a local namespace object
var ns:Namespace;

// reference the contextual namespace
ns = ContextNamespace.instance.getNamespace();

// invoke methods using the namespace reference
// should the contextual namespace change the
// implementation will reflect the change
UserViewHelper.ns::renderView();

In the above code a local namespace is defined which references the current contextual namespace used by the application via ContextNamespace.instance.getNamespace(). The local reference is then used to identify the correct namespace from which methods are to be invoked.

For additional examples which demonstrate how ContextNamespace can be utilized to provide a globally accessible reference to a namespace, view the ASDocs.

ASDocs
ContextNamespace
INamespaceManager

AS3 Singletons, revisited

Friday, December 7th, 2007

The topic of Singletons in ActionScript 3.0 has been coming up again lately and it has been very interesting to see all of the unique solutions the community has come up with. In particular I like the idea of having Singleton metadata which would allow the compiler do all of the work for us.

Personally I feel the Singleton pattern is extremely useful. It is arguably one of the most common design patterns around today. Practically every management centric API requires a Singleton one way or another. Some developers claim that the Singleton pattern is nothing more than a euphemism for a global variable, to some extent this is true, however the intent of a Singleton is clearly different.

As useful as the Singleton pattern is my biggest complaint about Singletons has always been the actual construction code required to create / protect the Singleton instance. This extra code often becomes quite verbose and it is annoying to have to sift through all of the Singleton code when working with the actual class implementation code. It would also be nice to not have to constantly re-write the Singleton construction and implementation code every time a Singleton is needed.

So is there a way around all of this? Yes!

I developed a simple class called SingletonMonitor which singleton classes can extend to allow the omission of all Singleton specific construction code. All that is needed is to have the class which is to be a Singleton extend SingletonMonitor. That’s it. No more getInstance(), inner classes, type checking and so on is needed. As a best practice I recommend that you define the Singleton instance in the class itself in order to improve code readability.

An example demonstrating how to use the SingletonMonitor can be seen in the following:

package
{
    public class Manager extends SingletonMonitor
    {
        // define the singleton instance of Manager
        public static const instance:Manager = new Manager();
    }
}

As you can see no Singleton construction code is needed. Additionally, by extending SingletonMonitor you are clearly stating that the class is intended to be a Singleton.

So how is this accomplished? It’s pretty simple…

When a derived class is instantiated the SingletonMonitor constructor is invoked, the constructor parses the current stack trace in order to determine the derived class’ name (hence the hack). The name of the derived class is then used as a key in the SingletonMonitor hash table. When a subsequent instantiation of the class is made SingletonMonitor checks the name of the class and if it has previously been defined in the hash an exception is thrown. I originally developed this using introspection to determine the fully qualified name of the class, however the preferred implementation is to have the class eagerly instantiated at compiled time (i.e. constant), thus the stack trace is not available.

Admittedly this is a bit of a hack, but so are the alternatives, otherwise this issue would never have been a topic of discussion in the first place.

However what I like about this new approach is that the Singleton is being managed outside of it’s concrete implementation, and that is the goal of this post; to present an alternative means of managing Singleton construction. Through this the Singleton construction and management code can be omitted as it is being handled by a completely separate object.

So the SingletonMonitor was the first example of how Singleton management can be achieved. The second example demonstrates the Singleton management approach implemented via composition as opposed to inheritance - which is my preferred mechanism of Singleton Management. In addition to creating the SingletonMonitor which utilizes inheritance I also created a SingletonManager which utilizes composition. The SingletonManager is the implementation I recommend and prefer.

An example demonstrating how to use the SingletonManager can be seen in the following:

package
{
    public class Manager
    {
        // define the singleton instance of Manager
        public static const instance:Manager = new Manager();

        // the constructor simply invokes SingletonManager
        // validateInstance and passes a reference of the
        // instance, that’s it.
        public function Manager()
        {
             SingletonManager.validateInstance( this );
        }
    }
}

The SingletonManager requires the class constructor to invoke SingletonManager.validateInstance and pass in a reference of the instance. This is automated in the SingletonMonitor as the class name is determined automatically which is convenient, however the readability of the SingletonManager is preferred as it clearly states intent. Additionally the SingletonManager guarantees the correct type is resolved.

So this is a new way of thinking about Singletons; to provide a management system from which Singleton construction and protection can consistently provided.

To be honest, this was really just an experiment I have been playing around with for some time now that I thought I should share, I am not sure if I would use the SingletonMonitor in production code as the parsing of the stack trace just feels a bit to much like a hack. However I will most likely utilize the SingeltonManager moving forward as it is a great way to abstract Singleton construction and protection from the class implementation.

My hope is that there will be a true solution available as we move forward, but for the time being if you would like to create Singletons without the need for all of the Singleton implementation code feel free to extend SingletonMonitor for management or SingletonManager for compositional management.