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: Commands and Notes  (Read 10299 times)
pedr
Port to AS2
Full Member
*
Posts: 27


View Profile Email
« on: June 02, 2009, 12:25:52 »

Hey Cliff,

Been a while  ;).

Had a couple of situations lately where I've found the 1 Command to 1 Notification situation problematic. Obviously if you know in advance that you're going to need multiple Commands to respond to a single Notification, you use a MacroCommand, but when you are registering Commands dynamically, it is easy to inadvertantly bump a previously registered Command out of the way with a new one.

To be more specific, I have a Command that registers other Commands to listen to a Proxy's Notifications. Due to the dynamic nature of the setup, it is possible that there might be have been other Commands registered for the same Notifications. I immediately thought a safe way of dealing with this would be to check to see if there are already any Commands registered with the View, and if so, remove them, then place them (Along with the newer Command) into a MacroCommand and reregister that. This would ensure that nothing ever gets bumped. The only problem is that there is no way to retrieve the Command class from the Controller - Controller.hasCommand() returns a Boolean and Controller.removeCommand() returns void.

I find increasing use in dynamically registered Notifications, and it seems to me that this is a fair use case for either the Controller accepting multiple Commands for a single Notification or for the Controller offering access to a registered Command's class.

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



View Profile WWW Email
« Reply #1 on: June 02, 2009, 03:09:29 »

Hi Pedr! Hows life?

Right.

I hear what you're saying, but I'm having trouble envisioning the circumstances leading to the problem.

Can you give me a good description of a real-world scenario where I'd want to be doing all this dynamic registering of Commands that could stomp all over each other?

-=Cliff>
Logged
pedr
Port to AS2
Full Member
*
Posts: 27


View Profile Email
« Reply #2 on: June 03, 2009, 01:18:19 »

Life is good. Been keeping my head down and getting on with things, but should have a lot more time for the important things (Like pmvc) now.

As for a use case, I'll start with a generalisation. Its no secret that Notifications are pmvc's Events (To a degree), so I can't help but translate the one note / one command ratio to Flash's Event model. To me, the silent superceeding of a previously registered Command by a newly registered Command is like a Class registering for an Event and by doing so, unregistering another class. This seems to be a dangerous precident, especially on a larger project with many people working on it. Personally I can't see a problem with a one to many ratio of Notes to Commands - It would be easy enough to order by registration order or even to allow registration at a particular point  - Controller.registerCommand(command, executionPosition), or perhaps to weight a Command - Controller.registerCommand(command, weighting). That said, I understand that the latter two solutions would add an element of complexity where it is perhaps not needed.

A second use case would be at Startup. I seem to reinvent startup management every time a start a new project and I feel like I've tried a lot of different setups over the years. Essentially I want to be able to say:

StartupManagerProxy(facade.retrieveProxy(StartupManagerProxy.NAME)).registerProxy(galleryProxy, [settingsProxy, assetProxy]).

Where the second argument is an array of dependences. I then want my StartupManagerProxy to take the registered Proxy (an IStartupProxy with an aquire() and a getStartupNotificationNames() method which returns its result, fault and update notification names), and manage its place in a sequence based on its dependencies and the number of simultaneous connections etc.

In order for the StartupProxyManager to be informed as registered StartupProxies dispatch Notifications, I have it firing a Notification that triggers a Command that registers a set of other Commands which are fired by the Notification names it got through calling getStartupNotificationNames():Array). This way, the StartupManagerProxy is notified when its StartupProxies aquire or fail to aquire their data. My problem lies here. As the StartupManagerProxy is (indirectly) dynamically regsitering these Commands, it is very possible that somewhere else in the application a Command that is listening for these same Notifications gets bumped.

Currently I deal with this situation by having all StartupProxies append a predefined suffix onto their declared notification names when they are retrieved via getStartupNotificationNames():Array. A suffix which only the StartupManagerProxy's Commands are looking for.

The StartupManagerProxy then consumes these Notifications, clones them, strips the suffix and redispatches them. This way, any other Commands still get the Notifications.

Sorry. That was a little longer than I expected, but it hopefully makes sense. I can also give you good use-cases when using application-wide state management, though that would be little more complicated to explain.






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



View Profile WWW Email
« Reply #3 on: June 03, 2009, 05:57:03 »

