Odds and Ends

Change is afoot in the lands of Flash and Flex

November 14th, 2011

Adobe has recently made a number of rather muddled announcements around Flash and Flex that have caused confusion and concern in the development community. In this post I hope to clarify what actually has been said and present my take on what it might actually mean for those of us on the receiving end.

Adobe has made it clear over the past while that, like the other big players, they see HTML5 as a major force for expressive and rich content on the web. Actions such as the acquisitions of PhoneGap and Typekit, the development of Edge and Wallaby and their contributions to WebKit, jQuery and the CSS3 specification have backed up their openness about where they see the future heading. Unfortunately, how they see Flash (and Flex) fitting into this vision has been a little unclear, and recent announcements have only confused matters further.

Image used under creative commons licence from Janielle Beh

Flash

The most misunderstood and misreported of the announcements is that Adobe is ceasing active development of the Flash Player plug-in for mobile browsers, i.e. there will be no new versions of the browser plug-in for your mobile phone or tablet (except for critical patches). Development of the desktop browser version of the plug-in is very much continuing, with various interesting new APIs and features already announced for Flash Player 12. Personally, I am not surprised by the announcement regarding the plug-in for mobile browsers.

As users on mobile devices we don’t really use, expect or want overly rich content on the browser because it tends to be cumbersome due to high network latency and expensive (depending on your data tariff). Rather, we go to apps whenever we want anything more than fairly static content. Without an equivalent ubiquity to that on desktop browsers, Flash Player is never going to be in any kind of position to even attempt to change that behaviour, and attempting to achieve that penetration looks like a complete non-starter considering the platforms blocking it outright and the vast resources apparently required to support it for the others

In addition to these reasons, the ubiquity of modern, HTML5-supporting browsers on mobile devices undermines one of the other strong motivations for the use of Flash Player. Namely, that it is a solution to the issue of backwards-compatibility and feature support that plagues development for desktop browsers. Few would argue that HTML5 as it currently stands on mobile devices is unable to reliably provide the (limited) richness desired for web content.

Flex

The (rather tepid) announcement regarding Flex that Adobe has made is that after the release of Flex 4.6 in a few weeks, governance of the SDK development is going to change significantly. It is going to be handed over to an open source foundation consisting of members of the current development team, developers from the community, members of the Spoon Project and contributors from enterprise companies. In some respects Adobe has in the past hinted that something like this might happen. At AdobeMAX 2010, Deepa Subramaniam mentioned that they were considering allowing community developers to submit patches that would have to pass through Adobe’s test suits before becoming candidates for inclusion, and this move seems like a logical extension of that train of thought. I feel the Flex SDK actually now requires the kind of TLC only a more open governance can provide because I think it could do with a focus on behind-the-scenes fixing and improving rather than glamorous, headline-grabbing new features.

Flex developers are understandably confused and frustrated by this announcement. As recently as AdobeMAX 2011, Adobe appeared to be giving a strong message about the future of Flex as its solution for enterprise-grade development, with a clear roadmap. The change of governance inevitably means a change of roadmap, regardless of how strong an influence Adobe might have over the new foundation. With hindsight, it is perhaps more obvious that Adobe’s enterprise-related angle has actually related to the future of Flash Player rather than Flex. However, rather than being upset by the timidity with which Adobe has approached this change and seeing it as a negative move, I think the Flex community and business and enterprises with a stake in the technology should embrace this change and realise the opportunity it potentially provides. There is a lot of money and time committed to Flex other than Adobe’s and Adobe is still fully committed to the technologies that underpin Flex, both Flash and AIR, so it is all but guaranteed for the foreseeable future at the very least.

Image used under creative commons licence from Janielle Beh

AIR

At the same time as all of this, Adobe has firmly re-stated its commitment to AIR. Most of the development of the desktop Flash Player plug-in carries over into AIR, and a whole number of new AIR features primarily targeting mobile devices have also been announced. With the recognition that users go to apps for rich content on mobile devices this makes absolute sense, given that, in my opinion, AIR is one of the best genuinely cross-platform development targets. Flex developers in particular should take heart from this, considering the close coupling between the Flex framework and the AIR API. Over time, we may start seeing the runtime shift more towards its JavaScript and HTML capabilities or, at least, applications taking more explicit advantage those capabilities, but at worst AIR would allow a smooth and transparent transition between the technologies.

Summary

Overall, my impression is that Adobe have a similar view on how HTML5 and Flash will play out in the short and long term to the one we laid out in our white paper. Namely, in the short term, the richer, more interactive and dynamic the content/application being developed requires, the clearer the choice for Flash/Flex over HTML5 is. However, over time, as tooling, developer skills and technology improve, and the spread of mobile devices continues at its current pace, HTML5 is likely to become the “better” choice rather than Flash/Flex.

The exciting prospect here is that, historically, what Adobe has excelled at is tooling rather than technology. Photoshop, Premiere, Illustrator, Flash Professional and others are unquestionably fantastic tools, and Edge has already hinted that Adobe could reach similar standards for HTML5 authoring. Adobe’s experience in bona fide IDEs comes primarily from its Flash and Flex tools so it would be reasonable to expect that any new HTML5 tools will feel fairly natural to any developers used to their existing IDEs. Again, Edge supports this view, since it is remarkably similar to the older Flash authoring tools.

It is interesting to contrast Adobe’s apparent approach to the future with HTML5 against that of Google and Microsoft. Where as Adobe appears to content to position itself strongly somewhat on the sidelines from where it might have a better vantage point to allow it to dive in when appropriate, Google and Microsoft seem, to some degree, more intent on outright dictation of the direction we’re all heading in. Regardless of how things pan out, it’s going to continue to make for a fascinating spectacle.

UPDATE: Head here for my colleague Colin’s more general thoughts relating to these announcements, they are well worth a read

UPDATE: The Flex team have added further information to their announcement that further justify my call for optimism.

Static Initialisation in Flex

July 29th, 2011

For reasons best ignored I recently investigated the different ways in which static initialisation code can be run in Flex. As well as a direct equivalent to the static initialiser blocks available in Java and C#, Flex has a couple of subtle variants that can prove useful in different circumstances.

First up, the “standard” static initialisation technique, the direct equivalent to that found in Java and C#. The block of code shown below will execute once, the first time an instance of MyClass is created before that first constructor call is executed.

