Modular ActionScript Development

In doing Flash Development for a multi-swf site, we ran into the “first class wins” problem. Basically, an ActionScript class’ bytecode is stored with the SWF that uses it. If the compiler detects a SWF being used, it’ll compile it in. This means, in a website that utilizes multiple SWF’s, 2 SWF’s that utilize the same class will both have their own copy. This is a waste of filesize which costs the user bandwidth.

All classes in Flash Player 8 and below are stored on the _global namespace. This is a special object added in Flash Player 6 that allows the storage of data common to all SWF’s that are loaded in dynamically at runtime, either via loadMovie or loadMovieNum. Before _global, classes were stored on _level0 …usually.

Flash Player 8 and below have a concept of levels. These allow SWF’s to be stacked on top of one another. You could do the same thing with MovieClips stacked on top of one another, but they had to exist in _root. Levels on the other hand each had their own _root. Now, there was a safe way to ensure every SWF was looking at the same data, and a great place to put classes.

No class could be overwritten, however. Classes are basically written in an #ifdef fashion behind the scenes when using ActionScript 2, like so:

// if the class isn't defined"
if ( _global.Ball == undefined)
{
        // define it
        _global.Ball = function(){};
}

Using that code above as a base, you can see how all subsequent loading of SWF’s have their classes of the same name / package ignored. The Flash Player assumes it’s already loaded, and thus does not use the class bytecode in the loaded SWF. On a job I’m on currently, we ran into this problem. We put a trace in our code, and it never ran when we deployed our SWF to the website. That’s because the website was already loading a SWF that had the same class, and thus was ignoring our new one since our SWF loaded later. Again, first class in wins.

This same problem also exhibited itself with loading applications into Central, Macromedia’s early foray in getting SWF applications onto the desktop (pre Apollo). Since Central was a SWF loader of sorts, you’d have classes left defined on _global, like they should be. This caused problems however, when you would load in a new SWF to test and not see your changes. If you didn’t reload Central, or delete your class from _global, it’d stick around, and your newly loaded SWFs would use the old classes.

The way class definitions work with loaded SWFs is not a bug and is by design for a few reasons. Additionally, it has been significantly improved in Flash Player 9.

Paraphrasing Roger’s entry about flash.system.ApplicationDomain, the justifications are basically:

  • A Loader should control what it’s loading
  • Classes not being replaced by loaded SWFs eases security concerns
  • Makes static / Singleton implementations predictable, and work with child content accessing the same classes

There are others, but those are the ones relevant to this discussion concerning Flash Player 8 and below.

You can additionally use this implementation to your advantage. Roger discusses some ways with the pro’s can con’s to each with regards to Flex development. For Flash development, some additional points are a little different.

For example, using Interfaces to allow 2 or more SWFs to talk to each other prevents the same class being included in both SWFs, and thus saving space. This includes all class dependencies, so you can see how this is a great way to encourage the good practice of coding by contracts (using interfaces) with strong-typing, both in ActionScript 2 and 3. This also prevents you from having to go through the laborious process of using Remote Shared Libraries. While RSL’s are great, there are currently no good tools (aside from ANT in Eclipse which Flash doesn’t have) to help management of RSL’s, thus they are a card house. When you get them working, they rock and look great. They are not change friendly; one breeze of scope creep or refactoring, and the whole thing comes crashing down. Hell, if it makes Darron Schall sweat, you know they are hard.

Roger mentions that using implied dependencies via external-library-path isn’t such a good idea because the reverse, having the shell exclude loaded classes, doesn’t work as a use case and is backwards. With context to Flash, I disagree with the first part. I do agree that a shell excluding child classes is silly. Now, interfaces imply you have a good API designed. Our API and designs fluctuate daily. While I agree with Roger that usually your implementation changes, yes, in application development, I’d agree. However, in the Flash world, the shiz is chaos. It may sound like a cop-out, and it is. I refuse to write good code knowing it’ll get torched tomorrow. I’d rather write working code that is maintainable and flexible enough to adjust to change requests. If 20% of what I’ve been writing dies, so be it. In the design world, things change down to the deadline. We also don’t have the kind of time to “flesh out” out our API’s. We can make a great first pass, yes, but when your design can change at a moment’s notice, what’s the point? “Man, this ComboBox is phat! It extends our base TweenComponent, and moves really well in that list. Huh? What do you mean they want the list items to fade in now vs. the list zooming up!? I thought they liked it and signed off on it last week? Son of a LKEJRLKJgfdsjglkdfjg””. That’s not sarcasm; it does happen, a lot. Imagine re-writing an entire list component and all sub-classes… it sucks. Will you now spend the same amount of time hammering out an API… or just make it “good enough”? What if you suddenly have no need for a List in the first place?

