Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: [1]
Print
Author Topic: Role of StageMediator?  (Read 15820 times)
jlahr
Jr. Member
**
Posts: 19


View Profile Email
« on: December 17, 2009, 12:10:17 »

Should mediators (and by extension, the view components that they instantiate) be crated by the StageMediator?

T
Logged
adrianw
Newbie
*
Posts: 8


View Profile Email
« Reply #1 on: December 18, 2009, 05:17:39 »

I think they could, but personally I've created command for registering mediator for specified viewComponent. I've also created VO that holds reference to MediatorClass and viewComponent instance. Here's the code (I've omitted import statements for clarity):

RegisterMediatorForComponent.as
:
public class RegisterMediatorForComponentCommand extends SimpleCommand implements ICommand
{
  public function RegisterMediatorForComponentCommand()
  {
    super();
  }

  override public function execute(notification:INotification):void
  {
    var registerMediatorVO:RegisterMediatorVO = notification.getBody() as RegisterMediatorVO;
    if(registerMediatorVO)
    {
      var MediatorClass:Class = registerMediatorVO.MediatorClass;
      var viewComponent:UIComponent = registerMediatorVO.viewComponent;

      if(MediatorClass && viewComponent)
      {
        var mediatorName:String = MediatorClass.NAME as String;
        if(mediatorName && !facade.hasMediator(mediatorName))
        {
           try
           {
             var mediator:IMediator = new MediatorClass(viewComponent) as IMediator;
             if(mediator)
             {
               facade.registerMediator(mediator);
             }
           }
           catch(e:ArgumentError)
           {
             trace("RegisterMediatorForComponentCommand Argument Error");
           }
         }
       }
     }
  }
}

RegisterMediatorVO.as
:
public class RegisterMediatorVO
{
  public var MediatorClass:Class;
  public var viewComponent:UIComponent;

  public function RegisterMediatorVO(MediatorClass:Class, viewComponent:UIComponent)
  {
    this.MediatorClass = MediatorClass;
    this.viewComponent = viewComponent;
  }
}

Sample usage:
:
var registerMediatorVO:RegisterMediatorVO = new RegisterMediatorVO(LoginFormMediator, loginForm);
sendNotification(AppNotifications.REGISTER_MEDIATOR_FOR_COMPONENT, registerMediatorVO);

I Hope this helps.
« Last Edit: December 18, 2009, 08:01:44 by puremvc » Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #2 on: December 18, 2009, 08:19:49 »

This is a nice implementation, Adrian. I would only suggest the viewComponent be cast further down to DisplayObject, which would make it usable in Flash as well as Flex.

The really good thing about this command is that it doesn't need to know (i.e. import) the component or its mediator class.

-=Cliff>
Logged
adrianw
Newbie
*
Posts: 8


View Profile Email
« Reply #3 on: December 18, 2009, 10:03:48 »

Thanks Cliff :)

You're right, my implementation only fits Flex, for Flash project it is necessary to change viewComponent's type to DisplayObject.
Logged
sideDoor
Full Member
***
Posts: 25


View Profile Email
« Reply #4 on: April 16, 2010, 07:20:14 »

Given that pretty much all actors in PureMVC have access to the facade, isn't this much simpler?