public class MyClass
{
    private static var initialised:Boolean = initialise();
    private static function initialise():Boolean
    {
        trace("static initialisation block that will execute" +
              " the first time 'new MyClass()' is called anywhere");
    }
}

If the intention of your code block is to create and initialise a static variable then this approach is clear and obvious. However, if you want to run some general initialisation code you still require a dummy variable and a return type on the static function. This is because the variable initialisation is the hook required to execute the function. This technique was used throughout the Flex 3 Framework code for style initialisation on components (an approach no longer in Flex 4 because of the improvements to style initialisation).

The second technique is that used by the Automation framework that is included with the SDK. This approach allows code to be executed when an application or module is loaded. The code would look as follows:

[Mixin]
public class MyClass
{
    public static function init(root:DisplayObject):void
    {
        trace("static initialisation block that will execute" +
              " when the application or module first loads");
    }
}

The root argument will be an ISystemManager or IFlexModuleFactory instance depending on whether the class was loaded as part of an application or module. Note that for the [Mixin] to be picked up the class must be included in the application or module, i.e. it must be referenced elsewhere in code or explicitly added using appropriate compiler arguments

The final technique comes from ActionScript’s ECMAScript heritage, in particular its prototype-based object model. In this case, code is written directly into the class scope, i.e. not inside a function block. This code will be executed the first time the class is executed in any way. That is, if the class uses the [Mixin] technique then it will execute along with the mix-ins static init function, otherwise it will be the equivalent to the “standard” approach and execute the first time the class is instantiated.

public class MyClass
{
    trace("static initialisation taking advantage of prototype-based object model");
}

I know it looks odd, but it genuinely is valid!

So putting it all together in the most artificial of examples, the following class would produce the trace output 1, 2, 3, 4 (with 3 and 4 only appearing when an instance of the class is instantiated):

[Mixin]
public function MyClass
{
    trace("1");
 
    public static function init(root:DisplayObject):void
    {
        trace("2");
    }
 
    private var initialised:Boolean = initialise();
    private function initialise():Boolean
    {
        trace("3");
    }
 
    public function MyClass()
    {
        trace("4");
    }
}

Flex, Silverlight or HTML5? Time to decide…

May 6th, 2011

Building on the experience and expertise within Scott Logic, my colleague, Colin Eberhardt, has produced an excellent whitepaper considering the three big web technologies at the moment: Flex, Silverlight and HTML5.


Recent advances in web technologies have resulted in a complex landscape for application
developers to navigate. Coupled with the recent boom in new platforms, from desktops, netbooks,
smartphones to tablets, making an informed and future proof technology choice is all the more
difficult. In this paper we will set technology bias and politics aside to navigate the similarities and
differences between Flex, Silverlight and HTML5 and give you the power to decide.

This white-paper is aimed at technical decision makers who are looking to choose the correct
technology for web application development.

Head over to Colin’s blog to download or read the full paper and to add to the conversation.

Updating Flex Sparkline to Flex 4

April 19th, 2011