Using the exclude.xml functionality built into Flash, having loaded SWF’s exclude classes that the shell will contain for them can work quite well. The trade off is, you need to remember to compile the “framework.swf” every time you make a change to a shared class. That way, all of your child SWF’s that are loaded into the main one use the same class, and are smaller since they don’t have to keep a copy of it.

How do you create & mange this framework FLA without tools like ANT? JSFL – JavaScript for Flash. There are four things you need to do.

First, you need to identify commonly used classes. These are classes, visual components and/or utility classes, that many FLA’s use. You then put these, like so, into a framework.fla on frame 1:

com.company.project.Class;

Notice the lack of import. Flash will recognize that as a usage and compile the class into the SWF. Keep in mind you do not need the MovieClip assets that go with visual components. With Flash Player 8 and below, these cannot be shared in a simplified fashion. Thus, you’re best bet is to externalize your bigger assets like images and sounds so they’ll be downloaded to the internet cache, and other SWF’s can load the same images and sounds. For frameworks like the mx one, it’s kind of a big deal, because the base component framework has a lot of built-in graphic assets that now have to be duplicated in many SWF’s. However, most design frameworks are made to be skinned, and thus are usually just lightweight MovieClips; containing a bounding box, a stop, and maybe more lightweight base classes on their assets layer, so this really isn’t that bad.

The second thing to do is to write a JSFL script that can auto-generate exclude.xml files. These text files that must reside next to your FLA file must also have the name yourfile_exclude.xml where the yourfile is replaced with the name of your FLA file. When you compile your FLA, Flash will look for this file, and if it finds it, it’ll make sure NOT to include any classes listed in the exclude.xml file in the SWF.

What your JSFL file will do is loop through all library items, and if it finds a class that is used the base framework, it’ll make sure to add that class to the list in the exclude.xml.

The downside? You won’t be able to test this SWF locally. That is unacceptable. Therefore, the third thing you need to do is to write another JSFL that deletes the exclude.xml file if there, and then performs a test movie.

Both of the above JSFL files can run in Flash MX 2004 7.2 and Flash 8 which both include the FLfile.dll. This allows JSFL to read and write text fields.

With Flash Player 9, it’s different. It also depends on if you are using the Flex 2 framework or not. Without repeating Roger’s good entry on it, Flash Player 9 has made a new place to manage the different sections where these classes are. The reason for this is because SWFs are no longer always tied to the display. Now, with the DisplayList, classes that represent display objects can exist independently, and need to be managed someplace with relation to, but not being tied to, the DisplayList. There is also a little more control over how these loaded classes are handled, and where they are stored.

When loading a SWF, you can determine which AppDom (pronounced like Kingdom – Roger’s slang for them) the Loader will use when loading the SWF. When the SWF is loaded, the classes are held in that context.

Someone, sometime, is going to have to handle this for ActionScript 3 in an easier way than is done currently with regards to Flash. Not all of us are building Enterprise Applications with SWF. Some of us don’t need the large Flex 2 component framework for our work. We need something lighter weight, like the set that Grant n’ Friends are working on for Flash 9 (Blaze), with less dependencies so it’s easier to modularize classes without the need for interfaces and Remote Shared Libraries.

Again, I agree with Interfaces with regards to Flex 2 apps, but in the design world, we don’t have that kind of time, nor can we garner that kind of commitment to API’s. Until I get a better IDE, I’ll never agree with RSL’s. To be fair, I haven’t given them a hardcore run through in a sizable Flex 2 project yet.

Anyway, I haven’t had time to peruse Roger’s Module source yet, but the “on the fly class loader” sounds pretty hot. It’d certainly make that skins on the fly tons easier via DLL-like SWFs, yes? I hope to write more about this subject in the future when I have some scripts to show as well as example file size savings. Additionally, while some bitch about how it’ll be hard to do this kind of stuff with the Flex 2 framework, SOME of it can be done, enough to make a positive impact I’m sure. When I’m done doing Flash consulting, hopefully I can jump back to some Flex 2! Till then, attach this.