:
facade.registerMediator(new IndexMediator(indexView);

I mean, you need access to both the view and mediator to instantiate your VO, so why not just skip that biz and register the mediator directly with the facade?

Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #5 on: April 18, 2010, 04:42:03 »

Writing the entire app as one class might ultimately seem simpler, but in OOP, we give classes Roles, Responsibilities and Collaborations. This generally leads to more classes which makes everyone throw up their hands and sigh about the vast amount of work necessary to write an OOP application. Such is life.

The Facade doesn't have the responsibility of managing the view hierarchy. Its defined role is to expose access to the other core actors in one place. It necessarily must register at least one Command for starting up the app, but then we leave the preparation of the model and view to commands.

In a super simple app, it might make no difference. However, as you start writing more complex apps, particularly with the StateMachine, you find that you don't always register all your mediators at once. So overriding initializeView and registering the Mediators there doesn't give you the control over the timing of registrations. You often have deferred registration of Mediators, where the view components aren't created until later in runtime.

If you were thinking you'd add tons of convenience methods to the Facade for doing this at any time, then you're taking the temptation to misuse the facade singleton. The reason so many people say 'singletons are bad' is because of what happens when you use them like this. They become these big bloated 'christmas tree' classes; decorated with tons of unrelated 'convenience methods'. That runs against the OOP premise. It overloads a class with responsibilities and collaborations that make its role fuzzy and therefore a target for even more 'where does this go' rush work.

It's a slippery slope and all that...
-=Cliff>
Logged
sideDoor
Full Member
***
Posts: 25


View Profile Email
« Reply #6 on: April 24, 2010, 12:52:05 »

Writing the entire app as one class might ultimately seem simple
Huh?

I'm not sure I made myself clear...

Somewhere in the middle of Adrian's RegisterMediatorForComponentCommand Class, he has:

:
var mediator:IMediator = new MediatorClass(viewComponent) as IMediator;
if(mediator)
{
facade.registerMediator(mediator);
}

and to fire the RegisterMediatorForComponentCommand, he has to create a RegisterMediatorVO, pass in a mediator/view pair, then send a notification.

:
var registerMediatorVO:RegisterMediatorVO = new RegisterMediatorVO(LoginFormMediator, loginForm);
sendNotification(AppNotifications.REGISTER_MEDIATOR_FOR_COMPONENT, registerMediatorVO);

My point was:  From within ANY command you can just call this:

:
facade.registerMediator(new LoginFormMediator(loginForm);
..which, effectively, is what happens within his RegisterMediatorForComponentCommand.

Considering that to use the RegisterMediatorForComponentCommand you must ALREADY know the Mediator and View your want to create, why pass them through the RegisterMediatorForComponentCommand command to effectively accomplish the same thing as you would by calling facade.registerMediator() - the latter using only one line of code?  Why is the RegisterMediatorForComponentCommand approach more efficient?  I don't really see any decoupling here...just delayed instantiation.

Thanks!
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #7 on: April 24, 2010, 08:41:31 »

Sorry, I took:

why not just skip that biz and register the mediator directly with the facade?

...to mean you wanted to do the registration of the mediators in the Facade.

-=Cliff>
Logged
sideDoor
Full Member
***
Posts: 25


View Profile Email
« Reply #8 on: April 25, 2010, 12:43:25 »

Oh, cool, now I see...

Again, thanks for your time...

Do you agree, though?  Although I initially liked Adrian's approach, and I don't mean to be negatively critical, isn't the process outlined simply wrapping the facade.registerMediator() method in a few unnecessary Classes?

sd
Logged
jpwrunyan
Sr. Member
****
Posts: 84


View Profile WWW Email
« Reply #9 on: June 06, 2010, 05:25:07 »

Adrian's idea is cool because it actually cuts down on the number of classes needed.  In this case Command classes.  The only drawback I can see immediately is if, like me, you combine the model initialization with the view initialization in the same command.  That makes it a bit harder to simplify.

Probably for Adrian, his application development follows a different pattern.  One thing I don't like about notifications is that it is hard to keep track what to expect in the body.  I have to get people to write code comments describing what each notification that comes into handleNotification() or execute() has in its body and some people are less diligent than others.  His use of the VO here is very appealing.  It never occurred to me to extend VO usage beyond Proxy notifications... thanks Adrian!

Cliff and Adrian, what would you think if RegisterMediatorVO class had an additional parameter for an array of Proxy classes to create and register in RegisterMediatorForComponentCommand?

:
override public function execute(notification:INotification):void {
  var registerMediatorVO:RegisterMediatorVO = notification.getBody() as RegisterMediatorVO;
  for each (var proxyClass:Class in registerMediatorVO.proxies) {
    if (!facade.hasProxy(proxyClass.NAME)) {
      facade.registerProxy(new proxyClass());
    }
  }
 
  ... continue registering mediator, etc.

Something like this would probably cover most of my cases.  (note: my proxies get their data from servers, but if they need to be instantiated with data, could that not also be included in the VO?  is this too complex?)
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #10 on: June 08, 2010, 04:54:12 »

I see what you're driving at here, but I'm not sure it's worth the complexity.

Usually, a Proxy is pretty light and there usually aren't that many of them to register for a given app. I find that just registering them all to begin with (but not telling them to automatically fetch data) is a good way to ensure they're present and accounted for whenever needed. I don't see that delaying their instantiation until the mediator that needs them is registered has a lot of value.

But if you have a situation where it does make sense, then the above seems like it would work to me.

-=Cliff>
Logged
jpwrunyan
Sr. Member
****
Posts: 84


View Profile WWW Email
« Reply #11 on: June 09, 2010, 06:35:07 »

Usually, a Proxy is pretty light and there usually aren't that many of them to register for a given app. I find that just registering them all to begin with (but not telling them to automatically fetch data) is a good way to ensure they're present and accounted for whenever needed. I don't see that delaying their instantiation until the mediator that needs them is registered has a lot of value.

But if you have a situation where it does make sense, then the above seems like it would work to me.

Well, essentially, the situation is that my project manager is telling me to do it that way.  I can also see where he is coming from (ie: why would you instantiate a Proxy before it's needed?).  Until I read your response I had just been deferring to his wisdom (he's been on this project from the very start, unlike me).  I can reason with him, though.

Next, our application has a TON of proxies... at least 50 classes... perhaps up to 100 instantiated.  The amount and types of data retrieved from servers is also immense.  On a side note, I have been trying to figure out a way to modularize the application into MultiCore without success... then, in theory, I could have like a dozen core apps with just a few proxies each.  But for now, it is not the case.  Honestly, simplifying our model tier feels like fighting the Hydra with a butter knife, and with the same predictable results.

The only other reason I can come up with is that most of our proxies grab server data automatically upon onRegister().  But I suspect you would say that I should simply move that logic from onRegister() into a different method (call it retrieveData()) which is called when the proxy's data actually needs to be retrieved.  As it is, there are some situations where I have to do that anyway (eg polling).  But where would I call such a method?  From inside the Mediators that use those proxies?  If I try to do it from inside the RegisterMediatorForComponentCommand then I am back to square 1 (ie how do I know which proxies need their retrieveData() method called?).

Thanks for the response.  Sorry if I am straying a bit off topic!
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #12 on: June 15, 2010, 06:17:53 »

why would you instantiate a Proxy before it's needed?
Because it's easier to do them all at once unconditionally than to put in the conditional logic to handle them in deferred fashion. The only pressure that would move me from the former to the latter is if there are a tremendous number of proxies as you mention in this post. So deferring in this case could make sense.

I have been trying to figure out a way to modularize the application into MultiCore without success...
Consider how you are breaking things down. You might want a single proxy or a group of related proxies to make up the bulk of a 'service core'. Snapping in and out the service cores as needed is one way to do it and it handles letting the proxies just make their calls as soon as they're registered if you like.

-=Cliff>

Logged
jpwrunyan
Sr. Member
****
Posts: 84


View Profile WWW Email
« Reply #13 on: June 15, 2010, 06:19:58 »

Thanks again for the reply, Cliff.
I can't yet picture in my mind concretely what a 'service core' is and how I would snap in and out of it, but I will try to figure it out on my own first.  Very likely I will come back and ask for help.   ;)
Logged
Pages: [1]
Print