AIR Cairngorm 2.0

June 22nd, 2008

I have received quite a few emails since the release of AIR 1.0 and Flex 3.0 regarding the AIR Cairngorm API which I developed last year. In the time since I have been working primarily with a modified version of AIR Cairngorm which I used on a number of successful real world AIR applications, however I simply have not had the time to document and refactor for general use until recently.

In case you are not familiar with AIR Cairngorm it is an open source project built on top of Adobe Cairngorm which provides a framework for working with the Adobe AIR SQLite API while building an application with Cairngorm.

AIR Cairngorm is built around the SQLService class which essentially wraps the AIR SQL APIs to provide a uniform interface which can be utilized as a service, much in the same way one would work with RPC services in a typical Cairngorm application. SQLService provides an API for both synchronous and asynchronous implementations.

In the time since the initial development and release of AIR Cairngorm, which was during the early alpha releases of AIR, there has been many changes to the SQL APIs in AIR. In addition I have also developed some new best practices for working with Adobe AIR and Cairngorm, all of which I tried to roll into this latest release where possible.

The following is a brief description of the current AIR Cairngorm API:

AIRServiceLocator: The AIRServiceLocator is a sub class of Cairngorm ServiceLocator, therefore it inherits the same API as ServiceLocator while also adding additional support for working with local databases via the getSQLService and hasSQLService methods.
AIRServiceLocator

SQLService: The SQLService class essentially wraps the SQLStatement and SQLConnection classes. SQLService allows developers to create an mxml implementation defined on a Cairngorm ServiceLocator just as one would with typical RPC services (e.g. HTTPServices, WebService etc.)
SQLService

ISQLResponder: ISQLResponder provides a consistent API from which asynchronous SQLStatement execution results and faults can be handled. ISQLResponder is very similar to IResponder in that it defines both a result and fault handler however with a slightly different signature which is specific to a SQLStatement result / fault, (i.e. strongly typed parameters).
ISQLResponder

SQLStatementHelper: SQLStatementHelper is an all static utility class which facilitates substituting tokens in a SQL statement with arbitrary values.
SQLStatementHelper

I have also created a custom version of my Cairngen project specifically targeting AIR Cairngorm code generation. In addition I will be making some future updates to AIR Cairngorm which will include support for various other AIR APIs in Cairngorm, so stay tuned.

Below I have provided downloads to the source, binary, air.cairngen and asdocs as well as asynchronous and synchronous example projects:
source
binary
examples
asdoc
air cairngen
air cairngorm (all)

Let design guide, not dictate

May 27th, 2008

A good design should be intended to guide implementation, not dictate it, and for good reason as in the real world of software development requirements and systems are far to complex and dynamic in nature to view a technical design as anything more than a basic prescription intended to form the basis of an efficient implementation. Yet far too often many people seem to believe that once a detailed design has been completed and approved implementation should be a breeze; however this is just not a very realistic expectation.

For instance, one of my core job responsibilities is to review technical design documents and provide feedback and direction. This is an iterative process which typically has between 1-3 iterations depending on the complexity of the system. Initially an engineer is given requirements for review; he/she then begins an initial draft of the design and once completed passes it on to me for review. I then review the document and provide feedback where applicable, either via annotations to the document itself or by sitting with the developer, which is by far my preferred process. Should modifications be required the developer will then make revisions as needed. This process is repeated until final design has been approved. At first it may appear as if only a single iteration of design and review would be needed, however more often than not, requirements may not be completely understood during the beginning stages of design, nor are they set in stone so it is very common that a design will need to change during the early stages of a project or even throughout the entire development stage. Once final design has been completed an engineer then begins implementing the design. Theoretically this may appear to be a quite simple process: create a great design which contains as much detail as possible, review it, make revisions and approve it, then just pass it off to any old developer to implement and that’s it, done - wrong!