10 Replies to “Modular ActionScript Development”

  1. Did you try intrinsic classes?
    I think it’s better to use intrinsics in SWF which classes are not used anyway because the SWF is loaded later and first class wins. The other way round would be you compile the main SWF with intrinsics and when the first SWF with the ‘real’ class gets loaded this is the first to win.
    Another advantage of intrinsics is that you save filesize. When only one version of a class is used why load the bytecode multiple times. Also the compile time of SWFs with intrinsic is fast because there is only a typecheck and no ‘real’ compilation I guess.

  2. An interesting post Jesse.
    I am really pleased that you have brought up the subject of Flash-based-Framworks. As I too have been having a lot of thoughts latley on creating an acceptable and flexible framework for use with Flash.
    For now I am still basing my sites loosly on ARP, as you pointed out in an earlier post, it is not flexible enough for Flash websites. Having to recompile the base.swf each time a Command is added is not really ideal.

    But I do like the idea of ARP’s Commands, they make the Model side of things much easier to maintain, so this is something I would like to try to keep. ModelLocator is also something that needs to be addressed.

    The thoughts I have had regarding a better approach have also been leaning towards a ‘classloader.swf’, possibly xml driven and loading in swf’s containing a particular class. The swf’s could then be organised in a similar manner as the actual packages (as in directories).

    Again, thanks

  3. You can create an intrinsic class out of every class. They simply start with ‘intrinsic class’ and you have to define the properties and methods like in an interface.

    Then you can compile against the intrinsic classes. for example FDT supports generating intrinsic classes. The class will be functional when the intrinsic class is ‘overwritten’ by a concrete class.

    Cheers,
    S

  4. Few problems with intrinsic with regards to Flash Development.

    There is no workflow to support this. You have to have a coder utilize a class with the intrinsic keyword knowing full well what he is doing. This means you now have to have 2 code-bases; one with the intrinsics and one with the concrete.

    With the above, you can at least install 2 JSFL scripts so even designers can easily work side-by-side with developers. If you are a Flash Developer all by yourself, no problem.

    Again, you cannot test locally. If I do a test movie, and it doesn’t work because of some dependency, that sucks.

    Finally, intrinsic isn’t supported in ActionScript 3. Although backwards compatibility is a moot point since ActionScript 3 won’t work in 8 and below, the workflow should be somewhat the same. The native keyword doesn’t do the same thing as intrinsic. Hopefully Flash 9 can somehow do something similiar to Flex’ mxmlc compiler to exclude classes. We’ll see.

  5. Yes, but the intrinsic codebase can be generated automatically. Hamtasc supports this and so it could be used via Ant.
    Another scenario where I used intrinsics. I had an AS2 classlib which was not compatible to MTASC. So I generated intrinsics with which I compiled my application using MTASC. Then the main movie loads a SWF which contains the comiled classlib and all is working …

    Anyway you have to know what you are doing when using intrinsics and it’s perhaps not the best workflow but in some situations I think it’s a nice solution.

  6. Again, from a Flash Developer perspective, I agree. However, things like mtasc, ANT, and FDT do not work well when doing design based projects. If the designer cannot compile locally on his/her machine with the FLA, that’s a failure in the workflow.

    My favorite workflow is when a desginer hands off a FLA, and I rebuild the FLA and integrate the assets into my codebase. At more creative shops and marketing agencies, that workflow doesn’t work. You’ll get drastic design changes down to the wire, and there is no way to shield your code base from such changes. The best bet is to keep the design in the FLA so your designers can tweak things if needed.

    As such, the developer(s) need to be able to work in tandem, peacefully, with the designers. Setting them up with Eclipse, or getting an existing code-base to be mtasc compatible isn’t relistic in some of the short time frames introduced. Granted, I’ve heard of a positive workflow in another company where the designer utilizes Flex Builder 2 to mock up designs in MXML and the programmer takes over from there. That is ideal, but a lot of these places still use, and will continue to use, Flash. Eclipse is an alien thing to inject into the workflow, but maybe it could work.

    If you look at this from a developer / designer workflow, you can see where the sacrifices are and why some things just don’t work in from that perspective.

  7. I can totally relate to what Jesse is saying here. In the wild west of online advertising, the one constant is change. The developer must remember that they are working for the designer, not the other way around. They want what they want regardless if it conforms to your framework or not. In this kind of business, one must sacrifice a certain amount of the benefits yielded by a framework by keeping that framework very open. Probably the most you can hope for is; code external, a loose interpretation of mvc, some managers, and a whole lotta jsfl.

  8. Great post. I agree that there is no easy way to develop and deploy a large Flash/Flex app without worrying about which classes are going to get clobbered. I don’t neccessarily agree that using RSL’s is a bad thing though. In Flex 2 building and deploying RSL’s is a piece of cake. If you use an RSL to deploy shared classes ie (a ModelLocator, Commands, utility classes) then it works great, all movies share the exact same classes, nice and easy to manage. The only big issue I have with RSL’s in Flex 2 is that anything you build that leverages the Flex framework means you pull the entire (almost 400K) framework into your RSL. So a simple class with a TextInput or Button and you take a big hit.

    Once Adobe gives developers some better tools for controlling what goes into an RSL from the framework I think that path will provide most people with a really decent solution.

Comments are closed.