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: Adding and removing view components from stage... tangle of concepts.  (Read 15943 times)
jlahr
Jr. Member
**
Posts: 19


View Profile Email
« on: January 20, 2010, 09:45:04 »

I'm taking a step back from the project I'm working on and trying to relearn the principles behind view components. I've read several posts that address concrete mediator / view component coupling and have read the best practices document half a dozen times, but it still doesn't click.

My issue is that I don't understand who is ultimately responsible for adding or removing a viewcomponent from the stage. By extension, I don't understand how entire sets of components (complex interfaces, for example) are managed and, to take it up one more level of abstraction, what that means for multi-swf projects.

Imagine a user signup process. The user goes through several screens containing forms and, upon completion, is dropped into the 'home page' which is a new swf. How do I break this down? Each page is a seperate view component? Global mediator handles the transition between page components? Upon completion, some kind of super global mediator drops the whole user signup swf and then loads the home swf?

I think my confusion is falling in these areas:

- Should the overall view hierarchy be managed in one mediator? I imaging if we're loading and removing entire panels there needs to be some parent to handle that transition. But which actor is actually processing the 'addChild' & 'removeChild' commands? Are we adding child directly to stage or to GlobalView?

- Mediators are allowed to add their own components. But don't mediators expect 1 argument for it's viewComponent? Do I just drop that param and create the viewComponent myself in the constructor?

- Ok, so even if we have mediators creating their own components, where do we instantiate the mediators? I know the initial set of mediators are created in the StartupCommand? Does it then follow that any new set of mediator / view component pairs be created in a command?

- How does this tie into a multicore paradigm with several swfs? I feel like this would require several sets of generic stage handlers, each handling the adding and removing of view component / mediator pairs according to their level of abstraction. I.e. GlobalSwfMediator which loads swfs which each have their own StageMediator which loads view components which each have their concrete mediator which add subcomponents... and so on down the line.

There are just some of the basic issues I'm not clear on. I understand the principles of view encapsulation and notifications and separation of data model from business logic... etc. There's a chasm, however, between these design concepts and practical implementation.

That's for your patience, I know this is waay too wordy. I just want to distill the above tangle of concepts and responsibilities into a few key techniques and I feel like a lot of people go through this stage with the famework.

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



View Profile WWW Email
« Reply #1 on: January 20, 2010, 10:43:58 »

- Should the overall view hierarchy be managed in one mediator? I imaging if we're loading and removing entire panels there needs to be some parent to handle that transition. But which actor is actually processing the 'addChild' & 'removeChild' commands? Are we adding child directly to stage or to GlobalView?
'Managing' isn't really the word to use when talking about a Mediator, it leads you down the road of thinking it might be a good place to heap a bunch of logic. It is a battle to keep logic out of the Mediator until one accepts that the view component itself should encapsulate its own behavior. Mediation is what mediators do. Its about sending and receiving information on behalf of the view component and as little else as possible.

That said, I'm assuming you're coming from a Flash perspective. This is one place where the Best Practices doc really is slanted a bit in favor of the Flex/AIR approach. That is, MXML is used to describe a view hierarchy which is built and only once that is done, is the PureMVC apparatus kicked into play and Mediators attached to the view components of that hierarchy.

If the hierarchy isn't built to begin with then you have take a slightly different tack. Create a StageMediator and give it a reference to the Stage. Then you can use Commands and/or Mediators to create view components and have them added to the stage by sending them off in the body of a notification that the StageMediator listens for, such as ADD_TO_STAGE. The StageMediator upon hearing this should call addChild on the Stage to add the new object.

As for handling the loaded swfs, they can be treated just as you would a view component, given their own mediator and can be added to the stage in the same way.

-=Cliff>
Logged
jlahr
Jr. Member
**
Posts: 19


View Profile Email
« Reply #2 on: January 25, 2010, 03:20:53 »

Thanks Cliff, this is helpful.

Using your suggestions I set up a StageMediator whose sole responsibility is to load and remove SWFs. Then I put up a few navigation buttons to allow me to load those swfs. I gave the buttons a mediator which listens for button clicks and sends an ADD_TO_STAGE notification to the StageMediator along with the SWF loader corresponding to the proper button.

Now, I'm worried I've giving too much responsibility to the button mediator. For example, if I wanted to load a SWF from anywhere else in the application, it doesn't make sense, to me, to have to handle it through a button mediator which really should do nothing but listen for clicks.