In a previous post I presented a library of sparkline implementations for Flex 3. I have finally gotten round to updating it for Flex 4. The new source code, documentation and pre-compiled swf (namespace: http://www.scottlogic.com/sparkline) can be obtained from here. As before, the components are being made available under the GNU General Public License.

As you can see, the versions appear identical:

Flex 3

Flex 4

Updating to Flex 4

For those of you interested in some of the changes required to migrate code from Flex 3 to Flex 4, here follow some of the details required to update this particular code.

The main change was due to Flex 4 essentially deprecating the StyleManager class and its static methods in order to provide mechanisms allowing modules to have independent style declarations. At the forefront of this change is the new IStyleManager2 interface, an instance of which can be obtained from the static getStyleManager method on StyleManager or, preferably, the styleManager property of UIComponent. In practice, using the Sparkline class as an example, this means changing from the static Flex 3 style declaration approach:

public class Sparkline extends SparklineBase
{
    /**
     *  @private
     */
    private static var stylesInited:Boolean = initStyles();
    /**
     *  @private
     */
    private static function initStyles():Boolean
    {
        var sd:CSSStyleDeclaration = StyleManager.getStyleDeclaration("Sparkline");
        if (!sd)
        {
            sd = new CSSStyleDeclaration();
            StyleManager.setStyleDeclaration("Sparkline", sd, false);
        }
 
        sd.defaultFactory = function():void
        {
            this.lineStroke = new Stroke(0x828282, 1);
            this.markerFill = new SolidColor(0x2963a3);
            this.markerStroke = new Stroke(0x2963a3, 0, 0);
            this.markerRadius = 2;
            this.normalRangeFill = new SolidColor(0x000000, 0.1);
        }
 
        return true;
    }
 
    ...
 
}

To overriding UIComponent‘s moduleFactory property to provide the “hook” for invoking the style declaration:

public class Sparkline extends SparklineBase
{
    /**
     * @private
     */
    private var _moduleFactoryInitialized:Boolean;
 
    /**
     * @private
     */
    public override function set moduleFactory(factory:IFlexModuleFactory):void
    {
        super.moduleFactory = factory;
        if (_moduleFactoryInitialized)
            return;
        _moduleFactoryInitialized = true;
        initStyles();
    }
 
    /**
     * @private
     */
    private function initStyles():void
    {
        var sd:CSSStyleDeclaration = styleManager.getStyleDeclaration("com.scottlogic.sparkline.Sparkline");
        if (!sd)
        {
            sd = new CSSStyleDeclaration();
            styleManager.setStyleDeclaration("com.scottlogic.sparkline.Sparkline", sd, false);
        }
        sd.defaultFactory = function():void
        {
            this.lineStroke = new SolidColorStroke(0x828282, 1);
            this.markerFill = new SolidColor(0x2963a3);
            this.markerStroke = new SolidColorStroke(0x2963a3, 0, 0);
            this.markerRadius = 2;
            this.normalRangeFill = new SolidColor(0x000000, 0.1);
        }
    }
 
    ...
 
}

You will also see that as of Flex 4, getting style declarations now requires a fully qualified class name rather than just the name of the class, e.g. com.scottlogic.sparkline.Sparkline rather than Sparkline. As before, this change is required due to the underlying shift in the approach used for style management by the framework in order to support independence between modules.

The other update required was due to the changed IFill and IStroke interfaces. In particular, the begin method on IFill takes an additional targetOrigin argument of type Point that specifies intended origin of the shape drawing. Similarly, IStroke‘s apply method now takes two additional arguments, targetBounds and targetOrigin, to provide the same drawing manipulation/restriction as IFill. Fortunately, the SDK team appear to have anticipated the potential complications and frustrations arising from these changes and have implemented them so that specifying a null value for the additional arguments results in identical behaviour to that which would have occurred in the Flex 3 code.

Presentation Model (or MVVM) with Mate

January 31st, 2011

This post introduces the Presentation Model (or MVVM) architectural pattern as one approach for creating “better” large-scale Flex applications and shows how the Mate Framework can be leveraged to not only achieve this pattern but increase separation of concerns above that of a “standard” Flex application.

Background

One of the great advantages Flex is that it makes creating applications very quick and easy by allowing ad-hoc mixing of MXML and ActionScript. This is ideal for rapid prototyping and can be all that is required for small applications. It also means anyone new to the technology can easily get started and relatively quickly put together quite rich applications. However, this architectural pattern, termed Autonomous View, does not scale well for larger, real-world projects. Fortunately, there are a numerous other architectural patterns – most famously(?) Model-View-Controller (MVC) – that attempt to directly address these concerns. Furthermore, various frameworks have been developed for Flex that specifically target these patterns. For example, both Cairngorm and PureMVC were designed for developing applications using the MVC architecture. There are many articles on the web considering the merits of different architectural patterns (and related Flex-specific frameworks). This article focuses on the Presentation Model architectural pattern, and a specific implementation of it using the Mate Framework, as a particularly useful approach to application development in Flex. Note that Mate is not designed to target any particular architectural pattern and that I am merely introducing its use with the Presentation Model pattern as one of many possible approaches, not a definitive or necessarily best one.

Presentation Model (or Model-View-ViewModel)

Presentation Model is an architectural pattern derived from Model-View-Controller (MVC) and originally introduced by Martin Fowler. Since then, Microsoft has introduced the Model View ViewModel (MVVM) pattern as a specialisation of Presentation Model that extends the original concept by adding a Model to make it more relevant to modern application development. I have adopted the MVVM terminology as I believe it better defines the entities involved in the pattern (purely because of its name).

The key features of the pattern are:

  • Model is the object model representation of state (whether as real state or as a data-access layer representation of the state)
  • View is the GUI elements
  • View model contains all GUI state and logic
  • View observes the view model and updates accordingly
  • View is “aware” of the view model
  • View model has no knowledge of the view

The observation required by the view is one of the reasons Flex is particularly suited to this pattern, as its binding functionality is simple and powerful implementation of observation. Additionally, the pattern ties in neatly to the relative merits of Flex’s two languages, creating a simple conceptual model for developers:

  • View = MXML = components & layout
  • ViewModel = ActionScript = behaviour & state

The main advantages of Presentation Model (or MVVM) are the clear code separation between GUI layout and behaviour and the testability this inherently introduces (compared to Autonomous View and similar). As well as the advantages this brings in all object-oriented technologies, in Flex this is particularly useful when its Module functionality is leveraged, as it creates clear and easy cut points. The disadvantages of this pattern is that it can be relatively verbose and sometimes requires information to be passed through view model instances in order to appropriately traverse the display tree. However, as I’ll show in the worked example below, the Mate framework provides some mechanisms that can drastically reduce the latter problem.

Mate

Mate is an event-driven Flex framework that provides both dependency injection and mechanisms to “glue” your code together, thereby enabling you to produce very loosely coupled code. The worked example below assumes some basic understanding of how Mate works, so if it is unfamiliar I recommend at least running through their Getting Started tutorial. There are also other excellent introductory articles and examples.

Worked Example

Here follows a worked example showing how the Mate framework can be leveraged to not only use the Presentation Model architectural pattern, but also add further elegance by using some of its core features. As previously mentioned, Gilles Guillemin has produced an excellent set of articles introducing Mate, and he even has an article that focuses on the exact same topic as this article. Unfortunately, his Presentation Model article does not continue with the nice example application he used in his previous articles and instead uses an overly simplistic example that does not present an overly compelling case.

The example below applies the Presentation Model (or MVVM) architectural pattern to the example Gilles Guillemin created for his introductory series to Mate. That is, an application with a global count that can be increased and decreased both directly and by manipulating a dynamic number of counters. Each counter maintains a sub-total that is the sum of its two sub-counters. Additionally, there is a global countdown that on reaching 0 resets all counts at all levels.


Source code

Core code

In order to not get too bogged down in application specifics and better focus on how Presentation Model (or MVVM) and Mate are used, I will focus on the sub-counter block of the user interface and logic. As shown in the class diagram below, the entities involved are: the view, SubCounterView; the view model interface, ISubCounterViewModel; and, an implementation of the view model interface, SubCounterViewModel. The diagram also shows how I have added some unifying interfaces for views and view models and a base class for view models containing some common functionality (more detail on this later when explaining the Mate-related specifics).

The observant among you will have spotted that there are no model classes mentioned. This is because in this particular example the models are the integer counts and as such do not require a custom class type. In more real-world applications it would be normal to have custom model classes that are used by the view models to maintain state.

Presentation Model UML
Class diagram abstractly showing presentation model example

The SubCounterView MXML consists of the viewModel property, a Mate map (more detail on this later when explaining the Mate-related specifics), a Grid to neatly lay out the local and sub-total counts and a couple of buttons to increase and decrease the local count. All state, such as the two count labels, is observed from the view model using binding and all logic/behaviour, such as the count increasing and decreasing, is delegated to the view model:

<?xml version="1.0" encoding="utf-8"?>
<mx:VBox
    xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:map="maps.*"
    implements="views.IView"
>
    <mx:Script>
        <![CDATA[
            import viewModels.ISubCounterViewModel;
            import viewModels.IViewModel;
 
            [Bindable]
            private var _viewModel:ISubCounterViewModel;
            /**
             * @see IView.viewModel
             */
            public function get viewModel():IViewModel
            {
                return _viewModel;
            }
            /**
             * @private
             */
            public function set viewModel(value:IViewModel):void
            {
                if (!(value is ISubCounterViewModel))
                {
                    throw new Error("ISubCounterViewModel instance expected");
                }
                _viewModel = ISubCounterViewModel(value);
            }
        ]]>
    </mx:Script>
 
    <map:SubCounterViewMap dispatcher="{this}" />
 
    <mx:Grid width="100%">
        <mx:GridRow>
            <mx:GridItem>
                <mx:Label text="Subtotal:"/>
            </mx:GridItem>
            <mx:GridItem>
                <mx:Label text="{_viewModel.subTotal}"/>
            </mx:GridItem>
        </mx:GridRow>
        <mx:GridRow>
            <mx:GridItem>
                <mx:Label text="Amount:"/>
            </mx:GridItem>
            <mx:GridItem>
                <mx:Label text="{_viewModel.count}"/>
            </mx:GridItem>
        </mx:GridRow>
    </mx:Grid>
 
    <mx:HBox>
        <mx:Button label="+" click="_viewModel.increaseCount()"/>
        <mx:Button label="-" click="_viewModel.decreaseCount()"/>
    </mx:HBox>
 
</mx:VBox>

As can be seen in the above code and class diagram, the view is tied to a view model interface rather than concrete class. Although this may seem unnecessarily verbose it brings some powerful benefits. it allows different view models, and therefore different logic and behaviour, to be used with the same view (i.e. inversion of control). This is both a relatively common code requirement and a useful mechanism for activities such as testing. It allows for the potential case of a single view model being shared across multiple views. A final (more arguable) benefit is that it encourages the developer to focus solely on the view rather than be distracted by behavioural details.

The ISubCounterViewModel interface looks like this:

/**
 * Interface for any presentation model that is to be used
 * with the SubCounterView view.
 */
public interface ISubCounterViewModel extends IViewModel
{
	[Bindable("subTotalChanged")]
	/**
	 * The total of all grouped sub-counter's counts.
	 */
	function get subTotal():int;
	/**
	 * @private
	 */
	function set subTotal(value:int):void;
 
	[Bindable("countChanged")]
	/**
	 * The local count.
	 */
	function get count():int;
 
	/**
	 * Increases the local count.
	 */
	function increaseCount():void;
 
	/**
	 * Decreases the local count.
	 */
	function decreaseCount():void;
}

The implementation of the interface, SubCounterViewModel, then looks like this:

/**
 * Default implementation of ISubCounterViewModel.
 */
public class SubCounterViewModel extends ViewModelBase implements ISubCounterViewModel
{
	private static const SUB_TOTAL_CHANGED:String = "subTotalChanged";
	private static const COUNT_CHANGED:String = "countChanged";
 
	//------------------------------------
	//
	//           Constructor
	//
	//------------------------------------
 
	/**
	 * Constructor
	 */
	public function SubCounterViewModel(dispatcher:IEventDispatcher)
	{
		super(dispatcher);
	}
 
 
	//------------------------------------
	//
	//           Properties
	//
	//------------------------------------
 
	//----------------------------------
	//  subTotal
	//----------------------------------
 
	private var _subTotal:int;
	[Bindable("subTotalChanged")]
	/**
	 * @see ISubCounterViewModel.subTotal
	 */
	public function get subTotal():int
	{
		return _subTotal;
	}
	/**
	 * @private
	 */
	public function set subTotal(value:int):void
	{
		if (value != _subTotal)
		{
			_subTotal = value;
			dispatchEvent(new Event(SUB_TOTAL_CHANGED));
		}
	}
 
	//----------------------------------
	//  count
	//----------------------------------
 
	private var _count:int;
	[Bindable("countChanged")]
	/**
	 * @see ISubCounterViewModel.count
	 */
	public function get count():int
	{
		return _count;
	}
	/**
	 * @private
	 */
	public function set count(value:int):void
	{
		if (value != _count)
		{
			_count = value;
			dispatchEvent(new Event(COUNT_CHANGED));
		}
	}
 
 
	//------------------------------------
	//
	//           Functions
	//
	//------------------------------------
 
	/**
	 * @see ISubCounterViewModel.increaseCount
	 */
	public function increaseCount():void
	{
		count++;
		subTotal++;
 
		// inform everyone else that the count has changed
		dispatchEvent(new CountEvent(CountEvent.LOCAL_UPDATE, _subTotal));
	}
 
	/**
	 * @see ISubCounterViewModel.decreaseCount
	 */
	public function decreaseCount():void
	{
		count--;
		subTotal--;
 
		// inform everyone else that the count has changed
		dispatchEvent(new CountEvent(CountEvent.LOCAL_UPDATE, _subTotal));
	}
}

The count and subTotal properties are straightforward Bindable properties with custom binding events. The increaseCount and decreaseCount methods are also very simple: they increase or decrease both the local count and the sub-total and then dispatch an event to inform that the sub-total has changed. The assumption here is that its local knowledge of the sub-total is correct and that it will appropriately be informed if that sub-total is changed elsewhere (much as it informs “others” of any change it makes, by dispatching the CountEvent). By making this assumption and using events for functional communication rather than explicit method calls we introduce loose coupling by using the observer pattern. Normally this would require some quite messy code to introduce and handle, but, as I will show, the Mate framework provides mechanisms that elegantly support this approach.

Glueing everything together

At this point we have all the constituent parts of the application, but they are not actually combined together in any functional way. Mate’s EventMap and LocalEventMap components are a powerful mechanism whereby this glue code can be introduced with minimal impact on any of the core code and easily swapped in and out. As exemplified in the SubCounterView code, maps are introduced as a simple MXML tag and beyond that are entirely self-contained. They leverage Flex’s event mechanism by hooking into an application’s display tree, either at the global stage level in the case of EventMap or at the level of a specific DisplayObject in the case of LocalEventMap (see how the dispatcher of the SubCounterViewMap in the SubCounterView above is set to be the view). To achieve better separation of concerns (and to avoid coding using what can quickly become little more than a global variable mechanism) LocalEventMaps are always preferable to EventMaps.

The first part of pulling the parts of the application together is to appropriately combine views with their view model instances. Mate’s map components allow us to inject these dependencies Injectors tags. The Injectors component can target any class instance that is added to the display tree below the map’s dispatcher or that is created within the scope of the map. With this hook, an ObjectBuilder is used to create the desired view model before being injected into the view using the PropertyInjector. This way we can very specifically target (and easily change) any desired view/view-model combinations. Here is what combining the SubCounterView with its SubCounterViewModel looks like in the SubCounterViewMap:

<mate:Injectors target="{SubCounterView}">
    <mate:ObjectBuilder
        generator="{SubCounterViewModel}"
        constructorArguments="{scope.dispatcher}"
    />
    <mate:PropertyInjector source="{lastReturn}" targetKey="viewModel" />
</mate:Injectors>

The second part of glue code required for the fully functional application is to turn the event communication assumption(s) of the view models (see SubCounterViewModel code and explanation above) into reality. Once again, Mate’s map components form the basis, but here it is the EventHandlers tag that provides the desired hook. The EventHandlers component allows a response to any event bubbled past the map’s dispatcher (or globally, depending on both the map type and the EventHandlers own dispatcherType). This response can be any sequence of actions, such as invoking a method on a class (MethodInvoker), setting a property (PropertySetter) or even creating another event (EventAnnouncer). An example from the application above is the reset event that is dispatched when the countdown reaches zero and all counters should be reset. For the SubCounterViewModel this is handled by setting the zero value from the reset as its local count value, as shown in the following code snippet from SubCounterViewMap:

<mate:EventHandlers type="{CountEvent.RESET}" dispatcherType="global">
    <mate:PropertySetter
        generator="{SubCounterViewModel}"
        source="event"
        sourceKey="newCount"
        targetKey="count"
    />
</mate:EventHandlers>

As shown in the class diagram and SubCounterViewModel code above (and highlighted by the ObjectBuilder in the view/view-model injection code above), the view model classes all require a reference to an IEventDispatcher instance to act as its event dispatcher despite themselves also being IEventDispatcher implementations. This is the compromise required to use Presentation Model in conjunction with Mate. As previously mentioned, Mate’s key components, EventMap and LocalEventMap, hook into the display tree’s event hierarchy. Therefore, the view model classes must dispatch their events into the display tree to appropriately tie in with the maps. Hence the IEventDispatcher reference required by all view models. Fortunately this functionality is easily captured by a common base class for all view models in such a way that this becomes all but transparent to specific view model types. See the source code for the worked example for further details.

And there you have it, the Presentation Model (or MVVM) building blocks and how to combine them into an application using the Mate framework in such a way that the various concerns of the code are cleanly separated.

Testing

As mentioned in the background information, testability is one of the strong drivers behind the Presentation Model (or MVVM) architectural pattern. To highlight this, the source code for the example above includes unit tests (using FlexUnit) for, amongst others, the view model classes, thereby showing how the pattern allows testing of view-related logic. By appropriately using interfaces and inversion of control throughout, the testability of the code is further enhanced as this allows us to leverage mock objects in the unit tests. I have used Mock4AS because I happened to have it to hand, but there are several other good mocking libraries for ActionScript, such as asMock and Mockolate, so take a look at the different ones and pick your favourite (I don’t have one yet).

Summary

Hopefully this article has highlighted the reason to consider the design of your Flex application in order to improve its maintainability and testability, and has introduced the Presentation Model pattern coupled with the Mate Framework as one of the potential approaches to solving these problems. I have only introduced a small sub-set of Mate’s components and their capabilities so would encourage you to delve deeper into the documentation, tutorials and examples to gain a better understanding of the full Mate framework and its subtleties even if you are not interested in the Presentation Model pattern.

You can download the full source code for the Flex example given in this blog post here: MatePresentationModel-src.zip.

Flex Charts vs Silverlight Charts – a test of Performance

November 16th, 2010

This post follows on from the comparison of two Silverlight chart libraries produced by my colleague, Colin Eberhardt, by adding an implementation of the simple image processing tool in Flex using the Flex Charting library to the comparison. The results show that the Flex Charts perform easily as well as the Visiblox charts without the need to specifically consider performance.

Since Colin produced his comparison of the Silverlight Toolkit and Visiblox charts there has been some noted interest in how Flash stacks up against them. This seems to be part of a general drive across the development community to gain a better understanding of the relative strengths of Flash/Flex, Silverlight and HTML5. In order to contribute a little to this, I produced a comparable application to those of Colin using the charting library that is part of the free, open-source Flex 4 SDK.

Here are my Flex application and the “winning” application from Colin’s investigation side-by-side. Click and drag a line across the image to plot the RGB pixel intensities along the line in the chart above. From these examples, it is clear that there is little to differentiate them performance-wise.

Flex Chart Visiblox Chart

Get Microsoft Silverlight

[Squirrel image used royalty free from stock.xchng; hare image used under CC licence from flickr]

Implementation

For details of the implementation of the Visiblox example above, see the original post. The mark-up for the Flex example above is as follows:

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx" >
    <s:layout>
        <s:VerticalLayout />
    </s:layout>
 
    <fx:Declarations>
        <s:SolidColorStroke id="axisStroke" color="#cccccc" weight="1" />
    </fx:Declarations>
 
    <s:Group width="100%" height="100%">
        <mx:CartesianChart id="chart" width="100%" height="100%" visible="false">
            <mx:horizontalAxis>
                <mx:LinearAxis id="xAxis" />
            </mx:horizontalAxis>
            <mx:horizontalAxisRenderers>
                <mx:AxisRenderer axis="{xAxis}" axisStroke="{axisStroke}"
                                 showLabels="false" tickPlacement="none" />
            </mx:horizontalAxisRenderers>
            <mx:verticalAxis>
                <mx:LinearAxis id="yAxis" />
            </mx:verticalAxis>
            <mx:verticalAxisRenderers>
                <mx:AxisRenderer axis="{yAxis}" axisStroke="{axisStroke}"
                                 tickPlacement="outside" tickStroke="{axisStroke}" />
            </mx:verticalAxisRenderers>
            <mx:series>
                <mx:LineSeries yField="red">
                    <mx:lineStroke>
                        <s:SolidColorStroke color="#aa0000" weight="1" />
                    </mx:lineStroke>
                </mx:LineSeries>
                <mx:LineSeries yField="green">
                    <mx:lineStroke>
                        <s:SolidColorStroke color="#00aa00" weight="1" />
                    </mx:lineStroke>
                </mx:LineSeries>
                <mx:LineSeries yField="blue">
                    <mx:lineStroke>
                        <s:SolidColorStroke color="#0000aa" weight="1" />
                    </mx:lineStroke>
                </mx:LineSeries>
            </mx:series>
        </mx:CartesianChart>
 
        <s:Label id="instructions" visible="{!chart.visible}"
                 horizontalCenter="0" verticalCenter="0"
                 fontSize="9" color="#cccccc"
                 text="Use the mouse to 'drag' a line across the image below." />
    </s:Group>
 
    <s:Group>
        <mx:Image id="image"
                  source="@Embed(source='squirrel.jpg')"
                  mouseDown="imageMouseDownHandler(event)"
                  mouseUp="imageMouseUpHandler(event)"
                  mouseMove="imageMouseMoveHandler(event)" />
        <s:Line id="line">
            <s:stroke>
                <s:SolidColorStroke color="#000000" weight="3" />
            </s:stroke>
        </s:Line>
    </s:Group>
</s:Application>

The above mark-up creates two Groups: one containing the CartesianChart and instructions, and the other the Image and Line. This is remarkably similar to the mark-up of Colin’s Silverlight examples, if slightly more verbose. The verboseness is the result of both Flex technicalities and my overriding the rather ugly default styles axis styles for aesthetic reasons. Note that the CartesianChart was used rather than LineChart purely because of the LineChart using the ugly ShadowLineRenderer by default for LineSeries (the CartesianChart uses the simple LineRenderer).

Unlike in Silverlight, there is no need to do anything funky with mouse event handling Flex, as the Flex component lifecycle means the UI will always have a chance to render. This means a simple mouse move event handler can be used to construct the chart’s data:

private function imageMouseMoveHandler(event:MouseEvent):void
{
	if (!_mouseDown)
		return;
 
	line.xTo = event.localX;
	line.yTo = event.localY;
 
	// compute length of line
	var length:int = Math.sqrt(Math.pow(line.xFrom - line.xTo, 2) +
				   Math.pow(line.yFrom - line.yTo, 2));
 
	// build the chart data
	var bitmapData:BitmapData = Bitmap(image.content).bitmapData;
	var chartData:Array = [];
	var xIndex:int;
	var yIndex:int;
	var pixel:uint;
	var point:Object;
	for (var i:int = 0; i < length; i++)
	{
		point= {};
		xIndex = line.xFrom + (line.xTo - line.xFrom) * i / length;
		yIndex = line.yFrom + (line.yTo - line.yFrom) * i / length;
		pixel = bitmapData.getPixel(xIndex, yIndex);
		point.red = pixel & 0xff;
		pixel >>= 8;
		point.green = pixel & 0xff;
		pixel >>= 8;
		point.blue = pixel & 0xff;
		chartData.push(value);
	}
 
	chart.dataProvider = chartData;
}

Once again, this code is very similar to that used in the Silverlight examples to construct chart data. However, notice that here we can choose to take advantage of ActionScript 3′s dynamic objects to drive our chart for simplicity’s sake. Furthermore, there has also been no need to pre-process the image data to obtain pixel information since the Image, Bitmap and BitmapData classes are designed and optimised for exactly this kind of pixel-level manipulation.

Conclusions

From the above examples it is apparent that there is little, if anything, to differentiate their relative performance. Furthermore, it would be fair to say that the outright technology choice of Flash/Flex or Silverlight has not differentiated these examples. Rather, the choice of charting library in either technology is far more significant with respect to performance. Therefore, in this case, the technology choice would have to be driven by some other factor than performance, for example, plug-in penetration, cost or existing developer expertise.

However, at a more technical level there are some interesting points to consider alongside the comparative performance of the two applications. The Silverlight examples were created with specific techniques for improving their performance. The implication is that a naive Silverlight implementation of the application is likely to have noticeable performance issues. In contrast, the Flex example has purposefully been created without any of the known performance improvement techniques, yet is still as responsive.

It is also worthwhile contrasting the respective charting libraries. The Visiblox charting library has specifically been designed for performance over flexibility, where as the Flex charting library is the opposite. The result is that although they are roughly equal in performance, the Flex charting library has many more options for customisation and extension than the Visiblox charting library. However, it should be noted that the Flex charting library is relatively mature (~4 years old) compared to the Visiblox charts (~2 months old).

You can download the full source code for the Flex example given in this blog post here: FlexChartPerformance.zip; and the full source code for the Silverlight examples given in Colin’s blog post here: ChartPerformance.zip

Logging to Server from Flex

August 6th, 2010

An issue that can crop up with Flex applications is the lack of any log information to match up against users’ bug reports. It is possible to configure the debug version of Flash Player to record trace() output, but most users do not have this setup. Additionally, it is much more desirable to maintain this kind of information server-side, where the development team have control, rather than relying on users’ whilst also clogging up their machines. A general approach to this problem is relatively obvious – send the information back to the server – but there are all sorts of ways this could be implemented. Of course, sending lots of logging information to the server creates an overhead in the application, so this should very much be considered on a case by case basis.

A solution that we use takes advantage of Flex’s native logging API, allowing it to be transparently added or removed from an application while providing us with the benefits of a decent logging framework, for example logging levels. Flex provides the ILogger class, instances of which are obtained using Log‘s getLogger() method, to log messages. In turn, these messages are sent to one or more ILoggingTargets, the most common of which, TraceTarget outputs the logging information using the trace() method. The logging API documentation provides details and examples for how to get started with this basic logging setup.

On the Flex side, our solution consists of little more than a custom ILoggingTarget implementation, RemoteTarget, that attempts to send the logging information to a specified URL and the appropriate code to initialise the target. Note that RemoteTarget uses URLLoaders rather than HTTPServices because HTTPService itself uses the logging API, thereby causing an infinite loop. Another feature worth highlighting is that our implementation stops logging if it has encounters any errors when sending the information to the server, so that, for example, an application does not repeatedly hit a server that is unavailable. All source code and examples associated with this article can be found here.

package com.scottlogic.logging
{
    import flash.events.IOErrorEvent;
    import flash.events.SecurityErrorEvent;
    import flash.net.URLLoader;
    import flash.net.URLRequest;
    import flash.net.URLVariables;
 
    import mx.logging.AbstractTarget;
    import mx.logging.ILogger;
    import mx.logging.LogEvent;
    import mx.utils.StringUtil;
 
    /**
     * ILoggingTarget implementation that sends logging details
     * to a remote service.  The following details are sent as
     * request parameters:
     *  - level: the log level as an integer (see LogEventLevel)
     *  - category: the log category
     *  - timestamp: as milliseconds from 1st Jan 1970
     *  - message: the log message
     */
    public class RemoteTarget extends AbstractTarget
    {
        /**
         * Flag to indicate whether remote logging is enabled
         * or not.  The RemoteTarget will automatically disable
         * itself if it encounters any errors.
         */
        private var enabled:Boolean = true;
 
        /**
         * Constructor
         */
        public function RemoteTarget()
        {
            super();
        }
 
        private var _url:String;
        /**
         * The URL of the service to which to log.
         */
        public function get url():String
        {
            return _url;
        }
        /**
         * @private
         */
        public function set url(value:String):void
        {
            _url = value;
        }
 
        /**
         * @private
         */
        override public function logEvent(event:LogEvent):void
        {
            // if there has been any issue with remote logging
            if (!enabled)
                return;
            // if no url is set then do nothing
            if (!_url || StringUtil.trim(_url).length == 0)
                return;
 
            // attempt to log to the server
            try
            {
                var variables:URLVariables = new URLVariables();
                variables.level = event.level;
                variables.category = ILogger(event.target).category;
                variables.timestamp = new Date().time;
                variables.message = event.message;
                var request:URLRequest = new URLRequest(_url);
                request.method = "POST";
                request.data = variables;
                var loader:URLLoader = createLoader();
                loader.load(request);
            }
            catch (e:Error)
            {
                enabled = false;
                trace(e.message);
                trace(e.getStackTrace());
            }
        }
 
        /**
         * Creates a URLLoader with all the appropriate event listeners.
         */
        private function createLoader():URLLoader
        {
            var loader:URLLoader = new URLLoader();
            loader.addEventListener(IOErrorEvent.IO_ERROR,
                                    ioErrorHandler,
                                    false, 0, true);
            loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,
                                    securityErrorHandler,
                                    false, 0, true);
            return loader;
        }
 
        /**
         * Disables the remote logging and traces debug information
         * when there is an IO error during logging to the remote server.
         */
        private function ioErrorHandler(event:IOErrorEvent):void
        {
            enabled = false;
            trace("ERROR - IO error in RemoteTarget");
            trace(event.text);
        }
 
        /**
         * Disables the remote logging and traces debug information
         * when there is a security error during logging to the remote
         * server.
         */
        private function securityErrorHandler(event:SecurityErrorEvent):void
        {
            enabled = false;
            trace("ERROR - Security error in RemoteTarget");
            trace(event.text);
        }
    }
}

