I’ve recently encountered a couple of libraries that despite being 99% pure AS3 had minor dependencies on the Flex framework that prevented their use in ActionScript projects or in Flash without modification. This is unfortunate, because it limits the immediate usefulness of the libraries, and fragments the community’s access to them.
Regrettably, this approach is (unintentionally) promoted by Adobe. There is a ton of useful code distributed in the Flex SDK with minor or no dependencies on the framework, and no effort has been made to eliminate those dependencies and distribute / identify those classes for use in non-Flex projects. I’d love to see some kind of identifier / documentation for framework independent code, and have it distributed with Flash as well.
<tangent>Moreso, I’d love to see a core UI framework that is shared between Flash and Flex, and is extended (in the general sense, not necessarily via inheritance) with Flex specific functionality (and the bulk that implies). It’s time for a unified component framework in the Flash platform! But that’s a rant for another post.</tangent>
So, what strategies can you use to create framework independent libraries?
The most obvious approach is to avoid including framework dependencies whenever possible. For instance, use an Array or Vector instead of an ArrayCollection. It’s platform independent, and a lot more efficient. Almost all of the libraries I release use this approach. Of course, this isn’t always possible or desireable, so we need other solutions.
From an architecture standpoint, you can utilize inheritance, interfaces, and composition to append framework specific functionality to your core code.
Inheritance allows you to “branch” your core logic to create framework specific subclasses, including all framework imports. This comes with all the usual caveats of inheritance, including making sure you define methods appropriately to make it easy to override ones that will become framework specific. Generally you will have a functional core class to use in ActionScript projects, a Flex specific subclass, and potentially a Flash specific subclass.
Composition can provide a more flexible approach. You can build your core classes to rely on plugins that encapsulate all framework specific logic, and which define a simple interface. By default these plugins can point to a framework independent implementation (even to the classes that use them). As a simple example, you could have an ITextInputMediator plugin that exposes methods and events for working with text inputs. By default it would point to a TextFieldMediator class, but could also be pointed at a FlashTextInputMediator or FlexTextInputMediator classes.
The act of setting up these plugins could be done manually by the library user, or could use a keystone class. This class would be compiled into a project once, and would import and assign the appropriate plugins and factories when it initializes.
You can also use conditional compilation to toggle imports and logic blocks based on the environment. For the most part, this offers the cleanest approach, but you must ensure to document it clearly, as conditional compilation is not yet widely used or understood in the Flash world.
Locally, you can leverage reflection (ex. getDefinitionByName and the “in” keyword), dynamic access, and events to your benefit. The first two should be used as little as possible, because they come with unwanted side effects like reduced compile time error checking. Because the event model exists at the player level, you can listen to any event from any IEventDispatcher object, without having to reference its type directly. SPL uses this to listen for “valueCommit” events from Flex controls, without having to import the framework – it uses a local constant for the event name instead of importing the Flex event object.
As a last resort, if your library has dependencies on well encapsulated Flex framework classes (ex. utility classes like HashUtil), you could choose to distribute them with your library to make it easier for users to get running. Always test the package in isolation to ensure you have included all of the dependencies (like that pesky Version.as file), and document which classes you included, so people using your library with Flex can optionally delete the copies you included.
Making your libraries more widely usable means they can be used by more people, which is really the point to releasing them. It also helps provide a more consistent code base for all Flash platform developers, regardless of the framework they’re using. If you aren’t going to make your library framework independent, at least consider trying to architect it in such a way that another developer could more easily modify it to work without the dependencies.
Now let’s see what we can do about encouraging Adobe to embrace this idea internally. 🙂
If you have other approaches or ideas on creating platform independent libraries, feel free to share in the comments.