Why I Switched from PureMVC to Mate…
This article is written with the assumption that the reader has at least some familiarity with the Flex MVC frameworks, PureMVC and Mate. However, knowledge of these systems is not required.
I Love You, PureMVC
For about a year now, I have used PureMVC exclusively for my Flex projects. I chose the framework because I could grasp all of the concepts and really understand the vision. Mediators could deliver on separating the views from the rest of the applications. Proxies could deliver models without having Singletons all over. Commands, well, we all know those. Combine it all under the ApplicationFacade, and everything made sense. I was sold.
Until recently…
PureMVC, Uh, I Think It’s Time We See Other Frameworks
In recent months, our relationship has hit the rocks. Over time, I’d completely ceased using Proxies. In earlier projects, I littered all of my code with retrieveProxy() calls. As I gained more experience, I tried to keep those calls within Mediators and Commands only. It took some work, but I learned something: Proxies don’t give me anything. So, I have skipped the unnecessary boilerplate and I just use the Model Locator pattern from Cairngorm, which is much simpler.
Commands still made me happy, but it was bugging me that I was calling sendNotification() from my client code. I tried to eliminate that. I pushed those calls into the Mediators and fired regular Flash events to get them initiated from those Mediators. To accomodate that, I began writing more Mediators. So now, I would add classes like DialogMediator, SoundFXMediator, and so on. Depending on how you architect your applications, you may or may not like this idea. I think they make sense in the context, but I was starting to lose my love for coding due to all the overhead boilerplate needed for each one.
“Well, at least my Mediators are powerful,” I thought. The growing number of them, anyway. Admittedly, I still have an affinity for them. You can perform such a wide range of functionality with them. Fire off a notification and you can have your Mediator enable and disable fields, reposition components, and do just about anything else.
Ummm, well, OK, one problem is that my mediators started having too much logic. It’s just too easy to perform all of my view manipulations in the Mediator, thereby making the View too dumb to reuse somewhere else. For example, if the status of the components had to be managed based on some model state, I found that the code for that would invariably all end up in the Mediator, not the view. If I were to pull the view out of my PureMVC application, I’d have to rewrite all of that code!
So, with me using only two-thirds of the framework, getting frusterated with the boilerplate code, and questioning if I’m putting my code in the right places, I wanted to see if there was something better out there.
Cairngorm? Hell no. Cairngorm is a piece of crap. Quote me on that. Commands…whoopeee dooo!
A retroactive work friend turned me on to Mate (though he hadn’t used it yet), so I took a look at it. I loved it.
This article is about my transition to the Flex Mate MVC framework.
Why I Switched To Mate
What attracted me to Mate were some key differences with PureMVC:
- Less boilerplate would be needed.
- Standard Flash events could be used for communication instead of custom classes like Notification.
- Event Maps offered a facility that replaces a lot of your need to write Commands and simplifies server communications.
I’ll go over some of these concepts in the next few sections. Hopefully, you’ll be as excited about Mate as I am.
Proxies: Migrating to Mate Models
Yeah, this was really easy. I didn’t have to do nothin’ since I wasn’t using Proxies anymore anyway. :-)
Mate doesn’t use any framework-specific classes for Models. So, you’re free to specify your models however you wish: Singleton model, static model, whatever. Models are models with no boilerplate needed and no guilt for not using it. W00t!
Commands: Almost Exactly The Same (If You Still Need Them)
At the very least, you’ll find that Commands are practically the same between PureMVC and Mate. However, it’s the small differences which make Mate Commands such an attractive choice.
First, the Mate Command doesn’t need to extend a class like SimpleCommand. Any class can serve as a command so long as it implements a method with the signature execute(event:Event):void. This offers a few benefits:
- You can test Commands using FlexUnit or DPuint without being forced to use the MVC framework as well.
- Your Command has more flexibility in what you want it to subclass.
- Less boilerplate if you’re writing it by hand.
Another thing you’ll notice is that you really don’t need to write so many Commands anymore. Instead of responding to an event by firing a Command, you actually have the ability to do things like send HTTP requests and invoke methods directly. Now, you might want to write your Command class anyway — and that’s fine — but the option to push more implementation into Event Maps will be there and, especially for smaller apps, you may find yourself doing this quite a lot and it’s a far better way to do things than PureMVC.
Event Maps are a big topic when it comes to replacing Mediators.
Mediators: Everything You Know Is Wrong
There is no question that the hardest thing I had to do to commit to Mate was moving from PureMVC Mediators to Mate’s Injectors. Mediators are incredibly flexible and a big reason why I’m a PureMVC fan. Here’s what they give you:
- An extremely generic way for a view to handle notifications.
- A way to control a set of view components without even having to composite them.
- Separation of UI and Command code when responding to a single notification.
I’ve used Mediators for some of the following tasks:
- Controlling component states.
- Populating controls without binding. (This can be faster in many situations.)
- Non-UI actions such as playing sounds and popping up dialogs.
What can’t they do??
The first you notice with Mate is that it doesn’t have the concept of a Mediator, but they it does have Injectors. While far less broad in what they can do, I do believe Injectors offer a more solid design pattern than the way I’ve been using (or misusing) Mediators.
Injectors can be thought of as data bindings, except they work with ALL views of a type. The Injector always modifies the targetKey for every instance of your view target. This can be good and bad. If you want all your views to react the same to model changes, it’s great. If you think using an Injector on a Label is a good idea, you’re mistaken. If you did this, all of your Labels would change when an injection happens!
However, while this jumped out in my mind as a possible problem, I realized that PureMVC does the same thing. For example, let’s say you have a component that has its own Mediator. Now, if you wanted multiples of that component, you’d create more components and call registerMediator() multiple times for each one. It sounds right, anyway.
There’s a problem, though. In PureMVC, removeMediator() takes a constant, namely that Mediator’s NAME constant. You can’t remove an individual Mediator! In effect, Mediators are singletons, whether you’ve realized it yet or not. You’re only recourse is to subclass the Mediators, name them with different constants, and do the same with the components you want them to control.
Injectors behave the same way. This explains why all of the sample programs available for Mate never have Application-level components. They always put the entire contents of an application in their own view component (such as Canvas). The reason for this is so that the Injectors can target the composite views and remove any ambiguity. It’s also just better design.
So, you have to do the same thing for Mate as well as PureMVC. But, the difference would be that you don’t have to mess with copying the Mediators. It’s much easier to replicate the behavior in your Event Maps.
Now, let’s go through all of my typical uses for a Mediator and see what the Mate equivalent is.
Enabling/Disabling Fields
In PureMVC, we can let a Mediator handle enabling, disabling, and a whole host of other operations on components. This is all fine and dandy, but it also forces us to send pretty heavy notifications when we want this behavior to fire.
In Mate, we can use either data binding or Injectors to take care of this. Data binding is easy, just bind your model to your component just like you learned in Flex 101. One problem, though, is that this isn’t “pure.” The view would have specific knowledge of the Model if I did something like:
<mx:Button label="Play" enabled="{MusicModel.getInstance().isStopped}" />
MusicModel would now be tightly coupled to my play button. Erich Gamma would roll over in his grave if he saw you do that. Good thing he’s alive.
The Injector approach, on the other hand, would be accomplished by adding to the Event Map:
<Injectors target="{MP3Panel}">
<PropertyInjector targetKey="mp3Playing" sourceTarget="{MusicModel.getInstance()}"
sourceKey="isStopped" />
</Injectors>
Note that this code is far cleaner, if a little less intuitive. MP3Panel is kept completely oblivious of the full application it’s being used in. It is loosely coupled from MusicModel. It can easily be pulled out later or used in a different way somewhere else, whether Mate is used or not.
It’s not as simple as a PureMVC Mediator, sure. You have to make sure isStopped is bindable or the Injector won’t work. You also have to learn to add specific view logic into that mp3Playing setter rather than lump it in the Mediator’s handleNotifications() method with the rest of your code.
This comes with an important win, though: It’s correct. By keeping that enabling logic in the Mediator, we lose it when we reuse the component anywhere else. That is, we’ve put UI logic in the Mediator, leaving the component too dumb to ever be separated from its PureMVC master. It wouldn’t know how to manage its own components without the Mediator!
Yes, I didn’t have to use PureMVC this way in the first place. I could have written it right the first time. The point may be that Mate enforces better programming discipline inherently, whereas PureMVC opens you up for abuse. Not the fault of PureMVC, but it can be argued that it’s an invitation to act this way. :-)
Populating Controls Without Using Binding
This is the easiest aspect to crossover to Mate. Injectors aren’t binding! While they do require the model fields to be Bindable, the Injector is doing a copy. Therefore, you never have to bind. :-)
Done.
Popping Up Dialogs and Playing Sounds
I love doing these operations with Mediators. Fire off a notification and get popups and sounds and what have you. I use Mediators because, despite the fact it’s not wrapping a “view” per se, this is UI we’re dealing with even if it’s not visual. So I use Mediators.
The bad news is that, unless we want to do some arcane programming, we can’t do this the same way with Mate.
The good news is that we can replicate this in a couple of ways. First of all, we can simply use Commands. In Mate, just like in other frameworks, Command objects cache. This means they can be stateful. (There is also an option to disallow caching, but we wouldn’t use that here.) Hence, we can use Commands just like Mediators.
That’s one way.
The second way is to use controllers. Here’s how we could do it in the Event Map:
<EventHandlers type="initSound">
<InlineInvoker method="{SoundSystem.getInstance().init}" />
</EventHandlers>
<EventHandlers type=”playSound”>
<InlineInvoker method=”{SoundSystem.getInstance().playSound}”
arguments=”{[event.soundID]}” />
</EventHandlers>
Essentially, we’re turning the events into method calls, just like a Mediator would have added. Semantically, we’re using controllers instead of Medicators. Notice we use InlineInvoker, because Mate would create two distinct models if we used MethodInvoker. This is important to remember. If you only needed a single controller for one Event Map, you could safely use MethodInvoker for this.
A small win that we get is that we no longer have to deal with the switch/case soup that Mediators impose on us. I hate forgetting break statements.
Event Maps: A First-Class Service Locator!
Mate also provides a really slick facility, akin to Cairngorm’s Service Locator, but far better! In Cairngorm, you would put all of your application’s service calls into one MXML. To call them, you pull them out from Commands, set up some callbacks, and go.
It was far less convenient if those calls had parameters you needed to substitute, though.
In Mate, you can do the same thing, but you can inline the result handlers and, better yet, substituting parameters is intuitive and easy! Check out the Services tags for usage. It will ease the burden of writing so many Commands!
Loves it.
Saving Time On Smaller Applications
Another of Mate’s great benefits is how much faster it is to write smaller applications. Let me tell you a story.
One of my favorite hobbies is competitive Scrabble. Over the span of a week some time ago, I wrote a set of applications that helped me train to be a better Scrabble player. One application let you give it a set of letters and it told you all the valid Scrabble words you could make from them. A second application tested you on it. Finally, a third application trained you on so-called “Bingo Stems,” which are a way to help you learn and memorize the most common 7-letter bingo words. (That one’s a secret!)
As a disciplined developer, I was bugged by the fact that I was writing these short little applications without using PureMVC! THE HORROR! Why wasn’t I using it? I was just too lazy to write all the boilerplate needed to write a “maintainable” application. The apps didn’t need to be maintainable. They would be done in a day and I wasn’t planning on touching them again, ever.
And it would have taken a lot longer to finish them. I needed them right away!
So, what’s the problem? The problem is that I’m all but admitting that PureMVC doesn’t necessarily make my job any easier. In fact, it makes me work harder! The only reason I use it is to make a more flexible application that can be maintained and expanded later.
But, it doesn’t make programming it any easier. And do I really want a framework where many times I would opt not to even bother using it?
Mate is different. I would have actually used Mate to write these apps without any hesitancy. Using the Services tags, I could have written my HTTP calls faster. The events that I dispatched (in the absence of PureMVC) are almost exactly equivalent to what Mate uses. I would have gotten all the benefits of the MVC framework without any of the extra mess I was trying to avoid.
In short, it would have made my work easier.
In fact, I can probably go back and refactor them to use Mate pretty easily. Maybe I will. Any Scrabble fans out there? :-)
Conclusions
I hope that I have demonstrated to PureMVC developers out there that there’s a better way to do things. Don’t be scared. You’re thinking patterns may need to change just a tad, but it only took me a couple of days to understand it — and I do believe they are better patterns of thinking.
You can have an MVC framework that makes your life easier, no matter what size the application you are building. You can get your work done faster with no sacrifices to the Almighty Design Gods ™. And, as much as I hate to admit, Mate is actually pretty fun to use, too. :-)
Treat yourself and take a look at Mate.
Comments are currently closed.