Thursday, June 14, 2012

PureMVC, amendments to best practices

I recently inherited a very well written PureMVC project, following the recommended best practices to the letter - and it gave me a lot of headaches. So I'm making some amendments.

First let me give some context. This project was a video player project, the client orginally had their own in house video player, (ie NetStream based), but are now moving to a service for their videos. They wanted to keep the UI the same, just switch out the video player.

This is perfect, this is exactly what an MVC framework should be about, I could keep the view part and just replace the video player and model to where the data was coming from.

While trying to decode the source code, I started by just seeing if I could instantiate just one of the mediators, to see what the view looked like. Compiler Error.

Turns out, that the mediator had referenes to the ApplicationFacade to get the notification names. Well that means that the entire ApplicationFacade had to be compiled. That meant that all of the registered commands, mediators and proxies, had to be compiled. So somewhere deep within the framework, I was missing a bunch of classes.

So my first step was to comment out all of the proxies and commands, as I only wanted the views. Still no joy. Not wanting to remap all of the notifcation declarations, I made a MediatorNameConstants. This file had a list of all of the mediator names, but without references to the mediator classes. I updated all of the NAME values of all of the mediators to point to this file as well as all of the references.

Now when I wanted a mediator, I only needed that mediator and the facade, not all of the framework.

As I worked through the code and added stuff back in here is the list of best practices regarding PureMVC that I came up with.

  • While tedious, keep all mediator and proxy names in a separate constants file.
    I did this so any mediators or proxies that were referenced in mediators, weren't required to be compiled in, only their names.
  • Then within a mediator, command, or proxy, instead of creating local variables for other mediators or proxies, declare them as explicit getters
    Like this:
    public function get myProxy():IMyProxy { return facade.retrieveProxy(MyProxyConstants.NAME) as IMyProxy) }

    That way the class can be overwritten for extension and testing. This would also allow for some dependancy injection, if so desired.
  • Make the proxies into interfaces, at least the major ones, like ApplicationProxy or ConfiguationProxy.
    Now there is a theory that says if you only have one, than an interface isn't needed, and I agree. Although I think for something that is major and widespread like the two mentioned above, that an interface of one does make sense.

If these things were in place in my inherited project, it would have saved me days worth of debugging and code searching efforts.