Wednesday, June 16, 2010

Flex Cairngorm architecture


Cairngorm is an implementation of several design patterns that form a lightweight architectural framework. Design patterns offer specific solutions for specific problems and when a collection of patterns regularly collaborate with one other, their assembly is for the greater good of a greater aim. You call this collection into a higher order a microarchitecture. In general, it offers developers a starting point for some technical architecture that is generic enough to apply in most cases to complex applications.

Cairngorm architectural framework

Cairngorm follows the principle of seperating the view and business logic which is known as the Model-View-Controller pattern (MVC). The following list shows the different elements that form the framework. Also check out the Cairngorm diagram for a graphical overview of the components.

  • View – The main.mxml document and its corresponding components are the basis of the view. It contains UI controls for user interaction and displays the state of the models data. Views dispatch events handled by the controller.
  • Model Locator – It acts as a centralized repository for all data needed in the application. It manages the view an is declared as [Bindable] to use all variables for data binding in the view. It must be implemented as a singleton which implements the Cairngorm IModelLocator. All data managed in the model should only be updated through a command or a responder object-

  • Value Object – A value object is a class that only has properties to store values. It contains no methods or logic an acts as a pure data container. Value objects must implement the Cairngorm ValueObject interface. If they should be mapped to a corresponding server-side class it must declare the [RemoteClass (alias='')] metatag. By doing so, Flex automatically converts an server-side object returned through remoting or data service interaction to its corresponding ActionScript object.

  • Event – In Cairngorm everything should be mapped to an event. Whenever the user interacts with the view or an action occurs an event must be dispatched. Custom events extend the CairngormEvent class an have a special property to contain the data that comes with it.
  • Command – Commands actually do the majority of an applications work. They recieve the event and its data, execute the logic an can change the workflow state of the model and view. Each command must implement the Cairngorm ICommand interface and its execute function. The revcieved event is a generic CairngormEvent and must be casted to the appropriate custom event first. The complete frontend-logic of the RIA is encapsulated within the commands.
  • Front Controller – It extends the Cairngorm FrontController class and maps the dispatched events to its corresponding commands. Therefore it has two methods: the constructor and an initialize method which will map an event to an command via the addCommand method. The controller is instantiated directly in the main.mxml via a component tag. You simply need to add the directory your class is in as an XML Namespace and then include the tag in the file.
  • Service Locator – Implemented as a singleton, it contains references to all services an application will use. Like the Front Controller, it is placed within the main.mxml via a tag. Possible services to be used are RemoteObjects, HTTPServices, WebServices or custom services.
  • Business Delegate – Business Delegates form an abstraction layer between the server-side services and the main frontend application. The locate the required service in the Service Locator, call the given method on it and route the response back to a responder object. Unlike the other elemente in the Cairngorm architecture, it does not extend a class or implement an interface, but it need to follow some guidelines: it must have at least two properties, one named reference to the ServiceLocator and one reference to a responder, both set in the constructor. And it must have implemented one method for each server-side method to be called. The delegate is created within a command object. It should only pass strongly typed value objects to a responder. If it does not recieve an appropriate object, it must create one before passing it.
  • Responder – Responders implement the mx.rpc.IResponder interface. A responder recieves the result of a service call and implements frontend-logic like a command. It directly may set values of the model and should only deal with strongly typed value objects.
  • Service – The Service is formed by an application tier, build with some server-side technology like J2EE or PHP. It Accepts the service requests from the RIA and responds back data. With a remoting technology like BlazeDS it is even possible to pass back value objects witch are transformed to their corresponding ActionScript objects in the application, so it can interact with them as if they are created by script.

10 Tips for Flex Application Performance