Here is a small example showing how RemoteTarget can be used:

<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="horizontal"
    applicationComplete="initialise()"
>
    <mx:Script>
        <![CDATA[
            import com.scottlogic.logging.RemoteTarget;
            import mx.logging.Log;
            import mx.logging.LogEventLevel;
            import mx.logging.ILogger;
 
            private static const LOG:ILogger = Log.getLogger("RemoteLogging");
 
            private function initialise():void
            {
                var target:RemoteTarget = new RemoteTarget();
                target.url = ""; // set logging service URL here
                target.level = LogEventLevel.INFO;
                Log.addTarget(target);
            }
        ]]>
    </mx:Script>
    <mx:Label text="Text:" />
    <mx:TextInput id="input" />
    <mx:Button label="Log Text" click="LOG.info(input.text);" />
</mx:Application>

As the information is being sent back as a standard example server-side code I have included is in Java and consists of a relatively simple HttpServlet that parses the information and mirrors it onto its own logging framework, in this case log4j.

Flex Sparkline

February 8th, 2010

Sparklines are described by their inventor, Edward Tufte, as “data-intense, design-simple, word-sized graphics”. They are an ideal tool for displaying trends for single entries within large data sets, for example, stock prices. As well as the standard miniature line series, Tufte’s original specification introduces a ternary sparkline, a.k.a. win-loss sparkline, where small columns are used to indicate “win” or “loss” and no column to indicate “draw”.