There are a number of problems to this approach. Below I have outlined the three I feel are most significant and the solutions I have found to address each.

  • Creativity
    The first problem is that a design which goes into too much detail completely limits or even worse, kills creativity - which in my opinion is the single most important trait a developer can possess, especially when designing. The developer is now merely a typist and will undoubtedly become very bored when implementing the design, especially if it is not even his/her design to begin with! Because of this lack of creativity the final code will ultimately suffer and bugs can be expected. Keeping design on a higher level allows developers to have the creative freedom needed to provide quality implementations and work they can feel is their own.
  • Flexibility
    The second problem is that the more detailed and precise the design the less flexibility there is when requirements change and modifications need to be made to the design and thus implementation. For example, if a design contains very low level details, such as method signatures and other implementation specific details the ability to change the design now becomes increasingly complex and will result in much of the design needing to be reworked significantly. In addition the more detail there is the harder it is to write unit tests against the design as the actual implementation has already been defined. Designs need to be very high level and should not go beyond identifying class names, their responsibilities, relationships and dependencies.
  • Tools
    The third problem, which is probably the single most consistent problem I have recognized in my experiences is that far too often developers get caught up in all the details of UML notation and related tools. Again this negates creativity and results in the developer concentrating more on making the design look technically correct rather than concentrating on designing towards a great solution to the problem at hand. In addition this also results in unnecessary time being spent to complete the design, time which could be much better spent on something that produces a better pay off for the project. Now this is not to say that UML shouldn’t be used, actually quite the contrary. I strongly feel that a final design must be in UML as a shared language is needed in order for everyone involved in the design and implementation to easily understand the design. I insist on a technique where developers draw out their design in any way that can be easily understood by them without having to give any thought to anything other than the design itself. Only once the design is finished is the use of Visio or other UML tools to be used.
  • The above illustrates the three most common design issues I have encountered, most of which pertain to over detailed designs, as well as the approach I take in addressing each. If you have not encountered any of these issues in your own work than that is generally a good sign, however try to keep them in mind when designing as it will pay off in the end. The important thing to keep in mind when designing is to design for flexibility and simplicity. Less is usually more and the KISS principle, especially when applied to software design will always pay off in the end.

    Implementing interfaces in mxml

    May 19th, 2008

    Most Flex developers are aware that mxml files are essentially declarative representations of ActionScript classes, that is, during compilation the mxmlc compiler generates ActionScript 3.0 classes from mxml files before being converted into bytecode that runs in Flash Player. This can be seen by setting the compiler argument -keep-generated-actionscript to true.

    You may be thinking “yeah I know this, and…”, however in the past week I have had two talented Flex developers say to me: “but you can’t implement interfaces in mxml… Can you?”

    Now if you think about that statement a bit more you will probably realize that you most certainly can, however it mat not seem so obvious at first as developers tend to think of mxml for what it is, a markup language and not necessarily from a compilation perspective.

    So in case you are not aware how interfaces can be implemented in mxml I have provided a few simple examples below which demonstrate how a custom component can implement an interface, in this case mx.rpc.IResponder.

    First you define the interface that the component will implement using the implements property of the component.

    <?xml version="1.0" encoding="utf-8"?>
    <mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
             implements="mx.rpc.IResponder" >
    </mx:VBox>

    Next you simply implement the operations defined by the interface as you normally would in a class:

    <?xml version="1.0" encoding="utf-8"?>
    <mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
             implements="mx.rpc.IResponder" >
        <mx:Script>
            <![CDATA[

                public function result(data:Object) : void
                {
                    // implementation
                }
               
                public function fault(info:Object) : void
                {
                    // implementation
                }
            ]]>
        </mx:Script>
    </mx:VBox>

    Now you may be wondering how multiple interfaces are implemented in mxml? This is very easy as well, simply specify the fully qualified class path of each interface as a CSV (Comma-separated values). An example can be seen in the following:

    <?xml version="1.0" encoding="utf-8"?>
    <mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
              implements="mx.rpc.IResponder,mx.core.IUID" >
        <mx:Script>
            <![CDATA[
                    public function result(data:Object) : void
                    {
                         // implementation…
                    }

                    public function fault(info:Object) : void
                    {
                         // implementation…
                    }

                    public function get uid() : String
                    {
                         // implementation…
                    }

                    public function set uid(value:String) : void
                    {
                         // implementation…
                    }
            ]]>
        </mx:Script>
    </mx:VBox>

    And that’s all there is to it.

    Package-level function closures in ActionScript

    May 6th, 2008

    Package-level function closures are very useful for creating generalized functionality which does not require a class (static methods) or instance of a class (instance methods).

    Unlike static and instance methods package-level function closures are not associated with a class or instance of a class but rather with a package. There are no syntactical differences between package-level functions and static or instance methods.

    Package-level functions are for the most part utility functions; for instance the flash.utils package contains a number of package-level functions, the most common of which are describeType(), getDefintionByName(), getTimer() and so forth.

    Package-level function closures are created by defining a function directly inside the body of a package (where class and interfaces are defined), as can be seen in the following example:

    package com.ericfeminella.display
    {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.IBitmapDrawable;
    import mx.graphics.ImageSnapshot;

    /**
     *
     * Creates a snap shot of a <code>Bitmap</code> object
     * from the specified <code>IBitmapDrawable</code>
     * implementation.
     *
     * @param  display object in which to create the snapshot
     * @return <code>Bitmap</code> snapshot of the display object
     *
     */
        
    public function createSnapShot(target:IBitmapDrawable) : Bitmap
    {
        return new Bitmap(ImageSnapshot.captureBitmapData(target));
    }
    }

    Calling a package level function is straightforward, simply import the function just as you would a class or interface and then invoke the function directly…

    // import package function
    import com.ericfeminella.display.createSnapShot;

    // once imported the function can be invoked
    createSnapShot( this );

    Typically you will find that most functionality can be grouped to a Class or an instance object, however on occasion you may identify specific functionality which is common to packaged functionality as opposed to a specific object, and in these cases utilizing package-level functions is a great option.