While helping a coworker get started with Flash and Flex development, I thought it would be a good time to cover the list of things that I have found pretty essential to know about Flex development, coming into it as a new developer.
Some of these items are simple details that you need to know. Others point to profound differences between Flash/ActionScript/Flex and other development environments.
Before you start
If you know HTML/CSS development, and some JavaScript, but nothing about ActionScript or Flex, you should really take the time to understand what object-oriented programming means, as ActionScript is a true object-oriented language, and Flex is an object-oriented framework. The same advice applies if you have been doing pure timeline-based Flash development without getting much into the ActionScript stuff.
Doug Winnie of Adobe has produced an excellent article addressing this topic. Additionally, he offers a series of free online video tutorials to get you started with ActionScript development from the perspective of a Flash developer.
1. Things happen asynchronously, even the simple stuff
Flex is a very asynchronous framework. What does ‘asynchronous’ mean? Basically, it means that you can’t really depend upon something happening right when you invoke the call to it in your code. Instead, the actual consequences of an assignment, or a call to a method on an object, might happen at some arbitrary time in the future.
This is not just the case when you call a remote HTTP webservice from your Flex application; it’s also the case when you do something as simple as setting the dataProvider
property for a user interface control such as a DataGrid
. Behind the scenes, DataGrid
performs all kinds of work that doesn’t necessarily occur at the time your code make the assignment, and you don’t necessarily know when it will be complete.
You need to be aware of this fact when coding your applications.
2. Styles versus properties on Flex UI components
Flex UI components (buttons, menus, and so on) have both properties (as provided by the ActionScript language) as well as styles (which are provided by the Flex framework).
It’s important to know the difference between properties and styles, since some visual aspects of components can be set via properties:
button.width = 100 ; |
button.height = 50 ; |
and others are set via styles:
<mx:Style> |
Button { |
color: #cc0000; |
textRollOverColor: #ccff00; |
fontFamily: Trebuchet MS; |
} |
</mx:Style> |
|
<mx:Button id= "setupB" text= "Click Me" click= "onSetup()" /> |
If you try to set a style in ActionScript code using the same syntax as properties, the attempt will fail. You need to use the setStyle()
method instead:
button.setStyle( "color" , "0xc3f508" ) |
It’s also important to realize that while most property changes happen very quickly, there’s a great deal of overhead in using the setStyle()
method at runtime for defining styles. So you should try upfront to define as many styles as you can, using style sheets.
3. CSS styles in Flex are not exactly the same as in HTML
Flex components can be styled using standard CSS style sheets, and in fact you can include CSS stylesheets in your Flex application.
But there are two things you should note:
- Though CSS uses a hyphenated style (example:
text-font
) for its property names, Flex uses camel-case (example:textFont
). This apparently came about because the hyphens cannot be used as attribute names for MXML tags, due to rules imposed by the XML standard.
Flex does accept the hyphenated names if you include an external stylesheet, or if you define styles inside the body of an<mx:Style>
tag. But in general, if you are styling a Flex/AIR application and don’t plan to share those styles with HTML content, you should probably prefer the camel-case names for consistency across your application. - Flex components have many style properties that simply do not exist in HTML-land. For a complete guide to Flex styles, see the online Flex 3.0 CSS Properties List, as well as Adobe’s Flex 3 Style Explorer.
4. MXML and ActionScript are one and the same, even if it doesn’t look that way
All of the groovy MXML tags that you use to declare interface layouts in Flex are turned into ActionScript objects by the Flex compiler. Likewise, you can place ActionScript inline in your MXML files, and you have the choice to create new components using MXML or ActionScript.
It’s worth understanding the relationships between MXML and ActionScript so that you can make intelligent decisions about when to use MXML, and when to use ActionScript. The Adobe Developer network has this introductory article on the topic. I also have some thoughts about this topic which might become a future blog post.
5. The Flex Code-behind pattern
The Flex Code-behind pattern goes a long way towards helping developers sort out the duality that exists between MXML and ActionScript in Flex projects. It’s based on the notion that user-interface layouts and controls are best handled by MXML, and application functionality is best handled by ActionScript.
And Code-behind is further based on the notion that MXML and the ActionScript that services it should be decoupled from each other. Decoupling allows designers to easily modify MXML, and developers to easily organize and reuse ActionScript functionality, or swap out interfaces on top of the same AS codebase. You can think of it as “unobtrusive ActionScript” for MXML.
See the very detailed presentation of this pattern from my friend James Polanco of DevelopmentArc.
6. The lifecycle of Flex component creation
MXML versus ActionScript largely concerns itself with the static organization of your program – what bits go in what files before you submit them to the ActionScript compiler? But an equally important topic concerns itself with what happens inside a Flex application when it starts running.
Flex has a well-defined lifecycle, complete with a state machine, for creating and destroying user interface components within an application. It also offers you several well-defined places where you can patch into this lifecycle at various points, to customize behavior for your needs.
Failing to understand how Flex creates and destroys components can lead to some unexpected coding errors and confusion, such as trying to change properties on an object that doesn’t yet exist.
See the excellent whitepaper on this topic from the folks at DevelopmentArc.
7. The racetrack model that Flash runtime uses for interleaving rendering and ActionScript execution
The Flash runtime began life as a mechanism for providing scalable animations on a computer screen. One of its biggest requirements was to produce smooth animation that doesn’t stutter. As such, the Flash runtime has baked within it at a very deep level the notion of frame rates and enforced rendering cycles.
As your ActionScript code runs and makes rendering requests, they are not carried out immediately. Instead, the Flash runtime queues each render instruction into a “display list”. The Flash runtime, unbeknownst to you, “butts in” at predefined intervals to render all the pending display list items to the screen, then returns control to your code. This behavior works in marked contrast to other virtual runtimes such as Java, which perform display rendering synchronously and only when your application says to.
Understanding how the Flash rendering model works, and how it fits in with asyncrhronous execution, is important to understand what happens when you manipulate Flex controls, and when your results appear onscreen. The best description of the “elastic racetrack” model Flash uses for rendering can be found in this blog post.
8. How data binding and watchers actually work
Flex has a mechanism called “data binding”. Basically, all this means is that you “bind” a source property to a destination property. Anytime you (or the user) changes the source property, Flex automatically copies the change to the destination – no extra code is need on your part, and you don’t have to worry about keeping them in sync. For instance, if you bind the value of a slider to a text field, anytime you drag the slider the text field automatically changes.
It sounds simple, but Flex does muddy the concept by (as usual) offering several types of syntax, both in MXML and in ActionScript, to bind one property to another. And there are several advanced things you can do with data binding. For instance, you can bind not only to properties, but also to functions, to allow you to alter the data as it is copied to the destination. Or you can simply set up a watcher on a property, so that your code can receive an event whenever the property changes.
Adobe’s Getting Started documentation on the topic is, in fact, a good place to get started.
9. Data encapsulation and loose coupling are important
Working on a new Flex application can fit the following pattern: you quickly get the user interface and the backing ActionScript up to make something that runs, often within the space of a single top-level MXML file. And then you start adding features. And additional code to tweak behavior of the controls within your application. And more features. Pretty soon, the entire application starts to look like one big pile of spaghetti, with controls and behavior heavily coupled to each other.
Code organization and top-level structure are very important in Flex and AIR projects. I’ve found that you can build an ad-hoc Flex application that scales up to around 1000 lines of code in a single file. Past that, there’s too much code and too many interactions between components to understand what’s going on. Beyond that point, you get into a situation where you change one thing here, and some unintended consequence pops out there.
Depending on the ultimate goals of your application, 1000 lines of code in a single file, without any externally imposed organization, might be just the trick. But odds are your application won’t stop there. In order to scale to additional sophistication and complexity, your application needs an overall architecture.
Here are some hints for organizing larger-scale Flex projects:
- Components are your friend. Divide your user interface into several MXML components. Doing so allows you to localize the particulars of each component into one file, so that when you need to look at how it operates, you are staring at 30 lines of code instead of 300, or 3000. ActionScript that you define within components should have as many private variables as possible, and use setters and data binding to allow outside code to manipulate the component’s internal state.
- Separate back-end functionality from front-end user interface. Build out your application functionality (business logic) in separate ActionScript classes. Where you are tempted to have your business logic modify an onscreen control, define a custom event and have your ActionScript class dispatch it. Make your main application listen for that event, and then set the control.
By separating business logic from user interface this way, you make it easier on yourself to figure out just who modifies your user controls, and who invokes your application logic. That makes unintended behavior when you make code changes much less likely. - Use the Code-behind pattern. The code-behind pattern further isolates your business logic from the user interface controls which drive it. A change to the user interface alters few lines of code, and the alterations are localized. Again, this makes “spooky action at a distance” unintended effects much less likely, and make it easier to change the interface without breaking the business logic.
- Consider using a framework such as Cairngorm or PureMVC. While I have my reservations about each framework (and the Flex application I currently work on does not employ either), they do have the advantage that they define standard patterns and conventions to how you structure your application, thus enforcing a sense of order and relieving you of having to make many decisions about how to lay out your overall application structure. They can also enforce a sense of uniformity to your code, which makes it easier for you and others to approach your application source code and understand “what goes where”.
- Use unit testing and functional testing. After you have broken your application into components, use FlexUnit or Fluint to write unit tests for them, and check out FlexMonkey to automate testing of your entire application at a holistic level.
Unit tests are great for insuring that each piece of your application works reliably in isolation. Tests help localize bugs, so that when something goes wrong you know that the bug is contained within a relatively small section of code. You never feel helpless because a bug could be anywhere in the system. And when you make changes, tests make sure you didn’t introduce new bugs into your code.
The time you spend developing tests is repaid in the time you do not spend in a debugger chasing down the root cause of a new bug. Tests also repay themselves in that once you author a test, you can run it again and again to verify your application works properly, forever. The time you spend writing the test is amortized over the lifetime of your application.
10. Weak versus strong references in ActionScript
Memory management is an essential thing to understand whatever language or environment you work in, and ActionScript is no exception. If you fail to understand how the runtime environment manages memory, you are likely to bloat your application through memory leaks or memory fragmentation.
This blog post and this one are both good articles to read, to help you understand how you can provide hints to the ActionScript garbage collector to allow it to free up memory associated with your event listeners.