Tom Sugden: Frameworks Archives

February 9, 2010

The Flexible Configuration Options of Parsley

One of the nice design decisions taken by Jens Halm when he created the Parsley Application Framework was to separate the configuration mechanism from the core of the framework, so different forms of configuration can be used as required. This idea in itself is not new, since Martin Fowler advocated it in his 2004 paper, "Inversion of Control Containers and the Dependency Injection pattern":

"My advice here is to always provide a way to do all configuration easily with a programmatic interface, and then treat a separate configuration file as an optional feature. You can easily build configuration file handling to use the programmatic interface. If you are writing a component you then leave it up to your user whether to use the programmatic interface, your configuration file format, or to write their own custom configuration file format and tie it into the programmatic interface" - Martin Fowler

The application of this design principle is particularly effective in Parsley. While some frameworks are restricted to specific configuration mechanisms, Parsley provides programmatic interfaces for synchronous and asynchronous configuration, and several out-of-the-box implementations. These interfaces provide an extension-point so developers can plug-in their own configuration processors when the need arises.

Configuration Processors

In Parsley, a configuration processor uses some form of configuration data to build up a registry of object definitions. This process is abstracted by the following interfaces:

Parsley has a number of standard implementations, including the following two most commonly used:

The developer manual has a section explaining how to extend the framework with a new configuration processor:

Example: Modular Configuation Processor

There are various reasons to write a custom configuration processor. Perhaps you want to support your own particular configuration files, loaded and processed at runtime. However, these interfaces open up some other doors for more interesting forms of configuration. For example, they can be used to process configuration data from a compiled module.

Consider a large, modular application. Let's say the application consists of a Flex shell application that loads 20 modules, and 10 of these rely on the same set of shared services. It's undesirable to compile these services into the shell application, where they could be inherited by the modules, since the shell should have no knowledge of these lower level details. Instead they could be compiled into a module and the shell application could load that module at start-up, so the services are available for inheritance, but there is no dependency imposed on the shell.

This can be achieved quite simply by writing a new configuration processor, something like this:

