Archive for December, 2007

Running ASDoc against AIR projects

Friday, December 28th, 2007

At first glance one might think the ability to run asdoc.exe against an AIR project would be pretty much the same as compiling ASDocs for a typical Flex project - but it’s not.

I recently completed updating my AIRCairngorm project and decided to compile the source code documentation as I always do, however when I attempted to do so my build failed. Based on the exceptions asdoc.exe was throwing it was pretty obvious the build was failing because none of the classes in the AIR API could be resolved.

I did a quick Google search and unfortunately there wasn’t much out there explaining how to resolve the errors. After a little more digging around and exploring of the sdk I was able to fix the build. Basically asdoc.exe needs to point to air-config.xml as well as the location of the air swc’s.

Below is the final build I am using which will allow you to compile ASDocs for your AIR projects:

<!– Adobe AIR ASDoc ANT Tasks –>
<project name="AIR ASDoc build" default="main" >
   
<!– defines all values for the ASDoc compiler –>
<property file="asdoc.properties" />
   
<!– main target: cleans and compiles ASDocs –>
<target name="main" depends="clean, create-docs" />
   
<!– deletes and recreates the asdoc directory –>
<target name="clean" >
  <delete dir="${output.dir}" />
  <mkdir  dir="${output.dir}" />
</target>
   
<!– runs the asdoc.exe compiler on the source –>
<target name="create-docs" >
 <exec executable="${asdoc.exe}" failonerror="true" >
  <arg line="-doc-sources ${src.dir}" />
  <arg line="-output ${output.dir}" />
  <arg line="-load-config ‘${frameworks}/air-config.xml’"></arg>
  <arg line="-library-path ‘${frameworks}/libs/’"></arg>
  <arg line="-library-path ‘${frameworks}/libs/air’"></arg>
 </exec>
</target>

</project>

You will also need the asdoc.properties file to go along with it:

# Modify the following properties to match your environment
# By default, the asdoc.exe property points to the location of
# asdoc.exe on Windows

sdk.dir=C:/Program Files/Adobe/Flex Builder 3 Plug-in/sdks/3.0.0
frameworks =${sdk.dir}/frameworks
src.dir =C:/workbench/clients/AIRCairngorm/
asdoc.exe =${sdk.dir}/bin/asdoc.exe
main.title =AIR Project title
window.title =Window title
output.dir =C:/workbench/asdoc

So if you happen to run into this problem in the future you can use the ASDocAntTask project to compile ASDocs for your AIR projects without the headaches.

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.