There are lots of ways build Flex applications. This shouldn’t surprise you; there are lots of ways to do most things in life, and building Flex applications is no different. Furthermore, it’s impossible to say there is exactly one right way to build Flex applications, just as it is impossible to say there is just one right way to do anything else. However, you can employ certain strategies that increase your likelihood of success when building Flex applications. We call these best practices, and in the following sections we’ll go into a bit more detail regarding a few of the best practices we consider most important. We strongly encourage you to try these out for yourself. Give them a fair chance; you may later discard some of them, but chances are that more than a few will prove to help you and your teams in the long run.
How you organize project files can have a tremendous impact of the success of a project. File organization might seem unimportant, but don’t underrate how influential this factor can be. Organizing files well ensures that not only is it easier to find the files and easier for teams to work together, but also you avoid potential naming conflicts and can facilitate source code versioning (see the section called “Versioning”” later in this chapter).
If you use Flex Builder to create Flex
projects, you have probably already noticed that Flex Builder
provides a degree of organization. Primarily, Flex Builder
distinguishes between where it stores source code (
files) and where it stores deployable application files
.html, and runtime assets). The default names for
the directories that Flex Builder uses are
src for source code and
bin-debug for deployable application files. This
high-level structure is important and essential to good project
file organization. However, you can do more, and indeed more is
required to keep files organized clearly. The following are a few
of the key things you can do to organize files:
.asfiles (except for the main application
.mxmlfile) in packages. As you’ve learned, Flex treats
.mxmlfiles as ActionScript classes, and therefore we can think of them and organize them just like we would ActionScript classes. We generally recommend using reverse-domain names for packages. For example, all the classes and
.mxmlfiles for the sample application in this chapter are organized within a
com.oreillypackage. After the reverse-domain package, we advise using a project subpackage where appropriate. In the sample application, we place all the files in a
pf3project subpackage. Then it is considered a best practice to further organize files into subpackages. For the sample application, we use the following subpackages:
See the section called “Abstracting Common Patterns”” later in this chapter for more information about controllers.
We use this package for all event types (subclasses of
See the section called “Abstracting Common Patterns”” for more information about models.
This package organizes all the business delegate and related classes.
See the section called “Abstracting Common Patterns”” for more information about views.
Place all embedded assets in a directory inside the source files directory. In the sample application, we call this directory
assets_embed. This directory can contain
.swffiles, embedded image files, and generally any sort of file that might be embedded in the application (as opposed to loaded at runtime). Depending on the number of files, it may make sense to create further subdirectories to better organize everything within the embedded assets directory.
Any runtime assets that must be deployed with the application should be organized within the deployable application directory (
bin-debug). These files might include
.xmlfiles, image files, or any sort of file that the application loads at runtime. Generally, these files should be organized within subdirectories within the deployable application directory.
Flex provides a lot of ways to apply styles to applications. You learned about all of these ways to style applications in Chapter 8, Customizing Application Appearance. This provides a great deal of flexibility in how to style an application, which is both good and bad. It is good in that it provides lots of options. It is bad in that it allows developers and teams of developers to apply styles without a consistent approach or plan.
We find that in general, it is best to apply most, if not all,
styles via external
.css files. We
make exceptions for some layout-related styles such as
horizontalAlign, which we frequently apply
inline. However, we prefer to apply the vast majority of styles via
.css files. For the Flickr
application, we use only one
file because the application simply isn’t complex enough to
warrant more than one
If you look at the
file, you’ll notice that we’ve organized our selectors
to make them somewhat easy to locate within the file. We place the
Application type selector first in the
file, followed by the rest of the type selectors in alphabetical
order. Then we follow the type selectors with the class selectors,
also organized in alphabetical order.
Although it is sometimes tempting to apply styles via inline
attributes to MXML tags, we’ve found it is far better in the
long run to take the extra minute or two to apply styles via
.css. This has several
advantages, some of which are as follows:
.csscleans up style-related clutter from
.cssallows non-Flex developers to work on styling an application.
.csshelps to differentiate between the layout (
view/.mxml) and style (
Application components are
invaluable and cannot be overrated. Large
.mxml files or ActionScript classes without
clearly defined roles and responsibilities are a good sign that
refactoring is necessary. When an application consists of many
smaller components, it is often easier to work as a team, to debug
an application, and to add new features or make changes to existing
features. Too few components, or components that are too large and
too complex, make applications difficult to manage. It is generally
advisable to err on the side of too many components with
responsibilities that are too granular than the other way around.
As a rule of thumb, all components should have no more than two or
possibly three key responsibilities. If a component has more
responsibilities, it should be refactored into several more
As we’ll see later in this chapter, we use application components extensively for the parts of the application that we call the views and the controllers. Almost universally, developers use application components for views. Our use of application components for controllers is somewhat less usual, but we think it provides a solution to issues that are unique to Flex. You can read more about views and controllers later in this chapter. You can read more about application components in general in Chapter 9, Application Components.
Although versioning may seem like a related practices rather than a core practice, it is nevertheless a core practice that every team should be following for Flex projects. A variety of versioning software tools are available. Some of the most popular are Subversion (which we are using for the sample application), CVS, Mercurial, Git, Team Foundation Server, and Visual SourceSafe (VSS). Every versioning software works slightly differently, and different teams have different philosophies regarding how to manage code repositories. For example, some teams prefer not to add large assets (e.g., videos) to version control repositories, whereas other teams prefer the simplicity of adding everything to one location. What is most important is that you always add all source code to a repository, and you should always keep the repository up-to-date with changes. For the FlickrFlex project and many of our own projects, we like to add everything to the Subversion repository, including source code, Flex Builder project files, runtime assets, and compile time assets (embedded images, fonts, etc.).
Unit testing involves writing code that runs automated tests on project code. A test will run an assertion that will either pass or fail. A group of tests is known as a suite of tests. When running a suite of tests, you can quickly determine whether code is behaving as expected. If all the tests in a suite pass, it indicates that there is a good chance the application is working correctly. If one or more tests fail, it shows you where you should look to correct a problem with the code. Automated tests allow you to run suites of tests frequently, often every time you make a change to the code for an application. The results of the test will help you immediately identify any problems which new code might introduce.
Unit testing does not require that you use a testing framework. However, using an existing testing framework can greatly simplify writing and running test suites. There are two testing frameworks that we know of for use with Flex: FlexUnit (http://code.google.com/p/as3flexunitlib/) and AsUnit (http://www.asunit.org). We find that FlexUnit is a little easier to use with Flex than AsUnit.
If you’re not familiar with unit testing or FlexUnit, you might find the article at http://www.adobe.com/devnet/flex/articles/unit_testing.html to be a helpful introduction.
Once you’ve starting writing unit tests, you’re likely to ask yourself exactly what you should be testing. Although it might be possible to write tests for every part of a Flex application, we find that it is generally easiest and most effective to write tests for only certain parts of an application. In particular, we find that tests for the following are most useful:
- Data model classes that have custom serialization or deserialization methods
- Business delegates
These are points of integration that represent relatively high fragility. If the contract with the service changes (e.g., the publisher of the service changes the API), it’s possible that the entire Flex application will stop working correctly. Having good unit tests for business delegates helps you to quickly identify where an error is occurring if a service contract changes or if a service simply goes offline or throws an error.
- Utility classes/methods
There is a philosophical approach to software development, known as test-driven development (TDD). This methodology advocates writing tests before writing application code. You then write the application code to get it to pass the tests. Some Flex developers find TDD works well for certain types of classes, such as model classes and business delegates. Other Flex developers don’t find that TDD is well suited to Flex development. We are mixed on the issue of TDD for Flex development, with one of us liking it and the other not. You’ll have to be the judge for yourself.
You can learn much more about test-driven development in the excellent book, Test Driven Development by Example, by Kent Beck (Addison-Wesley).
The sample application has a suite of tests that are included in
package, and the application also includes a test runner,
TestRunner.mxml, to run the tests.
You can see that there are two classes in the test package:
PhotoTest case runs tests verifying that a
Photo object correctly deserializes
XML data as it is returned by the Flickr service. From a TDD
perspective, it is useful to write this test before writing the
Photo class and its deserialization
method. Having the test written first can help to verify that
Photo does what it is intended to do
and that it meets all the requirements placed on it as you write
it. However, even after the class has been written, the tests are
useful because you can run them to verify that no regressions have
occurred as you refactor the application. Likewise, it can be
helpful to write the
class before writing
and yet it is also useful after writing
FlickrService to verify that the service works as
Even with the best practices mentioned in the preceding section, the idea of building a Flex application from scratch can be a bit daunting. Where should you begin? Sometimes too much freedom can be paralyzing. Artists often report that their greatest creativity stems from having boundaries. Likewise, you may find that having structure may provide the right environment for building a successful Flex application. This is the role of a microarchitecture.
Microarchitectures are intended to provide a general guideline and structure for building applications. A microarchitecture doesn’t deal with the specific requirements of a specific application, but rather concerns itself with a philosophical approach to how applications should be structured and designed in general. Microarchitectures provide these oft-needed boundaries and guidelines that help remove the paralysis you might otherwise experience. To that end they can be useful.
Various individuals and organizations promote many microarchitectures for Flex applications. A few of the more popular of these are as follows:
We don’t advocate the use of any one microarchitecture over another. In fact, we don’t really advocate the use of microarchitectures at all. Instead, we recommend that you find a system that works best for you. For the sample application, we are borrowing some of what we consider to be the best ideas from our own experiences building applications with Flex.
Although any one of these microarchitectures might be helpful and useful, don’t be surprised if it is limiting at the same time. The boundaries created by a microarchitecture can provide structure, but they are still boundaries. If you decide to use one of these microarchitectures, it is probably a good idea to follow the rules and build applications exactly as specified by the microarchitecture until you are familiar with the basics and have built several applications successfully. However, at that time you may find it useful to break the rules a little and adapt them to what works best for you. To really take our advice on this matter you’ll probably need to be fairly proficient with Flex and with basic design and architectural patterns before you even start working with a microarchitecture. That’s not because we think microarchitectures are “advanced” or “difficult.” Rather, it’s because we think that to be able to have a critical approach to using a microarchitecture (such that you can learn from the patterns without having to adopt the entire system blindly) you need to have a fair amount of Flex and application development experience first. For the sample application in this chapter, you’ll find that we’re not stressing that you must build your own applications using the same design structure we’ve used. Instead, we’re simply providing one example that uses patterns that we’ve found to be useful for Flex applications.