package com.adobe
{
     import flash.events.ErrorEvent;
     import flash.events.Event;
     import flash.events.EventDispatcher;

     import mx.events.ModuleEvent;
     import mx.modules.IModuleInfo;
     import mx.modules.ModuleManager;
     import mx.utils.StringUtil;

     import org.spicefactory.parsley.core.builder.AsyncConfigurationProcessor;
     import org.spicefactory.parsley.core.builder.ConfigurationProcessor;
     import org.spicefactory.parsley.core.registry.ObjectDefinitionRegistry;

     public class ModularConfigurationProcessor 
          extends EventDispatcher 
          implements AsyncConfigurationProcessor
     {
          private static const MODULE_LOADING_ERROR : String = 
               "Unable to load the module at URL {0} due to {1}";
          private static const MODULE_INCOMPATIBLE_ERROR : String = 
               "The module doesn't implement the ConfigurationProcessor interface.";

          private var url : String;
          private var module : IModuleInfo;
          private var registry : ObjectDefinitionRegistry;

          public function ModularConfigurationProcessor( url : String )
          {
               this.url = url;
          }

          public function cancel() : void
          {
               module.removeEventListener( ModuleEvent.READY, moduleReadyHandler );
               module.removeEventListener( ModuleEvent.ERROR, moduleErrorHandler );
          }

          public function processConfiguration(
               registry : ObjectDefinitionRegistry ) : void
          {
               this.registry = registry;
               module = ModuleManager.getModule( url );
               module.addEventListener( ModuleEvent.READY, moduleReadyHandler );
               module.addEventListener( ModuleEvent.ERROR, moduleErrorHandler );
               module.load( registry.domain );
          }

          private function moduleReadyHandler( event : ModuleEvent ) : void
          {
               try
               {
                    processConfigurationWithModule();
                    dispatchEvent( new Event( Event.COMPLETE ) );
               }
               catch ( e : Error )
               {
                    dispatchErrorEvent( e.message );
               }

          }

          private function processConfigurationWithModule() : void
          {
               var instance : Object = module.factory.create();

               if ( instance is ConfigurationProcessor )
               {
                    ConfigurationProcessor( instance ).processConfiguration( registry );
               }
               else
               {
                    throw new Error( MODULE_INCOMPATIBLE_ERROR );
               }
          }

          private function moduleErrorHandler( event : ModuleEvent ) : void
          {
               dispatchErrorEvent( MODULE_LOADING_ERROR, url, event.errorText );
          }

          private function dispatchErrorEvent( message : String, ... rest ) : void
          {
               dispatchEvent( new ErrorEvent(
                    ErrorEvent.ERROR,
                    false,
                    false,
                    StringUtil.substitute( message, rest ) );
          }
     }
}

The processor is initialized with the module URL. It loads the module, creates an instance, then checks whether the module itself is a configuration processor. If so, it delegates configuration processing to the module. Here's an example module:

package com.adobe
{
    import mx.modules.ModuleBase;

    import org.spicefactory.parsley.asconfig.processor.ActionScriptConfigurationProcessor;
    import org.spicefactory.parsley.core.builder.ConfigurationProcessor;
    import org.spicefactory.parsley.core.registry.ObjectDefinitionRegistry;

    public class MyModule extends ModuleBase implements ConfigurationProcessor
    {
        public function processConfiguration(
            registry : ObjectDefinitionRegistry ) : void
        {
            new ActionScriptConfigurationProcessor(
                [ MyModuleConfiguration ] ).processConfiguration( registry );
        }
    }
}

Parsley's extension points can be taken a little further by writing a complementary configuration tag:

package com.adobe
{
    public class ModularConfig implements ContextBuilderProcessor 
    {
        public var url : String;

        public function processBuilder( builder : CompositeContextBuilder ) : void 
        {
            builder.addProcessor(
                new ModularConfigurationProcessor( url ) );
        }
    }
}

So now a modular configuration can be easily combined with other forms of Parsley configuration using the usual MXML tags:

<mx:Application ... xmlns:sf="http://www.spicefactory.org/parsley">

    <sf:ContextBuilder>
        <sf:FlexConfig type="{ MyShellApplicationConfig }"/>
        <adobe:ModularConfig url="MyModularConfig.swf"/>
        <adobe:ModularConfig url="MyOtherModularConfig.swf"/>
    </sfConfigBuilder>

    ...

</mx:Application>

Here the shell application configuration will be combined with the configuration from two modules to form a Parsley context that can be inherited by other modules, loaded later on-demand.

Conclusion

When creating a framework, it is wise to define generic interfaces for configuration processing, so that different formats can be used where appropriate. In many cases programmatic configuration with MXML is the simplest and most desirable option, but there are several valid cases for configuration from XML and other kinds of file (including SWFs) loaded at runtime. The configuration interfaces provided by Parsley satisfy this requirement very well.

Posted by tsugden at 10:25 PM | Comments (0)

November 23, 2009

Modularity in Flex Applications

There has been talk recently about the trend towards inversion-of-control frameworks in Flex. In addition to this, a higher-level movement can be seen towards modularity frameworks. Such an approach to architecture can bring many benefits, particularly in enterprise settings with larger teams and formal release processes. This post explains what modularity means in the context of Flex and discusses some of the benefits and options available for implementation.

What is Modularity?

Modularity is something more general than the Flex Module and ModuleLoader components. These are a form of modularity, but the principle is broader: modularity is about separating applications into smaller units that can be developed and deployed independently. In the context of Flex, these units might be modules, sub-applications or any other kind of encapsulated content. A modular application usually has a structure like that shown in Figure 1.

Modularity Figure.002.png

Figure 1 — The structure of a modular application

In the figure above, the application consists of a thin shell that loads three modules: Dashboard, Contacts and Messages. These modules represent different functional areas of the application. Their implementation detail is independent of one another. The application shell is responsible for loading and laying out the modules, and providing a means of communication between them. This might be a global data model, a registry of interfaces, or in the case of Figure 1, some kind of message bus.

What are the Benefits of Modularization?

Modularization can bring benefits for end-users of an application and also for the teams that develop and deliver them; Here are some of the benefits:

  • A module can be developed, tested and profiled in relative isolation.
  • Build times are shortened, since changes to one module don't require other modules or the shell application to be recompiled.
  • Modules can be loaded on demand, so the initial download for an application is smaller.
  • If a user never uses the features of one module, that module need not be loaded.
  • Individual modules can be deployed into production, instead of redeploying an entire application.
  • Different modules can be loaded for different users based on their entitlements.
  • A module is easier to understand and maintain than a monolithic application, since it is more functionally cohesion.
  • The interactions between modules can be confined to a thin API, reducing regression as an application grows.

The benefits in terms of architecture and development efficiency are arguably the most important. Small groups of developers can work on individual modules. The contracts of communication between modules can be agreed, so the implementation is free to change and improve without regression.

Framework Provisions for Modularization

Some frameworks have features to help with building modular applications. PureMVC was probably the first to do so with the multi-core version of the framework and its Pipes utility for controlled flow of messages between modules. The Parsley application framework is also designed to support modular applications, in which a module would normally have its own inversion-of-control context that inherits object definitions from the context of a shell application. Parsley includes a messaging framework that can be used for loosely-coupled communication between modules.

The other frameworks are hot on their heels. Spring Actionscript will have modular support as of version 0.9, where each module can have its own context with the option to inherit the object definitions of its parent. A parent context will be able to control which object definitions are exposed to a child context. And the lightweight Swiz framework is going to improve its support for modular development in the near future with its 1.0 release.

In addition to these established frameworks, there are some emerging frameworks focussed more specifically on modularity. Potomac and Adobe Gravity are two new frameworks inspired by OSGi, the dynamic module system for Java. Both aim to provide the infrastructure for loading bundles (i.e. modules) at runtime and communicating between them through service interfaces. Adobe Gravity remains an Adobe internal project but there are plans for a future open-source release, while Potomac is publicly available and includes some developer tooling in the form of a Flash Builder plug-in.

Cairngorm 3 and Modularization

One of the key messages of the Cairngorm 3 reference architecture (currently in draft) is to separate applications into distinct functional areas that can be developed independently; in other words a modular architecture, where each functional area is a module. The Cairngorm guidelines recommend that communication between functional areas takes place through a thin API that might consist of interfaces, events and data transfer objects. This approach minimizes dependencies between the distinct functional areas of an application. It promotes what Robert Martin terms "good dependencies" in the direction of stability. More details can be found in the Creating Functional Areas draft document.

The Enterprise Solution: Adobe LiveCycle Mosaic ES2

LiveCycle Mosaic ES2 is far more than a modularity framework, but modularity is an important part of its design. It's a client-and-server-side technology for building applications by composition, combining different pieces into personalized views that are focussed on the activities that different users perform. On the server-side, reusable application assets can be stored and shared, while LiveCycle DataServices is available for integrating with different data sources. On the client-side, applications are assembled from different tiles, that can be developed from scratch or adapted from existing Flex and HTML applications. A customizable shell application loads and lays out the tiles, and the framework provides a publish-subscribe messaging API for communication between them. For more details about the Adobe enterprise solution to modularity, refer to the LiveCycle Mosaic ES2 product page.

Conclusion

As we attempt to build bigger and better applications in Flex and AIR, the topic of modularity becomes more important to ensure efficient development, scalability and maintainability. It is vital to be able to separate portions of a large application so they can be developed, tested and deployed independently. The Flex SDK provides some simple means of modularization with Modules and Sub-Applications, and some frameworks build on top of these to provide more features. Furthermore, Adobe has now released an enterprise solution in LiveCycle Mosaic ES2 that provides the infrastructure for rapidly developing and deploying RIAs to the browser and desktop in a modular way.

Posted by tsugden at 10:32 PM | Comments (0)

September 13, 2009

Coming Soon: Cairngorm 3

Cairngorm is about to undergo a transformation that will broaden its scope and increase its value to clients and partners. Instead of centering around a specific implementation of the Model-View-Controller pattern, Cairngorm 3 will consist of a set of best practices, tools and libraries, many of which apply across frameworks. This is the knowledge gathered by the Adobe Technical Services organization and partners over the last five or six years, condensed and presented to help others to deliver successful Flex projects in the enterprise.

For those familiar with the Cairngorm 1 & 2 micro-architecture, the traditional Cairngorm library remains a part of Cairngorm 3. Our best practices for applying the Cairngorm library will be shared, together with information about tried-and-tested extensions. And like before, Cairngorm 3 will recommend a layered architecture that separates concerns and supports test-driven development, but this time the approach has been refined and most parts of it complement multiple frameworks.

So what is Cairngorm now if it isn’t just a framework? Well it’s a foundation for delivering successful Flex projects. It’s the answer to the question, “What are the best practices for Flex in the enterprise?”, to help set new teams off on the right track. It’s the information that can’t always be found in official documentation or framework manuals. It's going to be accessible, informative and open-source. And it’s coming soon...

Posted by tsugden at 8:57 PM | Comments (6)

August 24, 2009

Applying the Presentation Model in Flex

Introduction

The purpose of the Presentation Model design pattern is simple to grasp: it’s a way of moving state and logic out of a view component and into another class, where it can be developed, comprehended and unit tested more easily. The pattern promotes a clean separation of concerns, helping to keep MXML views as structural definitions, free from Script-block logic. However, there are several ways to apply presentation models in Flex. Some of these can help us to build simpler, more testable systems, while others may lead towards entanglement and maintenance difficulties.

For a comprehensive introduction to the Presentation Model pattern and a comparison between it and other presentation patterns, please refer to Paul Williams' blog series on the topic. At Adobe Professional Services, we have found the Presentation Model to be well suited to Flex, since it takes advantage of language features like bindings and in-line event handlers, while side-stepping some of the difficulties of unit testing display objects.

This article discusses two approaches to applying the Presentation Model -- hierarchical and componentized -- and makes a recommendation in favour of the latter.

Two Approaches: Hierarchical or Componentized

Hierarchical

With the hierarchical approach to the Presentation Model (PM) pattern, a hierarchy of PMs is developed that reflects the hierarchy of view components, as shown in the Figure 1.

PM1.png

Figure 1 - A hierarchy of views and presentation models.

Each MXML view component has a corresponding PM. The parent view contains the child views, and likewise, the parent PM contains the child PMs. Below these View-to-PM pairs, there are only basic UI controls, implemented in ActionScript without corresponding PMs.

With this approach, the top-level PM is usually instantiated in the top level view. It may be a singleton to allow other parts of the application, such as commands to access it as required. The child PMs are then passed down manually into the child views, as shown below:

<example:MyComponent ... >
<mx:Script>
[Bindable] public var model:MyComponentPM;
</mx:Script>
<example:MyChildComponent model="{ model.myChildComponentPM }" ... />
...
</example:MyComponent/>

When a hierarchy of presentation models is established, coordination takes place by method calls between the PMs, sharing objects amongst them, and dispatching events up the hierarchy. So if a user selects an item from a DataGrid in View 2, a selectedItem property may be updated on PM 2 and an event dispatched to announce the selection. PM 1 may listen to this event and perform its own logic in response.

Componentized

With the componentized approach to the Presentation Model pattern, there is a single hierarchy of view components but no hierarchy of presentation models. Each view component has a corresponding presentation model, but these models are independent of one another, as shown in Figure 2.

PM3.png

Figure 2 - A hierarchy of components, each with a presentation model

With this approach, the PMs are usually injected into their corresponding views using the view-wiring mechanism of an IoC framework. For example, the following code could be used with Parsley 2:

<example:MyComponent ... 
   addedToStage="dispatchEvent(new Event('configureIOC', true'))">
<mx:Script>
[Inject] [Bindable] public var model:MyComponentPM;
</mx:Script>
<example:MyChildComponent/>
...
</example:MyComponent/>

Here the configureIOC event instructs Parsley to inject a presentation model instance, declared in a configuration file, into the model property of the view. Notice that there is no need to pass a model into the child component. Each component is self-contained and takes care of its own business.

A variation of this approach is to declare the presentation model directly in the view, as shown below:

<example:MyComponent ... >
<example:MyComponentPM id="model"/>
<MyChildComponent/>
...
</example:MyComponent/>

Although the presentation models are kept independent of one another with the componentized approach, there remains a need to coordinate the components in some way. This can best be achieved using an Inversion-of-Control (IoC) framework, such as Parsley, Swiz or Spring ActionScript. There are ways to do so:

  • Messaging - route messages directly between the models using whatever mechanism your preferred framework provides. Parsley 2 includes a loosely-coupled messaging framework; Swiz has a notion of mediated events; while Cairngorm MVC has a singleton event dispatcher that can serve a similar purpose.
  • Domain Interfaces - inject shared domain models into multiple PMs. Coordination then takes place when the PMs call methods on the interfaces to these models, and listen for events dispatched by them. All IoC frameworks support this feature.
  • Controller/Presenter - use separate classes, known as controllers or presenters, to coordinate multiple PMs. These classes are typically injected with a number of presentation models, using an IoC framework. The controllers then listen for events and invoke methods on the PMs.

The relative merits of these are not discussed here, but will be tackled in another article. Each approach achieves a similar result of de-coupling the components from one another. The two approaches to the Presentation Model pattern are now compared in terms of their responsiveness to change.

Responsiveness to Change

It is common for the visual designs of a user interface to change during development, based on user feedback, client demands, or moments of creative inspiration from the designers. In my experience, this usually happens when I've just put the finishing touches on the implementation, the pixels are perfectly aligned and the unit tests running green! So it's important to write code in such a way as to minimize the cost of change, allowing components to be manoeuvred from place to place and logic to be reused without great effort.

Consider the case where a view component needs to move from one region of the user interface to another. Starting with the simple hierarchy shown earlier in Figure 1, changes are required to four classes, now highlighted in red in Figure 3.

PM2.png

Figure 3 - Moving part of a View-and-PM hierarchy


View 3 needs to be detached from its starting place in View 1 and re-declared in View 2. Similarly, the reference to PM 3 contained in PM 1 needs be removed and introduced to PM 2. Any coordination logic that was in PM 1 also needs to be moved into PM 2.

In contrast, the componentized approach, first shown in Figure 2, responds more easily to change. Only the declaration of View 3 needs to be moved from View 1 to View 2, as highlighted in red in Figure 4.

PM4.png

Figure 4 - Moving a component within a hierarchy

Since the logic for the View-to-PM components is self-contained and coordination takes place externally, though messaging, domain interfaces, or controller/presenters, no further changes are necessary. If test-driven development is being practiced, the unit tests for the PMs also remain intact, whereas they would need to be refactored with the hierarchical approach.

Conclusion

The Presentation Model is a useful pattern for building testable Flex applications. By moving the state and logic used to present data and handle user gestures into PMs, it can be unit tested in isolation and understood more easily than Script-block logic placed directly within views. However, rich user interfaces can be somewhat volatile, changing their shape often during development, so it is recommended to apply a componentized version of the Presentation Model that is easy to adapt, rather than developing and ultimately maintaining a hierarchy of connected presentation models.

Posted by tsugden at 9:32 PM | Comments (6)

July 6, 2009

The Trend Towards Inversion-of-Control Frameworks in Flex

Last year I wrote three chapters about the Cairngorm MVC framework for a new Flex book, Professional Flex 3, published by Wrox Press. Cairngorm has been widely adopted on enterprise projects, so it was important to explain its workings and cover the best practices and common pitfalls. If you’re a developer who moves between clients and projects, this is important knowledge to have. However, with more time and pages, I’d have liked to devote similar attention to the other Flex frameworks now available.

Over the last few years, the Flex framework space has become well served with alternatives to Cairngorm, each offering their own take on the challenges of RIA development. While Cairngorm is rooted in design patterns from the Java enterprise world, some of the newer framework creators have taken a fresh approach, reflecting on the language features and special capabilities of ActionScript and the Flex SDK, then building from the ground up, taking advantage of features like event bubbling, declarative MXML and metadata.

Inversion-of-Control

In these new frameworks, there has been a trend towards the inversion-of-control (IoC) or dependency-injection pattern. There is a good reason for this, since this approach decouples the objects of an application, so they can change independently of one another and be tested in isolation. Applying IoC can make it easier to restructure a user interface, substitute the service integration layer, and refactor the models containing the logic and state of your application, amongst other benefits.

For those new to the concept, IoC means passing (or injecting) the dependencies for a class into that class, instead of creating the dependent objects within. The behavior of a class can then be controlled by passing in different types of objects; an inversion of the traditional approach. When interfaces are extracted from these dependencies, the technique becomes more powerful, because the class is decoupled from any concrete classes. The interfaces can be implemented in different ways to achieve different outcomes and can be substituted for testing purposes.

An example of this design is found in the Tree component of the Flex SDK. The Tree uses the ITreeDataDescriptor interface to determine whether the items in its data provider are branch or leaf nodes.

public interface ITreeDataDescriptor
{
    ...
    isBranch(node:Object, model:Object = null):Boolean
    ...
}

This interface decouples the Tree from the actual type of objects inside the data provider. By substituting different implementations of ITreeDataDescriptor, it can be made to render all kinds of objects in tree form. This inversion of control makes the Tree a more flexible component than it would be if a single data descriptor of fixed type was created internally.

Inversion-of-Control Frameworks in Flex

A number of IoC-based frameworks have emerged for Flex to support the development of loosely-coupled applications. They typically provide a way to configure the main objects used by the application (models, services, etc.) and to specify the dependencies between them. These frameworks are sometimes known as IoC containers, where the container is the part of the framework responsible for instantiating objects and setting-up (or wiring) the dependencies. In some cases, the container assumes further responsibilities, such as managing the life-cycle of the objects (calling initialization and disposal methods) or routing messages from one object to another.

To give a potted history, two of the earlier arrivals were Prana and Parsley, both of which were inspired by the popular Spring framework from the Java world. They used XML files for configuration and singletons for extracting pre-configured objects from the containers into Flex views. The generation that followed, including Swiz and the lesser-known Flicc, were lighter weight and took more advantage of features of Flex. Swiz took the most radically simple approach, defining objects (or beans) directly in MXML and injecting them automatically into views wherever a special metadata tag was placed, while Flicc provided a novel set of MXML tags for object definition, event handling and view injection.

Since then all of these frameworks have been evolving. Prana has become Spring ActionScript, an extension of the official Spring Platform, while Parsley picked up some tricks from Swiz and Flicc and broadened its feature set to include messaging, module integration and extensibility points. Swiz too has gained new capabilities while remaining distinctly lightweight, like prototype object instantiation (a.k.a. non-singletons) and more flexible event mediation with bubbling events and metadata. A more detailed comparison of these frameworks together with sample applications is due to be published soon on Adobe Devnet in an article written by my colleague, Ed Eustace (link will be added after publication).

Conclusion

The frameworks space is in good shape for Flex. Established MVC frameworks like Cairngorm and Pure MVC, that prescribe certain design patterns and structures, have been complemented by a slew of new frameworks1 centered around inversion-of-control. When applied correctly, these enable developers to write more loosely-coupled software that can be changed and tested more easily.

However, inversion-of-control is a very general approach that can be applied in different ways. Questions remain about the best way to use it for building Flex applications. For advanced developers, the freedom afforded by these new frameworks is a benefit, since their experience enables them to make wise judgements about how to structure the layers of an application (view, model, control, integration, etc). For less experienced developers, however, the pattern alone provides little guidance and mistakes can easily be made. Since software project teams tend to consist of multiple developers with different levels of experience, it is important to establish guidelines around the use of an IoC framework for a team to deliver efficiently.

The variety of approaches and competition between frameworks is in the interests of Flex developers and end users. It’s giving us better solutions to the recurring problems of RIA development, allowing us to focus on what is special and distinct about our projects, rather than the basic plumbing. There are some opportunities for consolidation and there's no one-size-fits-all solution at present, so technical architects need to evaluate carefully and choose the best framework for a particular situation, given the technical considerations and also the makeup of the team.

Progress looks to be steady with the current selection of frameworks, but perhaps new capabilities are needed for Flash Player and the Flex SDK to enable the next major leap forward?

1 The Mate Flex Framework and probably others have been unfairly overlooked in this blog post. Although not positioned as an inversion-of-control container, Mate does provide a means of dependency injection together with a neat set of declarative MXML tags to structure and coordinate a Flex application.

Coming Up

In a future post, I’ll write in more detail about Parsley 2, the second version of the Parsley Application Framework. Parsley has arguably the richest feature set of the current generation of frameworks, yet it also has a simple elegance. The blog post will focus on two of the features that currently distinguish it: module integration and loosely-coupled messaging.

Posted by tsugden at 8:35 AM | Comments (0)