This article is intended to present, and distribute, Flex implementations of sparklines, win-loss sparklines and another common variation, column sparklines. The Flex 3 version of the code and documentation can be obtained from here, while the Flex 4 version can be found here. The following is an example showing some of the variations available:

The Sparkline, TernarySparkline and ColumnSparkline classes are all implemented using core Flex functionality, i.e. there are no dependencies. They all implement IListItemRenderer and IDropInListItemRenderer interfaces, so can readily be used as standalone components or as item renderers in a DataGrid or other list control. Based on the original specification, the Sparkline allows the user to optionally show a normal range, x-axis min and max points and y-axis min and max points. All of these features and the line itself can be styled. Similarly, the TernarySparkline and ColumnSparkline allow the user to specify the “zero” value, and style positive, negative and zero styles independently. A final feature of the sparklines is that they will update automatically based on dataProvider updates, as shown in the following example, which plots a constantly-updating, randomly generated series of numbers:

It is worth noting that there are a number of alternative Flex implementations available. However, they all have further dependencies, potentially making them more heavyweight. For example, Tom Gonzalez and Andrew Trice both present implementations using the Degrafa graphics framework. Because of their use of Degrafa, these implementations inherently allow users to easily use any number of extravagant styling. Although potentially initially appealing, this goes against the good data visualisation practices suggested by experts such as Stephen Few and Tufte himself; “eloquence through simplicity”[ref]. Lucas Pereira and Sherlock Informatics both present implementations using the Flex Data Visualization library. The charts contained in the library are wonderfully feature-rich and flexible. However, this means that they are also rather heavyweight components and, therefore, using a large number of these as item renderers in an application is likely to use a lot of memory and/or make the application non-performant. A final potential alternative are the micro-charts available in the BirdEye visualisation library. Much like the examples using the Flex Data Visualization library, these can be perfect in situations where small numbers of instances are present, but again they introduce features that cause them to be more heavyweight than necessary.

