Tag Archives: reuse

There, There, and Everywhere

While Flash is a full participant in the world and idioms of the web, Flex is more attuned to applications (e.g.  full-screen) rather than as part of a larger web page. I come from a traditional applications development (sometimes I say that I don’t do dancing kitties”). When Adobe made the AIR runtime for the major desktops, I felt like I was home. Just as Flex and Flash allow one to Write Once, Browse Everywhere, AIR allows us to write applications that behave the same (mostly) whether running off a browser or on a desktop1.

AIR is a desktop runtime container that executes swf applications2 stored on a local drive rather than receiving the swf as part of a web page in a browser. It’s runtime library supports several classes that the Flash Player runtime library does not, specifically ones dealing with local file selection and management, HTML display, windowing, and native chrome (menus, window widgets, etc). AIR also includes installation and update protocols useful for desktop applications, which include an application profile specifying who distributed  it (i.e. who digitally signed it) and if it will modify local files, access local resources like web cams, etc. The AIR runtime will enforce these limitations (just as the Flash Player limits its swf’s’ access to servers based on the server’s crossdomain.xml file).

Even with the new ability to package, install, and execute native code modules, AIR is not designed to build low-level system tools for the desktop. It is designed to present the same sort of rich application that the Flash Player presents on the browser. These application present data in interesting ways. They connect different services together (e.g. Twitter and Google Maps). They connect to private servers and databases.

Why AIR?

We want to offer an AIR version of our applications because of the things they will notice: They will notice if your web application does not have an internet connection. The will notice if they have to browse to every file instead of dragging it. They will notice that your application reminder makes a new tab in their browser instead of a toaster message onto their desktop.

The key to offering the same application on both the Flash Player and the AIR desktop is more than reuse the same pieces; the key is to “reuse” the whole thing.

To do this, create an AIR project and a Web (Flash Player) project (e.g. DoSomthingAIR and DoSomethingWeb). Both will have just the top-level application MXML file and an implementation of IFilesManager appropriate to that environment. The majority of the application is in a core component in a DoSomethingLibrary project. It  has all the data connections and UI of the application. It can use local storage3 to keep non-confidential default settings (and even share them between the Flash Player and AIR applications on the same machine).

The only parts of the application specific to AIR or the Flash Player are:

  • Native drag and drop messages are ignored in the player (but they generate standard drag & drop messages)
  • System connectivity messages (AIR only)
  • User inactivity messages (AIR only)
  • File access operations (AIR only)

If the core application component is listening for AIR-only events, it will still run well in the Flash Player (although it will never hear those events). To handle the differences with file access operations, for example, one can create an Interface that hides the details and have an implementation class for each platform (see AIRFileManager and FlashFilesManager in Figure 1). Each application can instantiate the appropriate instance and assign it to a property of the core application component or of some common static class. The core application calls methods of that property (which is typed to the Instance) oblivious to which platform’s class is doing the work.

Converting an Existing Application

One might have an application complete or near complete before one considers a dual platform deployment.It’s easy to break the core application out so both runtime platforms can use it.

  1. Open the existing project
  2. Create a new Library project
  3. Add any swc libraries (e.g. flexlib, a3corelib) that the existing project to the new Library project. You can move any swc’s from the original project’s lib/ to the new Library project’s lib/ as well
  4. Drag the src/com/company/stuff directories from the original project down to the Libraryproject src/. You want it to move, not copy.
  5. Open the project’s main MXML file and copy everything to the clipboard
  6. In the new Library project, create a new MXML component based on Canvas in the new library project. Call it “CoreApplication”
  7. In the new CoreApplication component, paste the clipboard under the <Canvas> element of the new element and remove the <Application> elements and any attributes that apply directly to the application itself.
  8. Save and build the new library project and fix any references.
  9. Add the library project to the existingproject’s Build Path. If you add the whole project instead of just the swc reference, debugging is easy
  10. In the existing project’s main MXML file, remove everything except the <Application> elements and those properties that apply only to the application itself (e.g. viewSourceURL)
  11. In Design Mode, add an instance of the new CoreApplication component from the Custom branch of the component tree. Set the bounds to: 0, 0, 100%, 100%
  12. Build the original application again. It should work exactly the same.

Now you can create a new project for the other runtime platform (e.g. AIR) and put a CoreApplication component in it as well.

Two-For-One Is Enough

This technique allows us to deliver the same application via a browser or a desktop; it does not magically change the application. Mobile applications are fundamentally different in their presentation and flows; although the delivery mechanisms (AIR and the Flash Player) might be the same, do not try to leverage any non-trivial application’s UI into a very different environment. For this, we do need to design the parts of the application for individual reuse in a new application designed for one or more mobile environments.

If you are new to AIR, a good intermediate book is:

Adobe AIR in Action, Lott, Joseph; Rotondo, Kathryn; Ahn, Samuel; Atkins, Ashley, Manning 2009

1Windows, Mac, and Linux desktops
2As well as HTML and JavaScript
3using the SharedObject class

Reuse … Your Brain

Components were supposed to save us; they were the silver bullet that would make code reuse actually work. The problem with reusing code is that it takes at least three times as much work to make a component that works in all cases rather than just the ones the component author had in mind, and no one wants to put the work in unless they are getting paid.

The fun part of components is figuring out the best level of encapsulation and making a piece that fits nicely into that spot. Testing, debugging, documentation, and validation are not (for most people) the fun parts. for components to be useful in more than one context, they have to be internally and externally consistent, they have to handle attribute changes in all possible combinations, and they have to handle external error conditions at every possible point. Software libraries and SDK’s distribute themselves as classes and components, and they make applications possible. For the infrastructure organizations and component vendors, this is their business.

Components built within organizations do not have the support of paying users, and so they tend not to have the fit and finish of their commercial brethren. A commenter named Tim put it well in a discussion about Agile/XP and reuse:

The first time you have to pay for it to be coded,
The second time you have to pay for it to be reusable,
The third time it’s free.

With all due respect to Agile and XP, I err towards the other end of the spectrum: I like to build software clean enough that I am not embarrassed to have others use it. I want it so obvious that I will understand it quickly when I come back to it later. I like building well-rounded components that will survive a little transplantation or changes in usage. I like to take the time to make classes that know how to clone, clear, deep-copy/assign, and test equality. In other words:

Treat Yourself As You Would Have Others Treat You

Nevertheless, managers see a component named DataManager and assume (or at least hope) they can reuse it anywhere their design calls for a data manager. They don’t want to “waste” the effort spent building it the first time. Here is when intuition fails us all: we talk of “building” software instead of “composing” it. Software is ideas made manifest (albeit in a structure that judges those ideas against a very solid and unforgiving reality).  Software is not an engine where the number of cylinders is fixed. However, composing a better component is easier than building a second house. It’s often impossible to rebuild a component exactly the same as its original because the composer/author/developer/coder can’t stop themselves from improving their idea.

Besides running the same code in different environments, the best reuse is reusing experience. Experience grows all the time (and grows faster from bad outcomes). Rather than looking at components as commodities that remove the need for experienced developers, look at components as the steps that developers can stand on to see farther.