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: Using Mediators as Controllers  (Read 8007 times)
flexacs
Newbie
*
Posts: 2


View Profile Email
« on: December 27, 2009, 12:22:28 »

Hello everyone,

I am quite new to PureMVC, but I am very interested about working with this framework.
What I don't like about it is that sometimes I get the feeling it's too much code to write to do few. Of course, this will pay out later, for big applications, I got that, but still ...

Another thing is that you cannot find good authority samples. The existing ones are provided by 3rd party people and I think they do not follow 100% the concepts behind the PureMVC. For a framework beginner like me this can become very annoying, because you simply do not get the right way to do stuff. Every sample available on the internet has a different approach. I will give an example:

I am trying to build an AIR app using PureMVC and I studied lots of examples. I can do it, but I am interested in the right "perfect" way. So I took a look at CodePeek. I saw that only Startup and Shutdown commands are used. I was expecting to have a command for the search action, but instead the proxy methods are called directly from mediators. Working like this, you can completely remove the Commands from the picture, so where is the Controller then? Here it seems its role is played by the Mediators, which not only they provide a steward for the views, but they actually access the model directly.
Maybe I got this wrong, but it seems CodePeek approach is not 100% in the spirit of PureMVC. Can someone please tell me which is the correct way to approach this? Maybe a good sample?

Thanks all.
« Last Edit: December 27, 2009, 12:28:16 by flexacs » Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #1 on: December 27, 2009, 02:07:29 »

Codepeek was the very first PureMVC demo, written by me. It has been updated over the years to work with each new version of Apollo then AIR. It is due for a revisit on best practices, though the matter of the Mediator calling the Proxy remains perfectly applicable1.

The main places where this demo strays is in two places:

1) The mediators break the encapsulation of the components
:
        /**
         * The user has initiated a search.
         */
        private function beginSearch( event:Event=null ):void
        {
            codeSearchProxy.search( controlBar.searchTI.text, controlBar.searchCombo.selectedItem );
        }

The problem here is that the mediator knows about the children of the controlbar. Instead the controlbar should expose properties that are bound to these values and the Mediator should refer to those properties. This allows the underlying component implementation to change (say from a combo to a list with an appropriate name change) without the affecting the Mediator. It should look like this:

:
        /**
         * The user has initiated a search.
         */
        private function beginSearch( event:Event=null ):void
        {
            codeSearchProxy.search( controlBar.searchString, controlBar.selectedLanguage );
        }

2) The Mediator is setting event listeners and registering mediators in its constructor. This should now be done in onRegister:

 
:
       /**
         * Constructor.
         *
         * <P>
         * Populate combo box options and add listeners to
         * the viewComponent (the AppControlBar).</P>
         *
         * @param object the viewComponent (the AppControlBar instance in this case)
         */
        public function AppControlBarMediator( viewComponent:Object )
        {
            super( NAME, viewComponent );
           
            // retrieve and cache a reference to needed proxys
            codeSearchProxy = CodeSearchProxy( facade.retrieveProxy( CodeSearchProxy.NAME ) );
           
            // populate combo box on view component
            controlBar.comboOptions = codeSearchProxy.searchOptions;
           
            // add listeners to the view component
            controlBar.addEventListener( AppControlBar.BEGIN_CODE_SEARCH, beginSearch );
            controlBar.addEventListener( AppControlBar.CANCEL_CODE_SEARCH, resetSearch );
            controlBar.addEventListener( AppControlBar.CANCEL_CODE_SEARCH, resetSearch );
           
        }