The components are being made available under the GNU General Public License and can be obtained from here (Flex 3) or here (Flex 4). The zips also include some documentation and a pre-compiled swc of components, using the namespace http://www.scottlogic.com/sparkline.

UPDATE 19/04/2011: I have created an updated version of the library that is Flex 4 compatible. This is available here and a short article detailing the migratory changes can be found here.

Missing values in Flex charts

April 14th, 2009

An oddness in default behaviour that can throw those new to Flex Charting is that segments in charts that should correspond to a data point are missing. By this I mean charts like those in the following example:

When what is actually desired is the following:

This is achieved by setting the filterData property on the Series to false, for example:

<mx:LineSeries filterData="false" />

However, it is worth understanding the functionality that ties in with this property to appreciate the potential consequences. Adobe states:

When possible, set the filterData property to false. In the transformation from data to screen coordinates, the various series types filter the incoming data to remove any missing values that are outside the range of the chart; missing values would render incorrectly if drawn to the screen. For example, a chart that represents vacation time for each week in 2003 might not have a value for the July fourth weekend because the company was closed. If you know your data model will not have any missing values at run time, or values that fall outside the chart’s data range, you can instruct a series to explicitly skip the filtering step by setting its filterData property to false. [ref]

What is actually happening under the covers is that the series a collection of “all the data points” and a collection of “all the data points I think I want to draw”. When filterData is true, i.e. by default, the series creates the collection of “all the data points I think I want to draw” by iterating through the collection of “all the data points” and throwing away any that are null or NaN or that fall outside the axes minimum and maximum values. By contrast, when filterData is false, the two collections are identical. Knowing this it is obvious why the segments are missing in the example above: with the LineSeries if a data point is not to be drawn then the line segments to that data point will not be drawn; with the ColumnSeries if a data point is not to be drawn then the column representing that data point will not be drawn.