The Controller is just an interested party who says tell me when this note is sent. Just like an individual Mediator. When it's notified, it looks at the note name and instantiates and executes the associated Command just as the Mediator looks at the note name and handles it in the appropriate switch/case.

Sure the Controller could be made to handle multiple Commands per notification, but it would've been more complicated. One of the things I was aiming for in PureMVC was actually to reduce the number of commands written as compared to a Cairngorm app. Currently I'm actually quite happy that I have to write very few Commands. I cannot get my head around the storm of Commands that you are describing. But to each his own, I'm sure it's working for you.

If you are concerned that you might be bumping an already-registered Command, then do a facade.hasCommand(noteName) before registering it.

If you'd like a to have a custom Controller that copes with multiple Commands registered to a notification, it's pretty easy. You can simply extend the Controller class to add the functionality and then in your concrete Facade, override initializeController and don't call super.initializeController(), but instead do:

:
        override protected function initializeController( ):void {
            if ( controller != null ) return;
            controller = MyController.getInstance();
            ...
            registerCommand(xxx);
            registerCommand(yyy);
        }

If you work out something that does the right stuff, perhaps we could roll it into a utility for those who'd like to have lots of dynamic Command registration. I don't think I'd want to modify the core framework (and all the ports that depend on it) in such a fundamental way, though.

-=Cliff>

Logged
pedr
Port to AS2
Full Member
*
Posts: 27


View Profile Email
« Reply #4 on: June 03, 2009, 08:19:27 »

I don't think I'd want to modify the core framework (and all the ports that depend on it) in such a fundamental way, though.

I fully understand that. The simplicity is the reason I use PureMVC and at this point in its life I wouldn't suggest any such a change. However, a small change could be made that would have no impact on complexity or in the frameworks behavior.

I cannot get my head around the storm of Commands that you are describing.

Its exactly to prevent a storm of commands that I am dynamically registering commands. In the example I mention above there are just 3 Commands - HandleSuccessCommand, HandleFailiureCommand and HandleProgressCommand that are dynamically registered for each IStartupProxy. To me, this is hugely economical. Far more economical than a separate set of Commands for each IStartupProxy.

If you are concerned that you might be bumping an already-registered Command, then do a facade.hasCommand(noteName) before registering it.

As I mentioned in my first post, I have done exactly this, but once I have established that there is already a Command registered, there is nothing I can do about that fact. I would like to be able to remove the command and re-register it within a MacroCommand along with the Command that would have bumped it off, but there is no way I can get the Command class as removeCommand() return void. Now if removeCommand() just returned the Command class…

There have been many things that I've wanted changed in pmvc over the years that I have come to see as strengths rather than weaknesses, but in this case, what seems to me like a reasonable way of working is prevented by the framework. I certainly don't expect you to make changes to an already excellent framework purely on my account, but I find this an interesting point of discussion.

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



View Profile WWW Email
« Reply #5 on: June 03, 2009, 03:29:28 »

The reason you don't get back anything is it's just a mapping to a class not an instance of a class. Commands get instantiated on the fly when the controller is notified. So you couldn't retrieve a MacroCommand and add commands to it because its only a mapping to the MacroCommand class to instantiate. The addSubCommand calls would have to be prebaked into the MacroCommand.

:
HandleSuccessCommand, HandleFailiureCommand and HandleProgressCommand Personally, I do that handling inside the Proxy. What can those commands be doing as a result of every Proxy's success / failure that couldn't be done inside the Proxy itself?


-=Cliff>
Logged
pedr
Port to AS2
Full Member
*
Posts: 27


View Profile Email
« Reply #6 on: June 03, 2009, 03:50:09 »

it's just a mapping to a class not an instance of a class

Ok. I hold my hands up. This is very true.

What can those commands be doing as a result of every Proxy's success / failure that couldn't be done inside the Proxy itself?

These commands allow the StartupManagerProxy or whatever else is managing startup to react to the Proxy's initial aquistion of data. For example if a Proxy hitting a remote service failed to aquire the data, a second proxy could be used which aquires the data from another source. Essentially I want one Proxy to be able to monitor the initialisation of the others. I have always faught the temptation to use a bastardised Mediator for this job (The fact it can recieve Notifications makes it ideal for monitoring other Proxies), and I have never liked the StartupManager utility.
Logged
Pages: [1]
Print