A lovely little framework called Swiz

Swiz: Inversion of Control/Dependency Injection framework for Flex and ActionScript

A few days ago I stumbled upon Swiz, which bills itself as the "brutally simple micro-architecture for Rich Internet Application development with Adobe Flex." If the term micro-architecture or the buzzword Rich Internet Application haven't scared you off yet, read on, because it really is a lovely little framework.

Swiz is a lightweight framework for Flex (and ActionScript) that lets you separate your business and presentation logic and implement a loosely-coupled event-based architecture in your applications. I've purposefully stayed away from using the terms Inversion of Control (IoC) and Dependency Injection (DI), even though Swiz is, at its core, an IoC framework that lets you carry out DI. The reason? I feel people get too caught up on the fancy names and either get scared off or end up blindly implementing patterns and frameworks without really understanding what they're doing or why they're doing it. Thankfully, Swiz is simple enough that you can actually understand what it does and why it does what it does. And, it doesn't pigeonhole you into a color-by-numbers straitjacket or suffocate you under a mountain of boilerplate code like some other frameworks.

This blog post is not meant to be an introduction to Swiz. For that, read the Getting Started guide, watch the introductory video by Swiz creator Chris Scott from his presentation at 360Flex last year, and read the Swiz posts on Sönke's blog and those on Chris's blog.

Instead of an introduction, I want to document how I'm using Swiz and the modifications I've made to it in hopes that they might help other developers and possibly spark conversation on future features.

Open a window, let some AIR in

(Sorry, I couldn't resist!)

I ran into a couple of issues with Swiz when I finally got the chance to play with it yesterday. First off, I couldn't get the autowiring to work with new Window instances in AIR. Googling around, I found that this was a known issue and that Sönke had already applied a fix in the form of a registerWindow() method that you call before opening your window. The fix, however, didn't work for me without an additional little patch to manually force the autowiring on the Window class itself. So my registerWindow() method ended up looking like this:

public function registerWindow(window:IEventDispatcher):void
{
    window.addEventListener(Event.ADDED_TO_STAGE, handleAutowireEvent, true);
    window.addEventListener(Event.REMOVED_FROM_STAGE, handleAutowireEvent, true);
    autowire(window);
}

With that little change, my new Window instances get autowired correctly.

Wrrooom, wrrrrooom!

I also saw that the autowiring code was causing quite a bit of performance slow-down. So I decided that autowiring should be opt-in. I modified the framework so that only classes that have a public autowire property declared are autowired. I usually declare this in my classes like this:

public var autowire:Boolean = true;

I could have made it so that I used a metadata tag instead but the whole idea was to stay away from the overhead of describeType. (I'm not sure what additional overhead describeType's XML conversion adds on to the internal describeTypeJSON method but I have a feeling it's quite substantial. If so, it would probably be nice to have a method to just return metadata for a given class — in the spirit of getQualifiedClassName — to make it more performant to parse metadata at runtime.)

So my handleAutowireEvent() method in the Swiz class looks like this now:

private function handleAutowireEvent(e:Event):void {
  // Autowiring is strictly opt-in for performance/efficiency, and
  // having an explicit flag in the class should make your intent clearer.
  if (e.target.hasOwnProperty("autowire")) {
    autowire(e.target);
  }
}

Similarly, the handleRemoveEvent() method simplifies to:

private function handleRemoveEvent(e:Event):void {
  if (e.target.hasOwnProperty("autowire")) {
    _beanFactory.unwire(e.target);
  }
}

The performance increase has been striking: the overhead of Swiz, with this change, is entirely negligible whereas before I was experiencing a doubling in the initialization time of my app.

In case you make the same changes, you should also update registerWindow() (hey, every cycle counts right? Or something like that!):

public function registerWindow(window:Window):void
{
    window.addEventListener(Event.ADDED_TO_STAGE, handleAutowireEvent, true);
    window.addEventListener(Event.REMOVED_FROM_STAGE, handleRemoveEvent, true);

  // Fire the autowire manually for the window itself.
  if (window.hasOwnProperty("autowire")) {
    autowire(window);
  }
}

Flex Framework? How about ActionScript and Flex Framework?

I'm also using Swiz quite differently to how it was originally intended. Originally, you're supposed to declare your beans (beans? What are we Java?) in MXML. I found this unnecessarily limiting. So I declare my beans (or components; since neither ActionScript nor Flash are a type of coffee) in ActionScript. And, although I'm using Swiz on a Flex app currently, I don't see any reason off the top of my head why you couldn't use it in ActionScript-only projects too.

Here's a sample Beans class in ActionScript showing you how it's done:

package com.mydomain.myawesomeapp
{
  import org.swizframework.util.BeanLoader;

  import com.mydomain.myawesomeapp.SomeController;
  import com.mydomain.myawesomeapp.SomeService;

  public class Beans extends BeanLoader
  {
          // Simply instantiate and return an instance...
    public function get someController():SomeController {
      return new SomeController();
    }
    public function set messageController(o:*):void {};

              // ... or do some configuration beforehand
    public function get someService():SomeService {
      var someService:SomeService = new SomeService();
      someService.configureSomething("like", "totally", "cool");
      return someService;
    }
    public function set twitter(o:*):void {};

    public function Beans() {
      super();
    }
  }
}

So, basically, what we're doing is mimicking the methods in the ActionScript class that would have been generated from the MXML (or, more precisely, giving Swiz exactly what it's looking for in the BeanLoader, which are readwrite accessors; this is why we need the setter even though it doesn't do anything.)

And, finally, a gotcha that I find myself falling into: Remember to make anything you're going to [Autowire] or [Mediate] public. This means the properties that will receive the class instances and the event handlers. Since you'll be used to automatically making these private, take extra care!

In closing

Swiz is a lovely, lightweight framework that I'm really enjoying working with. It also has a small but active community and some good developers behind it. Play around with it, why don't 'cha and let me know what you think of it in the comments!

Comments