Performance-wise, it is worth noting that performance gained by the removal of data point filtering step by setting the filterData property to false will be offset against the performance lost by drawing data points that have no bearing on the view of the chart, i.e. data points that are one or two data points removed from those around the axes maximums. As such, the performance gain/loss and appearance gain/loss should be considered on a case by case basis.

An approach that can be used to get the best of both worlds is to extend the applicable series class and override the updateFilter method to ensure that data points that have no bearing on the view of the chart are filtered out, but any others aren’t. This could, for example, amount to filtering out any data points that do not lie in the range of the x-axis and that are not adjacent in the x-axis to a data point that does lie in the range of the x-axis.

An unfortunate note about the filterData property is that there is a bug when setting it to false on a LineSeries no data tips will show on the series (as can be seen in the example above). The bug has been filed with Adobe and has recently been marked fixed, however, the fix has not yet been released. The bug report details the relatively simple but somewhat nasty workaround that can be used in the meantime.

At Scott Logic the functionality relating to the filterData property as well as the property itself have been carefully manipulated to produce the various zooming and panning capabilities in our Hindsight application and the research charts available through our Market Overview pages.

The source code is now available.

Custom data tips in stacked Flex charts

March 24th, 2009

The number of frustrating decisions in Flex’s charting API is minimal, but high up on my list is a strange decision that prevents developers from accessing information that is frequently desirable for custom data tips in stacked area, bar and column charts. The default data tips for stacked charts display, amongst other things, the total of the values for all the series at a specific point along the x-axis and the percentage the highlighted segment forms of this total, as shown in the following example (source code):