1) Manage your event listeners - this message is two fold. First, you should always remove event listeners that are no longer needed. They can lead to object references that prevent the garbage collector, which equates to memory leaks, which can be very difficult to track down and detrimental to application performance. You can use weakly referenced event listeners to minimize memory leakage, but you still should explicitly clean them up when you don't need them anymore. The second factor is that failure to remove event listeners can cause performance issues. Event handlers could be firing within your application, which you weren't even aware of. You dispatch an event in a child component, and there could be handlers up the DOM tree (parent objects) that are also firing on the same event. If you don't want this to happen, be explicit with your event handlers; make them handle specific event types, and get rid of them when your application doesn't need them anymore.

2) Unload loaders - any time that you are using an object based on a loader (Image, SWFLoader, etc...), it's a good practice to call unloadAndStop() to unload the content from the loader, and invoke the GC. This will free up valuable system resources and cpu cycles won't be wasted if they aren't needed. I typically even do this for static image files, to prevent memory usage from creeping up.

3) Dispose of things - I find it to be a very good practice to create "dispose()" functions in your custom components, data managers, or views that will clean up the object's resources. The dispose() method will need to be explicitly invoked when you are finished using an object, but that dispose method will handle everything needed to clean up an object and free it's resources. For example, stop timers, remove event listeners, unload loader objects, set variable references to null, etc... Basically, get rid of anything that could possibly cause a memory leak or eat cpu cycles behind the scenes. Yes, it takes cpu cycles to invoke a dispose method, but trust me. It is much easier and much less computationally expensive to explicitly dispose of objects, rather than burn time, computation resources, and budget tracking down leaks and performance issues.

4) Handle collections properly - There are a few things I see all the time, and they're always the first things to change if I see them. Collections (ArrayCollection, XMLListCollection, etc...) are helper classes that wrap primitive structures like array or xmllist. In order to help make working with those primitives easier, the collection classes do things that can be computationally expensive if you aren't aware of them. The reason that bindings to collection work is because every time you add, remove, or update an item, events get dispatched. They also get dispatched every time you refresh a collection.

The first tip is to be conscious of collection events. If you loop over a collection and update 100,000 items, 100,000 events will get dispatched. This can cause massive performance implications, and can completely lock your application UI. If you don't need those collection events to be dispatched, you can use the disableAutoUpdate() function to suspend collection events. Just be sure to turn them back on when you are done, or if you need them again, using the enableAutoUpdate() function.

The second, is to not use a collection if you don't have to. If all you need is to do loop over 100,000 items, and you arne't using data bindings, then use an array.

And the third tip on collections is only when collections are filtered using a filter function... If a filter function is applied, you don't need to call the refresh() function every time you add a new object to the collection. This can cause performance hits, in some of the least expected places. For example, if you have a datagrid bound to a collection, and have another process which updates that collection. If there is a filter on the collection, it will automatically get filtered when you call the collection's addItem method. Calling the refresh() method after adding an item will cause the list data of the datagrid to be invalidated, thus causing the entire datagrid to be re-validated and re-drawn. This is easily missed when optimizing, and can make drastic changes in application performance.

5) Use deferred instantiation - By default, all navigational containers within Flex (tab nav, accordion, viewstack, etc...) only create their children as they are needed. This prevents the application from creating thousands of components that aren't needed yet, which helps keep the application running smooth, and without hogging resources or locking up. Changing the creation policy can cause big problems if you are not careful.

You should also keep deferred instantiation in mind when creating your own custom components. Don't create child objects in the constructor. Instead, override the createChildren() method, and create them in there. This way, your components also follow deferred instantiation rules, and they don't introduce any performance issues that can be difficult to track down.

6) Object recycling vs new objects - I've written about this one before, but I'll say it again. It is often less expensive to reuse existing objects, rather than creating new ones. This goes hand-in-hand with data virtualization.

7) Don't invalidate/destroy/re-validate your objects if nothing changed.
If you are building custom components, and someone changes a property (through a getter/setter), don't invalidate the component properties if the incoming value didn't change. This will cause the component to go through the full invalidation/validation lifecycle, causing properties to be re-validated/comitted, and the object to be redrawn on the display list. Only invalidate properties if something actually changed. Here is a straightforward example to demonstrate the concept:

