Day: April 14, 2008

Creating Layouts in Flex

Creating layouts in Flex should be easy, specially when you are using Flex builder and drag and drop capabilities. But, it is a little tricky than it seems and if you choose to ignore some of the finer details, I promise you will be stumped mid-way. While, I found some articles, but I still find something consolidated that I can get into my head. These are all scattered away (maybe I can not pin-point to the right stuff yet). Here is my attempt to put down in black-n-white some guidelines and rules as to what you should be doing and what not?

While all the feedback and comments are welcome, I would appreciate if you can collaborate with me on this one for us to have a comprehensive set of guidelines 🙂

Flex default layout manager, containers and children follow sizing and measuring algorithms to layout the pages and this exercise can be very resource intensive. You never know the client (PC) that will be running your application. Also, what you can not do is to have a minimum requirement like 2GB ram on all systems that run the application, because that would not be possible practically. This is not a game but an application that business users will work on.

Rule 1: Avoid unnecessary container nesting

Coming from an HTML/CSS background it is easy to fall prey to this habit when the objective is to have flexible designs. One example where things can go wrong very quickly are

Flex Layouts | Nested Containers

When you have such kind of nesting, the containers run measuring and sizing algorithm on children. Now, if you have some of the children as containers themselves this can be very time consuming. This will also be a performance issue if you are choosing to resize your screens as the same algorithm is executed again.

You must be asking what should we be doing if we find ourselves in such a situation? Look for alternatives. You should re-evaluate your choice of containers, a better option is Constraint based layouts which makes use of Styles, Horizontol & Vertical alignments, margins, and spacers.

Rule 2: Do not use absolute layout techniques

This technique needs you to define co-ordinates (x,y) for objects. While, this technique is most performant as the there is no need for the player to find out positions for the children, it is not a recommended practice. This approach will not provide you flexible designs and re-sizing the browser window will not resize and re-layout the objects. Try avoiding this one. This approach can be used only with Canvas or Application with layout=”absolute”

Also, you can choose to hard-code widths and heights. This also is a quick win solution because the player need not calculate sizes of objects. In many applications, you will find that this is anyways needed, because, you would not want to extend/shrink the size of your controls like TextInput with changing browser size.

Rule 3: Make wireframes before you start making layouts

This is a very handy and good practice. If you can, then make sure you have a paper-layout (wire frame) of your application design. This will help you in understanding the application design and assist in choosing a container appropriately

Rule 4: Use Navigator containers

Navigator containers like Accordion, TabNavigator and ViewStack has built-in deferred creation policy. This means that all the controls are not created at application start-up, but are deferred until you have activated that view.

Rule 5: Use Box when you have line up things in one direction (horizontally or vertically)

You should be using Box, HBox or VBox only when you have to logically group some controls together and place then in a layout. Do not use nested HBox and VBox to do placements on the screen.

Rule 6: Use Constraints if you have applications that can change size

You can use top, bottom, left, right to set anchor point on the application. This will ensure that your containers and controls would be anchored to the borders as defined by you. Let us say that you have set a control with left=10 and right=10, this will mean that as you resize the application, the size of the container / control will change.

I will try to code an example and upload the same for you to view in some time.

Flex Best Practices

Best Practices while developing in Flex/ActionScript 3.0

Use of Design Patterns

As in any other language, use of design patterns is also recommended in Flex. Some of the most widely used and successful pattern in Flex world are:

  1. Command Pattern: As a design pattern, Command Pattern is used where objects are used to represents actions. If you break up your application as features, then you should be having one command per feature. This pattern brings in many benefits like:
    1. re-usability of code as we have encapsulated functionality in classes that can be invoked from various areas of the application;
    2. commands can be used queued up using a Manager and can be run in sequence or asynchronously;
    3. provides the capability to perform undo(s) by maintaining the list of commands as the get executed
  2. Model-View-Controller (MVC): You can choose to have a MVC as a “hand-rolled” code, or use some of the existing libraries like PureMVC or Cairngorm.
  3. Singleton: Flex being a client, it is recommended that you manage state on the client itself instead of a server. Singletons provide you with a capability of managing states in the objects itself.

Caveat: You can not use Singletons together with Modules. Doing so would mean that multiple instances of the same module will be referencing to the same model and hence data causing issues on the views. This is one area where you would have to careful not to tip the balance.

Performance

  1. Garbage Collection: Little known facts:
    1. runs when the Flash player needs memory and is based on many factors like available RAM, available chinks;
    2. runs automatically and you can not force it to run
    3. does not do everything in single run. Player manages garbage collector execution in a thread and it may take a while before garbage collector starts to collect memory
  2. Use weak references for event listeners if you are very sure that there would be other references. But, if you not sure of that, then you should be using a strong reference. What you do not want is to loose your event listeners just because there are no other references to the object. If you use strong references, make sure you remove event listeners as well. A weak reference is one that is not counted by the Garbage Collector (i.e. it is not counted in reference counting, and it is not followed for mark sweeping). This means that if the only references remaining to an object are weak, it will be available for collection on the next GC sweep. References associated with event listeners are often forgotten by developers, which normally results in the listener never being removed from memory. This is why weakly referenced event listeners are so handy – if you forget to remove the listener, you will not impede the Garbage Collector’s ability to collect the object. But, they can be tricky as if there are no other references, and if you are awaiting response from an event, the event will get lost as the object would be collected by GC.
  3. Defer instantiation: You should be using deferred instantiation for creating controls. Containers like ViewStack, Tabnavigator has deferred instantiation activated by default and you should not change the policy. This will lead to having quicker application startup
  4. Reuse objects instead of creating new ones: killing existing objects and creating new ones will lead to an overhead on the player. Also, this will mean that you will have to write code to cleanup references of the object or else Garbage collection would not work
  5. Cleanup: To do the cleanup make sure you always, remove all event listeners and clean up all variable references by setting the object to null
  6. Make use of runtime shared libraries to decrease startup time

Optimization

  1. Use strongly typed variables: ActionScript compiler would be able to do some good code optimizations if you are using strongly typed objects
  2. If you have to refer to an object property time and again, then set that to a variable. Like: Do not use arrayObject.length in a for loop. Make sure you have that stored in a variable before the loop begins
  3. Be conservative about using custom item renderer’s in DataGrid. Having a renderer for every column would kill the performance
  4. Avoid unnecessary component nesting. Try to use Constraint based layout for laying out your pages. Use of HBox and VBox with dense nesting is not recommended. These should be used only when you have to lay out things in a row/column
  5. Use AMF !

I would be blogging away with more detailed viewpoints on each of these in times to come.

Disclaimer: Please note that the best practices listed above are purely my ideas/opinions and not recommendation by Adobe or Sapient. You