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: He Guys basic question about routing certain notifications  (Read 6792 times)
iasonvandermeul
Newbie
*
Posts: 1


View Profile Email
« on: April 19, 2012, 07:07:54 »

Hi everybody,

I am new to PureMVC and I am still figuring it out and some times it's hard to get my head around it but i guess it's part of the learning process. :)

Ok I have this ViewCommand that is being triggered when all data is loaded and this ViewCommand creates a ViewMediator on execution. The ViewMediator waits for a notification ViewMediator.CREATE_VIEW, so it can start creating display elements.

The VIEW_COMPLETE is triggered when all the view objects are created in a other Class called AnimationView. The animation View does the actual creating of the objects and then inside the mediator I addChild this AnimationView to the viewComponent.

So the next step I want to do is animate all those objects inside the AnimationView.

I wonder how to do this in the best way. Should I make some kind of construction that sends a notification to the ViewCommand and then send a other notification where the mediator listens to, so it can execute the startAnimation function in the ViewMediator and the viewMediator can execute the startAnimation within the view? Or should i do this with regular event listeners between the mediator and the view?

I hope it's a bit clear, but basically this is the code:


:
package nl.adlantic.app.views {
import nl.adlantic.app.models.AnimationProxy;

import org.puremvc.as3.interfaces.IMediator;
import org.puremvc.as3.interfaces.INotification;
import org.puremvc.as3.patterns.mediator.Mediator;

public class ViewMediator extends Mediator implements IMediator {

public static const NAME : String = "ViewMediator";
public static const CREATE_VIEW : String = NAME + "CreateView";
public static const VIEW_COMPLETE : String = NAME + "CompleteView";
public static const START_ANIMATION : String = NAME + "StartAnimation";

private var animationView : AnimationView;

public function ViewMediator(viewComponent : Object) {
super(NAME, viewComponent);
}

override public function onRegister() : void {
super.onRegister();
}

override public function listNotificationInterests() : Array {
return [ViewMediator.CREATE_VIEW];
}

override public function handleNotification(notification : INotification) : void {
super.handleNotification(notification);
viewComponent = notification.getBody();
createViews();
}

private function createViews() : void {
animationView = new AnimationView(animationProxy.animationData());
viewComponent.addChild(animationView);
sendNotification(ViewMediator.VIEW_COMPLETE);
}

private function startAnimation():void{
// EXECUTE ANIMATION
// animationView.animate();
}

private function get animationProxy():AnimationProxy{
return facade.retrieveProxy(AnimationProxy.NAME) as AnimationProxy;
}
}
}

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



View Profile WWW Email
« Reply #1 on: April 19, 2012, 10:42:08 »

My thoughts about the code in no particular order:

1. Don't define the notification names on the Mediator. This couples any actor sending one of those notifications to that Mediator, (i.e., has to import the class) which is bad. The sender should not be coupled to the receiver. Yes, a Proxy typically defines the notifications it SENDs, but that's different. The View and the Controller exist to expose the Model for interaction, so that direction of coupling is acceptable.

2. Naming a class ViewCommand is too ambiguous. I cannot tell what its purpose is from that name. This can lead to its being given conflicting responsibilities. You say ViewCommand creates the ViewMediator, so something like MediateViewCommand is more appropriate.

3. You're asking if you should somehow communicate with the ViewCommand after the ViewMediator has created its children. No. See number 2. Make a different command for follow-up activities such as AnimateViewCommand.

4. The constructor of the ViewMediator takes an Object. What will it be tending? A subclass of Canvas? If so, make the viewComponent argument of type MyCanvas or whatever.

5. If the actual class your mediator is tending is a MyCanvas instance, then make the Mediator named MyCanvasMediator. It makes it obvious what component this mediator tends.

6. You make a private reference to the animationView in the ViewMediator. Why? Don't make references to objects where you don't have to, it makes it difficult to destroy things later. This belongs in the view component.  Inside MyCanvas (or whatever), create this animationView property and expose a method called initializeAnimationView() that takes the data you retrieve from the Proxy, instantiates the AnimationView, and adds it to its own display list. There is no need for the Mediator to assume this responsibility - you're doing code-behind. Remember a Mediator's role is one of communication. Do what you can to keep it that way. This approach also encapsulates the view component's implementation. For instance, later if you have an AlternateAnimationView that you'd rather use, you don't have to change the Mediator, you can modify the view component and the Mediator remains unaffected.

7. No need to override onRegister() just to call super.onRegister(). You're inheriting that method, and also, it does nothing in the framework class, just an abstract placeholder.

8. In handleNotification(), also, no need to call super.handleNotification(). The framework method is just a stub for meeting the requirements of the interface.

9. Add a getter for the viewComponent that casts it to the appropriate type for manipulation by the other methods in the Mediator.

10. Get in the habit of using switch inside handleNotification. Even if you're only interested in one note. When you add another interest later, you won't have to refactor.

11. Fetch your Proxys in onRegister() and set them on a local reference instead of using a getter to fetch it every time. That means you only have to do the fetching once instead of repeatedly. In your code, you were only using it once, but later on in the project, you may use it again and then you're wasting cycles refetching it.

12. Create a VO to carry the initialization data from the Proxy to the component. Strong typing is your friend.

13. In this scenario, I am skeptical of the need for the separate AnimationView class, and think its responsibilities could probably be rolled into MyCanvas (or whatever).


In AppConstants:
:
private static const NAME:String = "MyApp";
public static const CREATE_VIEW : String = NAME + "CreateView";
public static const VIEW_COMPLETE : String = NAME + "CompleteView";
public static const START_ANIMATION : String = NAME + "StartAnimation";

In MyCanvas (or whatever):
:
private var animationView:AnimationView;
public function initializeAnimationView( animData:AnimDataVO ):void
{
    animationView = new AnimationView(animData);
    addChild(animationView);
}

public function startAnimation():void
{
      animationView.startAnimation();
}

In MyCanvasMediator:
:
package nl.adlantic.app.views {

import nl.adlantic.app.models.AnimationProxy;
import org.puremvc.as3.interfaces.IMediator;
import org.puremvc.as3.interfaces.INotification;
import org.puremvc.as3.patterns.mediator.Mediator;

        public class MyCanvasMediator extends Mediator implements IMediator
        {

                public static const NAME : String = "MyCanvasMediator";

                public function MyCanvasMediator(viewComponent : MyCanvas) {
                        super(NAME, viewComponent);
                }

                override public function onRegister():void
                {
                       animationProxy = facade.retrieveProxy(AnimationProxy.NAME) as AnimationProxy;
                }

                override public function listNotificationInterests() : Array {
                        return [ AppConstants.CREATE_VIEW,
                                   AppConstants.START_ANIMATION
                                 ];
                }

                override public function handleNotification(note: INotification) : void
               {
                        switch (note.getName())
                        {
                                case AppConstants.CREATE_VIEW:
                                        myCanvas.initializeAnimationView(animationProxy.animationData());
                                        sendNotification( AppConstants.VIEW_COMPLETE );
                                        break;

                                case AppConstants.START_ANIMATION:
                                        myCanvas.startAnimation();
                                        break;
                        }
                }

                private function get myCanvas():MyCanvas
                {
                        return viewComponent as MyCanvas;
                }

                private var animationProxy:AnimationProxy;
        }
}
Logged
Pages: [1]
Print