public function set myProperty( value : Number ) : void

{

if ( _myProperty != value )

{

_myProperty = value;

propertiesChanged = true;

invalidateProperties();

dispatchEvent( new Event( "change" ) );

}

}

8) Dynamic/Generic vs. Typed Objects - Dynamic and generic objects certainly have their place. They are generic, flexible, can be modified with any attribute, and can be used in a wide variety of situations. However, if you have a typed object and do not need the generic qualities, use strongly typed objects. The strongly typed nature of ActionScript 3 is one of the reasons it is fast. Accessing properties of strongly typed objects is simply faster than accessing properties of generic & dynamic objects.

9) Use constants when applicable - If you have a value that does not ever change, but you reference it all the time, use a constant. Constants are accessed faster and require less overhead.

10) Use static members - Static properties and functions do not require a variable instance to be invoked or accessed. Since they don't require an instance, it is faster to access them directly from the class, and does not require the memory necessary to instantiate the object. Utility functions, or functions that do not require attributes of a specific instance should be put into static functions.

Speaking of constants in #9... normally I suggest to make constants static. This will help you keep your memory footprint to a minimum b/c it will not need to be attached to a class instance.


Some missing features in action script 3

#1: Abstract Classes with Abstract Methods (ASL-18)

Well, do I have to have to say something about that wish? Basically abstract classes are such an essential thing, I am still wondering how Action Script made it to 3.0 without them. Just documenting which Methods must be overridden is not enough. And the known workarounds are really... well... hm... forget it - this is a compiler thing, which cannot be checked at runtime.

#2: Generics (FP-811)

The Vector class is a good start - but it's not well supported in Flex 3 (keyword: data binding) and it's not a generic concept. There should be something like Generics in Java that provide type checking at compile time, but can also be used for any custom class, just like in Java.

#3: Threads (ASL-23)

Not every method can be split up into chunks and processed using callLater. Real threads or at least a simplified form are essential for enterprise grade applications. But that's probably the oldest discussion around Action Script which will never be implemented.

#4: Enums

Well, although Enums can be easily simulated using classes, it's way more complicated when working with BlazeDS. When the backend relies on Enums in its data structures all enums must be wrapped in Java Pojos, before Blaze DS can handle them. And worse, even all the data structures that have references to enums, must be wrapped to reference the Enum wrapper classes instead.

#5: Non-public Constructors (ASC-2583)

Makes a singleton in Action Script much easier. Also a protected constructor would enforce the need to sub class a template base class.

#6: Operator Overloading (ASL-10)

Still missing it in Java and this is, where Action Script could actually beat Java. I don't want to have another equals method for comparing arbitrary classes for equality - I want to be able to simply override the == operator to be able to compare any two objects for equality. Or the + operator for concatenating two data structures. Just like in C++ or smalltalk.

#7: Method Overloading (ASL-9)

While ActionScript provides an easy way to simplify methods with long parameter lists using default values for parameters it's not enough to justify not having method overloading. I do not want to have to write methods like doSomethingWithString(value:String), doSomethingWithInt(value:int), doSomethingWithObjectA(value:ObjectA),...

#8: A True Hash Map Implementation

A HashMap is an essential data structure today. But currently it's hardly possible to implement a true HashMap for all generic ActionScript classes, as the base Object class, does not provide a template method that returns a hash code and therefore no instance can provide a hash code. Another problem is the ability to check for equality - see #7.

#9: Native Widget Style for AIR

According to Adobe, AIR should take over the desktop with local applications. However AIR applications will always look like alien applications, as the look and feel will never match the look and feel of the operating system. If Adobe wants to be taken serious on the Desktop, a native and accelerated Widget Style is a must. This could be done by providing wrappers for the basic components that are displayed using native UI elements (Cocoa, GTK, Windows) and by providing access to the operating systems color scheme.

Well, that is just my personal wish list. Most probably other Action Script developers have much better ideas or would prioritize my list in a different order. I would like to hear your ideas. Be creative and leave comment.