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: Best practice for using the type parameter with multiple-instance Mediators  (Read 10184 times)
jpwrunyan
Sr. Member
****
Posts: 84


View Profile WWW Email
« on: June 20, 2011, 02:42:20 »

Ok, first, I have a way to do this, but I want to see if this is really the best way to do things.

I have two types of mediator classes.  One is a generic view, the other is a generic control panel.  Each view/control panel acts as a pair.  These pairs have the exact same function except that the data they work with is different in each case.

Because of this, I have implemented just two classes: ViewMediator and ControlPanelMediator.  The application as a whole displays data sets A, B, and C.  I have instantiated my view/control panel pairs with names like: "ViewMediatorName/A" and "ControlPanelMediatorName/A".

Now the hard part is for a given ControlPanelMediator to affect a given ViewMediator I need to use the type parameter to make sure unrelated actors of the same class aren't also effected.  In other words, ControlPanelMediator/A needs to control ViewMediatorName/A (for example, telling it which attributes in the common data model to display, whether to be transparent or not, etc.).

Currently, I am having these two mediators extract a "sharedType" variable from their names upon registration. 

:
override public function onRegister():void {
  //mediatorName = "ViewMediatorName/A"
  //sharedType = "A";
  //same thing for ControlPanelMediator
  sharedType = mediatorName.split("/")[1];
}

Then when ControlPanelMediator sends a notification, it sets the notification type to this variable, and the ViewMediator with the same sharedType variable handles the notification (all other ViewMediators ignore it).  I think that part is relatively sound.  But it's the actual method of extrapolating this "sharedType" variable from the mediator name upon registration that I am unsure about.

Is this the best way to do this?  I was thinking I ought to explicitly set the "sharedType" on each mediator... but how would I do that without making a big mess?

Remember, the point is I don't want to subclass these for each data set used in the application because the data sets are identical in structure.
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #1 on: June 20, 2011, 08:14:34 »

Rather than concatenating the type and the mediator name base, and later trying to extract the type, maybe do something like the following:
 
:
private var sharedType:String
private static const NAME:String;

public function ViewMediator( viewComponent:View)
{
    sharedType = viewComponent.type;
    super(getMediatorName(),viewComponent);
}

override public function getMediatorName():String
{
     return NAME+"/"+sharedType;
}

override public function handleNotification(note:INotification):void
{
       if ( note.getType() != sharedType) return;
       switch ( note.getName() )
       {
             ...
       }

}

NOTE: I'm assuming the value to be used for sharedType is available on the view component itself at Mediator construction time. And in handleNotification, I'm also assuming that every note that will be handled by this mediator will be directed to a specific instance using the type parameter. That is there will be no notes that all instances will respond to.

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


View Profile WWW Email
« Reply #2 on: June 20, 2011, 07:42:07 »

Thanks for the reply, Cliff.  Your second assumption is correct, there are no notes that all instances will respond to.

However, *currently* the view component instances are created in the mediator's onRegister() method.  This is just to defer instantiation and speed up application start time.  Please tell me if this violates convention--I've been doing it for some time.  Also, the data sets to be used in the application are determined from a separate initial query so the number of View/ControlPanel pairs is dynamic.

:
//very simplified...
for (var i:int = 0; i < dataConfig.length; i++) {
  ...
  facade.registerMediator(new ViewMediator());
  facade.registerMediator(new ControlPanelMediator());
  ...
}

I *could* modify the application so that it instantiates the view components first, sets the type parameter on them, and then passes them to the mediator constructor during the start-up.  It would just be some work changing the current code (but not a problem).  However I am a bit reluctant on principle.  The type value is of no consequence to the view component.  I would essentially be putting it there for the benefit of its mediator which seems... odd.  The view component would never actually use the type variable itself.

Anyway, you did make me think of something new with your suggestion.  Until now, I have been pretty strict about not modifying the constructor arguments with the framework classes.  I guess I thought that was best practice.  But if mediator constructor arguments may be arranged, added, deleted, etc. freely, then how about I pass the type argument there directly? 

:
facade.registerMediator(new ViewMediator(dataId));
...
public function ViewMediator(dataId:String)
{
    sharedType = dataId;
    super(getMediatorName());
}
override public function onRegister():void {
  viewComponent = new View();
}

Is there a best practice regarding framework class constructors?  Or a convention?  There have been times in the past that I wanted to pass parameters to the mediator through a third constructor argument but have not done this because I thought it violated convention (which is to say I haven't seen it done anywhere else).  In those instances I have unhappily dispatched notifications to set properties on the mediator. *1

Don't get me wrong, depending on your response, I may still go ahead and just add the type variable to the view components with a comment stating "Used by mediator.  Not junk.  Do not delete."  But in a way, I don't see much difference between this:

:
  var view = new View();
  view.sharedType = type;
  var med:ViewMediator = new ViewMediator(view);
  facade.registerMediator(med);

and this:

:
  var view = new View();
  var med:ViewMediator = new ViewMediator(view);
  med.sharedType = type;
  facade.registerMediator(med);

except that I know we have discussed not exposing properties or methods on the mediator.  If this risks just becoming a debate about "worse is better" let's leave it at that.  I don't need to waste your time.  I intend to follow your ultimate recommendation regardless.  But if the issues I raised would affect your recommendation, then I hope you will share your thoughts.  If not, I am just going to proceed with your first suggestion.

Thanks again for any feedback.

*1 There is a reason I have become militant about the mediator constructor being limited to (name, viewComponent).  That is because I have had people put all kinds of crap in there, including a second view component (remember, view/control panel pair).  Fed up with this, I made it a rule that the constructor is never to deviate from: (name=NAME, viewComponent=null).
« Last Edit: June 20, 2011, 10:41:12 by jpwrunyan » Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #3 on: June 21, 2011, 07:41:04 »

Until now, I have been pretty strict about not modifying the constructor arguments with the framework classes.  I guess I thought that was best practice.  But if mediator constructor arguments may be arranged, added, deleted, etc. freely, then how about I pass the type argument there directly?  
There's nothing wrong with that. Nor is there anything wrong with creating the view component in the constructor rather than before it's passed in. Your loop creating and registering mediators is just fine. You could pass in the id on the mediator constructor, and you're good to go. The framework classes have their requirements, but your subclass constructors can vary according to their own individual needs.

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


View Profile WWW Email
« Reply #4 on: June 21, 2011, 06:47:03 »

Thank you!  I will loosen up a bit about constructor arguments then, and try to use it as a means to pass simple initialization parameters to mediators, etc. instead of the cumbersome notification dispatching I've used so far.  I don't think the notification method was bad, but it did result in a lot of boilerplate to achieve what I felt should have been a very simple task. 

Furthermore, it allows me to handle the more complex requirements of the above loop registration in a simple, straightforward way.  I seriously had no idea how I was going to dispatch a notification using the type parameter to set the "sharedType" when the target mediator didn't yet have any "type" to discriminate.  Anyway...

I always appreciate your insight!
Logged
Pages: [1]
Print