When utilizing PureMVC Mediator’s, there are 2 ways I’ve seen people write them. The first way is to have the Mediator call methods on the View, passing data it retrieved from a Proxy. This can also be done from a Command as well. The second way is to actually give the Mediator/Command more responsibility of State management for a particular View, and call more than 1 method on it, doing a lot of code that’s often done in the View.
Both have the same problem: methods in the View that only PureMVC calls, yet exist for others to inadvertently use because they are public.
This is apparent when you’re in the View, and type in “this.”. In FlexBuilder, FDT, or FlashDevelop you’ll get a code hint with all the methods and properties you’re allowed to utilize. You often don’t want the PureMVC functions because only PureMVC Mediator’s will be calling those. Worse, since these functions have to be public for Mediator’s to access them, other View’s and classes can use these functions in inadvertently as well.
It’s a minor problem when it’s just you working on the code and you ignore them. If you work with a team, are handing off the code to others, or just have a LOT of View’s, namespaces can help ensure it doesn’t become a bigger problem for others who don’t know what you do by providing a better API.
For example, in one PureMVC application I have, I utilize a namespace specifically for PureMVC to use. That way, only he uses it. Since it’s called “puremvc_internal”, it’s pretty obvious that it’s for PureMVC to use vs. “public” meaning anyone can.
Here’s a traditional Mediator making a call on its View component:
case ApplicationFacade.SAVE_POWER_FILE_AS_SUCCESS: var savePowerFileAsProxy:SavePowerFileAsProxy = facade.retrieveProxy(SavePowerFileAsProxy.NAME) as SavePowerFileAsProxy; mainView.onSavePowerFileAsSuccess(savePowerFileAsProxy.powerFile); break;
And here’s the method the View is exposing specifically for this purpose:
public function onSavePowerFileAsSuccess(powerFile:PowerFileVO):void { removeCreateWindow(); openPowerWindow(powerFile); }
Being public, both the View itself, and others can access this method even though you most likely don’t want anyone except PureMVC accessing it. Creating a PureMVC specific namespace, you can not only ensure this, but also document who the method is for.
Four steps, ready?
First, create a namespace, and save it like any other class:
package com.jxl.powerz.puremvc { public namespace puremvc_internal = "https://jessewarden.com/dougmccunehasnicetatas/2009/puremvc/"; }
Second, use this namespace in your Mediator/Command class:
import com.jxl.powerz.puremvc.puremvc_internal; use namespace puremvc_internal; public class MainViewMediator extends Mediator
Third, call the method using the PureMVC namespace instead of the public one:
case ApplicationFacade.SAVE_POWER_FILE_AS_SUCCESS: var savePowerFileAsProxy:SavePowerFileAsProxy = facade.retrieveProxy(SavePowerFileAsProxy.NAME) as SavePowerFileAsProxy; mainView.puremvc_internal::onSavePowerFileAsSuccess(savePowerFileAsProxy.powerFile); break;
Finally, define the method using the PureMVC namespace instead of the public one:
import com.jxl.powerz.puremvc.puremvc_internal; use namespace puremvc_internal; puremvc_internal function onSavePowerFileAsSuccess(powerFile:PowerFileVO):void { removeCreateWindow(); openPowerWindow(powerFile); }
You can also utilize this technique using Cairngorm and the Universal Mind Cairngorm Extensions. Just modify the Callbacks.as file to call the resultHandler and faultHandler functions in the correct namespace, and you should be good to go.
Hi Jesse,
Cool tip, but I’m not sure that I fully understand the need to do such a thing.
The great thing about PureMVC, with regards to it’s view tier, is that you can write clean, self-contained, framework-independent view components.
This allows view components to be used across projects, and with alternative frameworks.
Transforming an API into a pseudo-private interface doesn’t seem like a good idea to me. Necessary perhaps for frameworks themselves, but not for UI/View components.
I might just be a little unclear on exactly where this would be useful.
Interesting nevertheless. Cheers!
I disagree. With PureMVC, you’re assuming your View’s have an API to accept data. Not all expose public methods with the sole purpose of getting data through a success method, or some sort of failure. For example, the List control has a dataProvider setter, but no “onDataProviderSuccess” or “onDataProviderFailed” for example.
View’s that are getting data from PureMVC are explicitly coded to have Mediator’s (or Commands) call methods on them, usually with data. The rest are normal API methods, such as selectedIndex, which I agree does not need a puremvc_internal namespace.
Secondly, I don’t use View’s across projects. Every project I’ve been on has been so different, the only code I’ve been able to re-use is library code or components, such as as3corelib, or some extensions to the Flex framework.
Third, if you’re going to use PureMVC, then use it. I fail to see any value in creating View’s that’d be used in both a PureMVC and/or Swiz and/or Mate project. The frameworks are different. Even if I did write a clean seperation, again, the proejct is so business specific, I fail to see how I could re-use View’s since there is no way in heck Client A would let me use code for Client B. If I were still working for Client A, I wouldn’t switch from PureMVC to Mate; most clients I’ve been with either have policy’s for the big ones on what they use, or general rules for the smaller ones.
…as anything with frameworks, it’s all subjective based on what type of work you do, what clients, who do you work with, what your deadlines are, etc. So, there really aren’t any right or wrong answers. That said, I know 2 guys who immediately thought this was useful (we were kind of un-sober though…), so perhaps they or others can chime in and describe differently than I can.
Agree with the approach – we got really hooked on namespaces for this exact thing in AFCS, where there are some cross-package “friend” classes, but didn’t want to expose public methods to let them talk. Actually hit a problem last week where a method that should have been namespaced was left public, and someone used it in a totally unexpected (or supported) way. A little syntax sugar can help folks learn your codebase. It’s definitely more useful for frameworks than for apps, but at a certain point (with enough team members), your app is a framework anyhow.
Nigel: “at a certain point (..), your app is a framework anyhow” – Nicely put!
Jesse: “View’s that are getting data from PureMVC are explicitly coded to have Mediator’s (or Commands) call methods on them, usually with data. The rest are normal API methods, such as selectedIndex, which I agree does not need a puremvc_internal namespace.”
I disagree. I see no distinction between “normal API methods” and the methods that you propose be semi-hidden. Why is selectedIndex “normal” and onSavePowerFileAsSuccess special? I think this is the bit that I’m just not getting :)
“it’s all subjective based on what type of work you do, what clients, who do you work with, what your deadlines are, etc. So, there really aren’t any right or wrong answers.”
I agree with this sentiment of course. But some things are worth debating. I constantly re-evaluate how I approach application design in an effort to discover the best possible way to deal with Separation of Concerns. I suppose I focus less on how such things affect development when working in a team.
“..the only code I’ve been able to re-use is library code or components, such as as3corelib, or some extensions to the Flex framework”
Yes, and imagine how much less re-usable those components would be if they were dependent on a specific architectural framework. I try to approach my view components in the same light; I build my view components as if they were indeed “extensions to the Flex framework”, and I try to keep the truly project-specific code small and separate. It is possible that if you approached view components differently you would be able to reuse them more often.
Here’s my current approach:
I break project-specific components apart into smaller, re-usable components. These components have no project or framework dependencies, they are simple: they expose an API and dispatch events (think: button, log-in form, cover-flow component, pageable list).
These simple components get composed back into a project-specific (complex) component. The complex component is obviously not re-usable. But it should be quite simple and light: an API, some composition, a little configuration, some styling, and some custom events. If it can’t be used across multiple projects, there is at least the potential for it to be used across the same project in different contexts.
As far as I’m concerned, a Mediator for such a component is just a plain old collaborator – it manipulates the view component via that component’s API (as any other collaborating component should be able to do) and it listens for events. It’s sole purpose is to de-couple the view from the application, so why would I want go and couple the view to it (and hence back to the application)?
“Not all expose public methods with the sole purpose of getting data through a success method, or some sort of failure. For example, the List control has a dataProvider setter, but no “onDataProviderSuccess†or “onDataProviderFailed†for example”
I’m afraid I don’t understand what you mean here. This could be the crux of the matter. Could you elaborate?
That’s good you see no distinction, but at the end of the day, you have to get something done. OOP is a great goal to strive for, but it’s inversely proportional to your productivity. The happy medium I’ve found is defining success/failure methods on a View, and letting it handle the rest.
I’m with you man, I learn everyday and question everything.
I don’t have to imagine. Yes, the code is very unusable in other frameworks, I agree. I’ve done that knowingly so that I can get code done faster. We/the client/the team already agreed on using PureMVC/Cairngorm/whatever, and are moving forward from there, spending no time solving a problem that isn’t a problem to solve; aka, re-usable in other frameworks.
We basically work in the same way at a high level; details are just different.
Adding namespaces merely confirms you are using a framework, and helps delineate the API for others to see where just like mx_internal let’s you know where the Flex SDK needs cross-class access in a similar vein: needs access internally, but not a public API method for others to consume.
Again, I use puremvc_internal namespaces not to couple my View’s to my PureMVC Mediator’s, but rather clearly define the relationship. This relationship was planned, and isn’t going away. While it’d be nice to think I could still write the methods as encapsulated public methods, sure, some probably will be and could be utilized in other parts of the app, or even a new app. … but probably not.
My point with the List is that you have to create a wrapper class around it to populate it with data from PureMVC so you can either populate it with data via dataProvider, or show a GUI over top of it when things fail. Otherwise, you’ll have to have the Mediator for the List do that which isn’t ideal because you don’t want Mediator’s handling GUI state since that’s what the View’s should be doing for their own, internal state. Since the List component doesn’t come predefined with “onIGotYourDataProviderReadyToGo” and “onIFailedToGetYourDataSorry”, you have to write that yourself. So, writing List controls during a project, to me, seems like a waste of time unless the sole purpose of your project is to create components. Following YAGNI, you’ll probably only need 30% of the features a List control offers anyway, so why spend time making it all OOP-i-fied just to put another layer on top that masks all the stuff you aren’t using, yet spend precious dev time building?
To say it another way, the List was created to be used as a base component for creating lists of data that are interactive. Like you, they wanted him to be utilized in a lot of contexts, and they succeeded. The primary mechanism for populating it with data is the dataProvider setter. This is very flexible; you can utilize an Array, an ICollectionView, an XMLList, or even an arbitrary piece of data.
The downside is that you cannot please all the people all the time. List’s dataProvider is a perfect example of trying too hard to be pure OOP, and sacrificing other areas. 95% of the Flex applications that I see that are actually going into production use ArrayCollection’s for all List controls. There are many detrimental costs for this, 1 being the lack of smooth scrolling, an oft requested feature of the List control. Had they spent more time finishing their preliminary attempt at it vs. spending time supporting all those interfaces for other data formats most people don’t use, the List control would end up being more useful for most people.
And that is the key: most useful for the most amount of people. That’s pragmatism, the ability to get things done that are useful.
So, yes, it’d be nice if my application specific View’s that are intended to be used with a PureMVC Mediator / Cairngorm Callback were written as encapsulated as possible; to never actually know that’s what they are written for.
… but I know which framework I’m using, I know which API methods were specifically coded to support it, and (mostly) where the View’s I’m creating are going to be used. OOP is nice to try for, but I always put pragmatism first.
Timely post, i was just considering this exact idea for a relatively large puremvc app I’m currently working on. I didn’t go with it because I felt, as mentioned already, that it ties the framework too close to the view. Instead I opted for getters/setters that modified the state in someway (leaning more towards a dependency injection approach)
Also, I could be misunderstanding what you’re doing, but I’m going to have to disagree with you again on the overall idea of using onSuccess/onFailed type methods in the view anyway (like old-school ARP). In this case, the view has some sort of knowledge of services used in the app.
…with that being said, I also agree with the idea that it can be a huge waste of time to over-OOP everything.
Oh snap, FlashApe is digging Dependency Injection!
*ahem* I agree, it does tie yourself a lot with the framework. I do it because… why? I’m using the framework. I’m not embarrassed by it, but I feel like PureMVC in particular has no clearly defined mesh points, hence things like FlexMVCS popping up.
Regarding onSuccess/onFailed, we agree to disagree. In my consulting, (check it out, another 90% quote) 90% of the applications I see do not handle errors. Whether Mate, Cairngorm, PureMVC… whatever, they usually just log the errors. I’m building an AIR app, and HAVE to handle them for users to understand why something didn’t work. Every user gesture I’m doing can fail (saving files, opening files, etc.). That and I got into the habit of doing it coming from the UM Extensions to Cairngorm.
My View doesn’t have any knowledge of services; it just knows it’s possible to have a data object thrown into it, or some failure via 2 public methods… which PureMVC is the most likely (read only) dude ever who’s going to call them. Unlike a List control, which ALWAYS assumes success via his dataProvider public setter, mine can say, “Hey man… we tried to get your dataProvider, but uh… the Hulk smashed it. Yeah, sorry about that. Please click ‘OK’ to accept your fate.”
Well, not handling errors is definitely not an option, it’s just weak to leave your app in a broken state or leave the user guessing.
What I’m saying is, to use your example about the dataProvider setter, I’d check there for valid data and proceed accordingly (in your case pop open the ‘hulk smash’ message). A small difference but to me seems a little cleaner.
In may cases, I let the mediator itself inspect the data, and if it needs to, pop open the message window (actually, it will shoot off a separate notification for a window manager to handle, but you know what i mean).
Aha, I think we’re all on the same page at the end of the day.
Continuing with the List example. I would do the same thing: Extend/compose List and add public methods to handle success/failure. I just wouldn’t try hide these methods with namespaces. I’ve had to switch Frameworks halfway through a project before, and I was very thankful that nothing in my views tied them to PureMVC. The namespace idea is, nevertheless, interesting.
“I’m not embarrassed by it, but I feel like PureMVC in particular has no clearly defined mesh points, hence things like FlexMVCS popping up.”
Heh, I would suggest that things like FlexMVCS pop up because PureMVC is an awesome idea that is, unfortunately, over-engineered and poorly implemented. But that would probably get me in trouble ;)
Note: I don’t criticise PureMVC, as many have done, without trying my hand at solving the problems I have with it. RobotLegs AS3 is my attempt at a “PureMVC” with Dependency Injection in place of the Model/Service Locator patterns (“Registry”). DI makes classes more reusable and easier to unit-test, but more importantly, relieves developers from the Casting headache inherent in PureMVC-based apps. If anyone is interested: http://shaun.boyblack.co.za/blog/2009/04/16/robotlegs-an-as3-mvcs-framework-for-flash-and-flex-applications-inspired-by-puremvc/
Great demo. Love the idea of assisting developers by only seeing the methods on intellisense that they need to see. I created a new demo loosely based on your example. It is not a full PureMVC example, but hints at it. http://www.blog.rivello.org/?p=422
wow shaun, that just may be exactly what I have been looking for :)
Samuel: Cool, hadn’t thought of that. That’s pretty handy actually!
Rich: I hope so!
I tend to agree with Shaun’s original post.
Saying,”I use puremvc_internal namespaces not to couple my View’s to my PureMVC Mediator’s, but rather clearly define the relationship. This relationship was planned, and isn’t going away.” is contradictory to me because a relationship that is planned and isn’t going away is the definition of tightly coupled.
I don’t think that your approach is wrong, but you no longer have true Mediators. As long as you are making your views framework aware, why not take it a step further and do away with the Mediators altogether?
“Tight coupling” has a negative connotation, one that implies the developer didn’t know it was tightly coupled. I know it is, I know where I’m breaking the OOP rules, and recognize the ramifications of doing so. I’m gaining productivity over increased time building an API for the sake of following OOP Purism for little to no gain.
Like I said in the past, the Mediator for PureMVC is great. It’s the most popular interpretation/implementation of the P in MVP I’ve seen for Flex/Flash. The majority of my View’s now just retain state, and the code for them is significantly reduced (sometimes totally) to just handle state and user interactions. No additional application/business logic, no “simple Mediator” type code; strictly showing VO’s, changing state, and responding to user interactions & data changes. That’s just awesome. Anything that can reduce the amount of code in my View’s, ride on top to handle being the liaison to the service layer and sometimes other View concerns just “feels” great.
Again, it all comes down to being an OOP Purist and refusing to let your View’s know that they have overloads that really control their destiny. If that’s your stance, yes, this technique is not useful, and offensive. To the Pragmatists who use PureMVC, Cairngorm, or any other framework, it’s a helpful way to leverage to an AS3 feature.