If you wanted to customise the data tips and still include information such as the total and percentage values then you would be out of luck. This why I consider the decision to give the necessary information protected scope in the relevant classes in the charting API as strange. Fortunately circumnavigating this issue only requires a little bit of dirty work…

But first, a brief diversion to provide a little background…
The code used to create a stacked column chart generally takes the following form:

<mx:ColumnChart type="stacked">
    <mx:series>
        <mx:ColumnSeries />
        ...
    </mx:series>
</mx:ColumnChart>

This is in fact a shortcut syntax. The ColumnChart automatically wraps the array of series into a ColumnSet with type “stacked”, as it is the ColumnSet class that takes care of the stacking and associated behaviour rather than the ColumnChart class. The same pattern occurs in stacked AreaChart or BarChart. Consequently, the following MXML produces the same end result:

<mx:ColumnChart>
    <mx:series>
        <mx:ColumnSet type="stacked">
            <mx:ColumnSeries />
            ...
        </mx:ColumnSet>
    </mx:series>
</mx:ColumnChart>

When wanting to create more complex combinations of stacking, clustering and overlaying in charts, this can only be achieved by explicitly introducing (and nesting) sets – as in the second code snippet. For further details on this see Adobe’s Stacking Charts article.
Diversion over…

To be able to display customised data tips that include information relating to the stacking in a stacked ColumnChart, BarChart or AreaChart we can take one of two approaches. Both approaches involve extending the ColumnSet, BarSet or AreaSet class (depending on the desired chart type) as it is the protected-scoped negTotalsByPrimaryAxis, posTotalsByPrimaryAxis, stackedMaximum and stackedMinimum properties that contain the interesting information. The first approach is to override the formatDataTip method in the extended class, resulting in something along the following lines:

/**
 * ColumnSet extension to introduce custom data tips.
 */
public class ColumnSet extends mx.charts.series.ColumnSet
{
    /**
     * @inheritDoc
     */
    override protected function formatDataTip(hd:HitData):String
    {
        // build up the custom data tip
        var tip:String = "";
        ...
        return tip;
    }
}

However, I think that this approach is slightly short-sighted because it means that for every customisation of the data tips you would create a new extension. The other, and in my opinion more reusable, approach is to expose the aforementioned properties publicly in extensions to the ColumnSet, BarSet and AreaSet classes. By creating these extensions, the standard approach to customising data tips can be used, i.e. a method with the appropriate signature is passed to the chart’s dataTipFunction property. The classes resulting from this approach would be something along the following lines:

/**
 * ColumnSet extension to expose the stack totals for public 
 * use, e.g. in a data tip function.
 */
public class ColumnSet extends mx.charts.series.ColumnSet
{        
    /**
     * @see StackedSeries.posTotalsByPrimaryAxis
     */
    public function get positiveTotalsByAxis():Dictionary
    {
        return posTotalsByPrimaryAxis;
    }
 
    ...
}

The minor downside to this approach is that the shortcut syntax for achieving stacked series, as used in the first example and explained above, cannot be used. The explicit syntax must be used to ensure that the extended version of the relevant StackedSeries extension is used.

The following example uses the approach presented above to provide customised data tips in the chart. The source code for the example includes the necessary extensions to the ColumnSet, BarSet and AreaSet classes, so feel free to use them.