Should look like this:
:
        /**
         * Constructor.
         *
         * <P>
         * Populate combo box options and add listeners to
         * the viewComponent (the AppControlBar).</P>
         *
         * @param object the viewComponent (the AppControlBar instance in this case)
         */
        public function AppControlBarMediator( viewComponent:AppControlBar )
        {
            super( NAME, viewComponent );
        }
       
        override public function onRegister( )
        {

            // retrieve and cache a reference to needed proxys
            codeSearchProxy = CodeSearchProxy( facade.retrieveProxy( CodeSearchProxy.NAME ) );
           
            // populate combo box on view component
            controlBar.comboOptions = codeSearchProxy.searchOptions;
           
            // add listeners to the view component
            controlBar.addEventListener( AppControlBar.BEGIN_CODE_SEARCH, beginSearch );
            controlBar.addEventListener( AppControlBar.CANCEL_CODE_SEARCH, resetSearch );
            controlBar.addEventListener( AppControlBar.CANCEL_CODE_SEARCH, resetSearch );
           
        }

Note that I am also strongly typing the view component, since this Mediator will only ever be used for an AppControlBar. This gives me compile-time checking that ensures I don't try to pass in something else.

And the reason for moving the event listeners and the facade manipulation into the onRegister is based on the assumption that you shouldn't (possibly) be starting conversations you're not prepared to participate in. If you are registered then it is safe to set those event listeners, because whatever system interactions they lead to, you're registered to receive notifications about. Same for fetching proxies and invoking methods on them, sending notifications or registering other mediators. In short defer everything but the call to super until onRegister.

Also, in MultiCore, you must defer facade manipulation until onRegister, because you don't get your local facade reference until initializeNotifier which is called after the constructor and before onRegister.

I will address these changes in Codepeek. I have over time done my best to cajole authors into refactoring their demos and utilities to suit best practices, but still there are always different styles. Also best practices have evolved over time. Still, for being the oldest PureMVC demo, it's not that far off the rails.

-=Cliff>

1In a typical n-tier system communication has to pass from one tier to the next and can't ever skip over a tier. The MVC triad is an atypical tiered system. It is handy to think of them as tiers because they divide the actors of the system into three distinct groups. But the topology is actually different, more like a triangle than a stack.

If you look at the original MVC pattern (http://puremvc.tv/#P100/T110) you'll see that it is a valid path for the view to update the model.


Logged
flexacs
Newbie
*
Posts: 2


View Profile Email
« Reply #2 on: December 27, 2009, 03:08:41 »

Hello Cliff (I suppose),

Thank you for the detailed reply. First of all I want to mention that CodePeek is a good sample, I was just puzzled a little.

I think am presenting the point of a medium-advanced developer (in general) who wants to become more friendly with PureMVC and I hope my opinions will help other solve problems and not bother anyone.
Another problem with CodePeek was the use of the XML_Database utility. For the DesktopCitizen utility everything is clear, but with the XML_Database I feel that there is not enough transparency. I am registering a Command which does something (good probably). But as I said, this is a small matter.

Now to come back to your explanation, I totally agree on the fact that Mediator can call the Model directly and MVC is not 100% a n-tier system, but now I am not sure when/why to use Commands ? Accessing the model directly from Mediator makes it easy, less code, so people (I mean me :)) would be tempted to take the short way. So using the PureMVC without using too much the Commands is it a bad practice?

Maybe some of my questions seem stupid for people with great experience like you, but I think for someone like me, who is a beginner with the framework and wants to do things the right way, it will make a big difference.

Regarding the Multicore version I cannot say too much because I used only Standard version. I am not sure yet when I will need the Multicore version.
« Last Edit: December 27, 2009, 03:19:37 by flexacs » Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #3 on: December 28, 2009, 09:33:34 »

Basically, the commands house business logic, and mediators mediate. If a mediator has to do a bunch of calculations and/or interaction with many different points in the model or view tiers in response to an event from the view component, you should instead send the necessary data to a command for this orchestration. Mediators shouldn't be terribly smart. They should basically be switchboard operators, just passing on information, not thinking about it or transforming it.

Also, I would suggest having a quick read of the best practices document, which does talks about the roles of all the actors in the system.
-=Cliff>
Logged
Pages: [1]
Print