Does moving this logic into a Command make sense? I've always thought of a command as a discrete chunk of procedural code and I don't see how it would function as, what seems to me, a mediator for the StageMediator. I.e. button tells command to load 'Home', command packages this and sends out the ADD_TO_STAGE notification? Why not just cut out the command and have everything talk to the StageMediator directly?

Also, if I want the loaded Swf to initiate an ADD_TO_STAGE notification is it as simple as importing that top-level StageMediator and sending the notification?

Thanks for your help.
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #3 on: January 26, 2010, 11:56:38 »

...I've always thought of a command as a discrete chunk of procedural code and I don't see how it would function as, what seems to me, a mediator for the StageMediator... Why not just cut out the command and have everything talk to the StageMediator directly?

The utility of a Command in this scenario would be to centralize the application's knowledge of where to get the SWFs and how to load them (when there are multiple places in the app that would like to initiate such a load).

Say you have 5 different places in the view that can cause a swf to be loaded. Having 5 mediators responding to their view components by loading the SWFs and shipping them off to the StageMediator, would be distributing the knowledge of swf location and loading across all those Mediators.

If instead, a Mediator sent off a notification called AppConstants.LOAD_SWF with a type property of AppConstants.HOME_SWF, a LoadSwfCommand could respond by switching on the type property of the note, loading the appropriate SWF and sending off the AppConstants.ADD_TO_STAGE message.

In the latter approach, the only thing the Mediators have to do is send off a note with the constant name of the SWF to load and the Command makes it a DRYer application by keeping the Mediators from having to duplicate the swf loading in addition to bare minimum necessity of sending off a note.

-=Cliff>
Logged
lostatoll
Jr. Member
**
Posts: 15


View Profile Email
« Reply #4 on: March 24, 2010, 12:36:16 »

Just wanted to mention that this thread was very helpful for me. Also coming from a pure as3 background.
Logged
sideDoor
Full Member
***
Posts: 25


View Profile Email
« Reply #5 on: April 04, 2010, 07:58:49 »

On this same topic, if views should be instantiated within their Mediator, then is the viewComponent passed to the constructor of a Mediator always merely a reference to the stage or document class or the parent-view to which the view of the Mediator will be added?

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



View Profile WWW Email
« Reply #6 on: April 07, 2010, 07:53:49 »

If a Mediator is in charge of creating its own viewComponent, then it doesn't need a constructor argument at all. And you should not pass the stage around.

The Mediator should instead construct its component and send it off as the body of a notification heard by a StageMediator who adds it to the Stage.

Or it could be heard by the Mediator for another view component that has already been added to the Stage, who adds the new component as a child of its own view component. You can create your entire view hierarchy this way and not have to have the StageMediator manage every single placement and not have multiple classes manipulating the Stage.

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


View Profile Email
« Reply #7 on: April 12, 2010, 07:00:13 »

Or it could be heard by the Mediator for another view component that has already been added to the Stage, who adds the new component as a child of its own view component. You can create your entire view hierarchy this way and not have to have the StageMediator manage every single placement and not have multiple classes manipulating the Stage.

Mr. Cliff,

So, with this second method you outlined, could I then:

1. create a generic ADD_TO_STAGE notification, and shuttle within its body a newly instantiated view.
2. allow each Mediator to generally listen for the ADD_TO_STAGE notification
3. allow each Mediator handle the notification by checking if the view contained in the body of the notification is of interest to the concrete Mediator
4. If yes, and add the new view to the Mediator's view component or subviews as required - the particulars here could be specified within the handle notification method of the concrete Mediator.
5. If no, do nothing?

Could this be a decent implementation of added views to the stage?  Or would I be causing the applications view structure/hierarchy to lean too heavily on Mediators.  Put another way, this mode of view instantiation pairs the display hierarchy of the application directly to the PureMVC framework.  I'm not sure that is the best approach.

OR, should the view be passed to a StageMediator, paired with a parent view and some parameters for placement and z-index?  Still here, I'm pairing PureMVC to the adding of views to the display list...

Again, thanks for your time, and kind regards.
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #8 on: April 13, 2010, 08:46:46 »

Could this be a decent implementation of added views to the stage?
The method you describe would work. Only have Mediators that actually expect to add components to their children listen of course...

Or would I be causing the applications view structure/hierarchy to lean too heavily on Mediators.  Put another way, this mode of view instantiation pairs the display hierarchy of the application directly to the PureMVC framework.  I'm not sure that is the best approach.
I argue that is a perfectly fine approach for several reasons:

1) If you later for some reason decide to go to another AS3 framework, you can write a custom way of creating your view then. You don't need to now because you have a framework with the actors imbued with the very roles and responsibilities that this problem calls for.

2) If you port this to another language, say Objective C or Java, there is already a PureMVC framework available and this same architecture you've built will work there.

The framework is there to help you, don't be afraid of it. If you go writing custom 'managers' and such to handle these problems at every turn, then you're not really letting the framework help you very much. And this brings me to

3) When other PureMVC people come onto the project, the less custom spaghetti the project has, the quicker the new recruit can get on with his or her job. The patterns in the framework are well defined and understood by quite a lot of people. In this way, the special classes that you write so as not to rely too heavily on the framework can end up working against you.

And finally,

4) If #1 happens, you may find that when you start implementing in your new framework that your special hierarchy builder doesn't jive well with the way they do things either, and end up with a white elephant in your codebase there as well. The key to making sure that you can successfully move to another framework is to keep your view components from knowing anything about the PureMVC framework. They shouldn't care how they get assembled.

-=Cliff>
« Last Edit: April 13, 2010, 08:48:55 by puremvc » Logged
sideDoor
Full Member
***
Posts: 25


View Profile Email
« Reply #9 on: April 13, 2010, 06:51:11 »

Great stuff, again, thanks for your time, I'm getting it!

One more question:

Only have Mediators that actually expect to add components to their children listen of course...

Would it not be cool to create an AbstractMediator to listen for any and all ADD_TO_STAGE notifications, and allow concrete subclassed Mediators to respond if necessary?  Or would this get too expensive?

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



View Profile WWW Email
« Reply #10 on: April 14, 2010, 09:30:48 »

Would it not be cool to create an AbstractMediator to listen for any and all ADD_TO_STAGE notifications, and allow concrete subclassed Mediators to respond if necessary? 
Yep. This is usually the way to handle cross-cutting Mediator interests.

For instance, if you check out the subclasses of JunctionMediator in the PipeWorks[1] demo, you'll see multiple levels of this happening.

There is the JunctionMediator which comes from the Pipes utility, and it handles ACCEPT_OUTPUT_PIPE, ACCEPT_INPUT_PIPE notes. Then, in the common package of the demo, there is a LoggingJunctionMediator which adds SEND_TO_LOG notification handling. Then in each core there are further sublasses ( PrattlerJunctionMediator, ShellJunctionMediator ) that extend LoggingJunctionMediator.

So they are able to handle the notes that are unique to their core, and toss the rest to super, knowing they'll be handled at the appropriate level. You just have to be sure to deal with the handleNotificationMethod properly.

Here's a snippet from the PrattlerJunctionMediator:

:
        /**
         * List Notification Interests.
         * <P>
         * Adds subclass interests to those of the JunctionMediator.</P>
         */
        override public function listNotificationInterests():Array
        {
            var interests:Array = super.listNotificationInterests();
            interests.push(ApplicationFacade.EXPORT_FEED_WINDOW);
            return interests;
        }

        /**
         * Handle Junction related Notifications for the PrattlerModule.
         * <P>
         * For the Prattler, this consists of exporting the
         * FeedWindow in a PipeMessage to STDSHELL, as well as the
         * ordinary JunctionMediator duties of accepting input
         * and output pipes from the Shell.</P>
         * <P>
         * Also send messages to the logger.</P>
         */       
        override public function handleNotification( note:INotification ):void
        {
           
            switch( note.getName() )
            {
                // Send the LogWindow UI Component
                case ApplicationFacade.EXPORT_FEED_WINDOW:
                    var prattlerWindowMessage:UIQueryMessage = new UIQueryMessage( UIQueryMessage.SET, PrattlerModule.FEED_WINDOW_UI, UIComponent(note.getBody()) );
                    junction.sendMessage( PipeAwareModule.STDSHELL, prattlerWindowMessage );
                    break;
               
                // And let super handle the rest (ACCEPT_OUTPUT_PIPE, ACCEPT_INPUT_PIPE, SEND_TO_LOG)                               
                default:
                    super.handleNotification(note);
                   
            }
        }

-=Cliff>
[1] PipeWorks source: http://puremvc.org/pages/demos/AS3/Demo_AS3_MultiCore_Flex_PipeWorks/srcview/
Logged
Pages: [1]
Print