Thursday, February 5, 2009

Pure MVC - the good, the bad and the ugly

I just finished my first Flash game built with PureMVC for ActionScript3.0 (sorry, it's a work project and not released yet).

I'm going to share some bad experiences and some good experiences about it. Let's start with the bad ones, because they're most fun to read.

As Tony says, PureMVC makes you write quite a bit of boilerplate code in the beginning. I expected that anyway, sice I had just learned the system. But it's true, it is far from a pleasant prospect to imagine having to write it again. If I will use it in the future, I will most probably copy the entire project and start changing, or even create a 'blank setup', with all the initialization code ready for ordinary applications.

One of the complications is that when sending messages through the facade (a similar publish /subscribe mechanism to Cairngorm Events), any command and any mediator can respond and act upon them (proxies can't). This makes it difficult to know who and what is doing at certain stages of the application, especially when the project is getting bigger. There is no central point to see who is doing the work at "APPLICATION_INIT", for instance, because any and all mediators can listen to this event, and that signaling code is in the particular classes (through the listNotificationInterests method). I found myself using Ctrl+H in Eclipse (which searches through all project files) more often than should be the case for a good framework (or for a programmer with good memory - I should eat more fish).

A subsequent, unforseen oddity comes to life when linking to other mediators in a mediator. I wonder if this verges on bad practice, but on a few occasions I needed to link mediators directly, and in one instance I realised I had circular referencing between two mediators. This would generally be no particular problem, but the way PureMVC recommends registering Mediators is not compatible with such referencing. Namely, you register them in sequence in the top-level ApplicationMediator, as part of an application initializing command. This means that the circular referencing will break, because the second mediator will not have been created yet when we attempt to retrieve it in the constructor of the first.
My way around this was to move the mediators registration code at the end of the application initialization and then to send a "MEDIATORS_REGISTERED" message, which could be listened by all mediators who may be in danger of circular linkage. This had the nice effect of bloating almost all my mediators' class code.

Also, when coding commands which need to wait for view components to finish animating, it becomes cumbersome when other entities (commands or mediators) need to act when that animation finishess. For instance, a card placeholder needs to change colour when the card reaches it. You don't want to lose state in the command by just registering a new command to execute at the end of the animation, because you need to use previously obtained information. You basically have to dispatch two 'messages' in the view component's mediator -> one through the facade (eg. "CARD_RECHED_DESTINATION"), for the interested mediators, and the other, a regular Flash event (for instance Event.COMPLETE). The command will then respond to the Flash event and continue its functionality. (Alternatively you can dispatch the facade message in the waiting command; but what if that animation is at other times triggered by different commands as well? You still need the message to be sent out...).

Now moving on to good things.

What's cool is that once you've gone through the initial scaffolding, it is very easy to add bits of functionality in the application. That is, if you leverage copy-paste, because something like _cardsMediator = CardsMediator(facade.retrieveMediator(CardsMediator.NAME)); is not fun to write 5-10 times per class. Also, the linking between visual components becomes a breeze, because most of the times they will respond to existing notifications.

Also, if I am to think about my application generally, I feel it is very solid, robust. I have had very few bugs caused by my misusing the framework, so from this point of view PureMVC does not stand in your way.

Will post back with more insights.

No comments: