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: Notes being sent 1st are not being received 1st  (Read 15397 times)
jaxim
Full Member
***
Posts: 22


View Profile Email
« on: August 27, 2011, 06:15:46 »

I think I'm either going about PureMVC's notification system incorrectly or there is something that can be improved about the notification system.

The problem I am having is that a notification is sent out but during one of the mediator's reactions to this notification, a 2nd notification is send out, which is received by the other mediators before the other mediators receive the 1st notification.

For example,
1) Note1 is sent to the application.
2) Mediator1 and Mediator2 are set to receive Note1
3) Mediator1 receives Note1 first.
4) Mediator1 reacts to the note by sending out Note2
5) Mediator2 receives Note2 and changes a local boolean property from false to true
6) Mediator2 finally receives Note1.
7) Because the local property is true, Mediator2 reacts to Note1. If the local property had remained false, then Medaitor2 would not react to Note1.


I understand why Mediator2 received Note2 before it received Note1 even though Note1 was sent before Note2; however, I expected a different behavior. This is exactly the same kind of behavior as ActionScript's event system, but I would have expected the PureMVC to allow a different behavior. I would have wanted any notes to be placed in a Queue system. So if Note1 was sent, then Note1 should be received by all Mediators before any other notes even if a Mediator sends out a note while Note1 is still being sent out.


QUESTIONS:
1) What is the workaround to this issue? How can I ensure that Mediator2 does not change a local property before it has a chance to receive Note1?
2) Is there a way to ensure all mediators receive Note1 before it receives any other notes?
3) If not, should the PureMVC be changed so notes are placed in a FIFO (First In First Out.) queue? As not to break previous PureMVC applications, should PureMVC be changed so a change of a property would make the notifications be sent either using the current logic or the FIFO logic?

Thanks!
Logged
Deril
Full Member
***
Posts: 22


View Profile Email
« Reply #1 on: August 27, 2011, 10:40:44 »

Hi,

 its a bit hard to guess what you are doing... :) it feels like you just have error there somewhere... lets me theorize a bit for fun.. :)

Lets think.. Note1 and Note2 can have separated or connected concepts.

#1 Notes have connected concepts.... if that's the case both should be based on one proxy, that whould represent that connection in your needed abstraction level. Then it does not matter what note comes first. mediator just takes needed proxy and do what it needs to do. If mediator1 getting note1 needs to change mediator2 behavior somehow... it should change proxy data via command in most cases, (instead of sending note to mediator2).

#2 Notes have different, not connected concepts. In this case, they should not depend on any Boolean stored in mediator.. (why you have Boolean in mediator to decide on how to react to notices in the first place? proxy should keep the state. not mediators.)

lets have a look in your questions...

1: think about your implementation.. you are doing something in wrong place.. or coupled something to tightly..
2: sure.. everything is possible! Instead of sending second notice, put it in the stack of some sort. Then with delay or after note1 confirms that it is done with his work, send note2 ! ... some extra coding needed.. :) but possible.
3: there is no good reason to change current behavior on notes.


Just think about putting conflicting state into proxy, and build from that up.
« Last Edit: August 27, 2011, 11:00:02 by Deril » Logged
jaxim
Full Member
***
Posts: 22


View Profile Email
« Reply #2 on: August 27, 2011, 12:19:52 »

Here is what I am doing with my 2 notifications, but keep in mind that there could be other cases like this.

Note1 is dispatched when the user clicks the ENTER key. The mediator then decides how to behave when the enter key is pressed. Sure, I could of made the mediator or its sprite listen directly to a keyboard event, but I wanted to be able to control the turning on and off the listening of the keyboard events centrally so that all of the app is affected and behaves the same way by keyboard events. And I guess I could create a singleton Keyboard class that all of my application's mediators/sprites listen to, but isn't the whole point of PureMVC is that you notify the app using its notification system?

So anyway, The Enter Notification is received by Mediator1, It sends out a notification that something should happen which then triggers a DISPLAY notification to be sent  (or rather a command tells mediator2 to display its sprite)  which causes Mediator2 to display its sprite. The Enter Notification finally reaches Mediator2. Mediator2 is set to only react to the Enter Notification if Mediator2's sprite is visible. Because the DISPLAY notification is received by Mediator2 before the ENTER notification (even though the ENTER notification was sent 1st), the mediator2 sprite is visible and so Mediator2 reacts to the ENTER notification.

« Last Edit: August 27, 2011, 12:26:40 by jaxim » Logged
Deril
Full Member
***
Posts: 22


View Profile Email
« Reply #3 on: August 27, 2011, 12:57:31 »

Mediator should not decide anything... its a job of logic tear to think about things.

 Lets see... I still missing some details.. Depending on what you are doing one or another approach could be better.

you are sending notice on Enter press. That's great! That's exactly how it should be..

Now we have 2 options.

1 - note is cough by mediator and processed.
2 - note is cough by command and processed.


 both cases are valid, but depending on what you are doing one approach is better then another.

for 1 if your key pressing action changes view in straightforward matter,  that does not require "thinking" - its perfect way to go!

 for example... I want my item to be shown then I press the button, and hidden then release. and nothing more. Lets say other parts of application don't care about this show/hide behavior, then I don't need a proxy to store state.

 but in your case it looks like your have more complex case. So I say.. lets go with option 2!

so... then enter key is pressed "HANDLE_ENTER_KEY" note is sent and HandleEnterKeyCommand is executed.

Next. As I mentioned before - you need a proxy!

depending on what you are doing you could have very different proxies. from what I know 2 options sound logical :

Option A : KeyPressProxy. This proxy stores key press state. In this proxy you would store key press boolean, count.. or whatever you need.
Option B : ViewElementStateProxy ... or something in that direction. This proxy would concentrate on remembering data you need to think about that evolves around your view, if you need data about 2 view objects that has nothing in common, maybe you even need 2 proxies. one for each mediator.

 Then you create proxies try to think less about view.. and more about state of your application and how it needs to change. Mediators are needed just to show it.

Here is scenario :

HandleEnterKeyCommand uses whatever proxies is best for you, think about meaning of life.. and other stuff.. and changes data to whatever you need to care about. And don't touch view at all.

Proxy classes gets data changed, and sends a note(or notes) to tell about it to whatever cares to listen. in your case you have 2 mediators.

 those mediators would get state with note(or get it from proxies), and just show it, without "thinking".

keep in mind that those 2 mediators should most likely know nothing about each other. And proxy data should be all and not more what they need for whatever they are showing.


I hope it helps.



« Last Edit: August 27, 2011, 01:22:28 by Deril » Logged
jaxim
Full Member
***
Posts: 22


View Profile Email
« Reply #4 on: August 28, 2011, 11:06:53 »

Thanks, Deril, for the attention in this matter.

I eventually chose to extend the core View class to get pureMVC to do what I wanted.

Do you see something wrong with wanting that a notification is received by all observers before subsequent notifications are received?

What you suggested, may not have worked for me. Even if I get the command to send the 2nd note, the 2nd note would still get received by some mediators before the 1st note was received. So I chose to extend View so notifications would be placed in a queue and wouldn't be sent out until the preceding notification was done being sent.

The following is an excerpt of the extended View class that I made. Now when I send Note1, it is received by all observers before any other notes are received, even if additional notifications are sent within the notification loop that is sending note1.


:
/** The vector array that contains the list of notifications that should be sent to the application.  **/
private var _vNotifications:Vector.<INotification> = new Vector.<INotification>();

/** The notitfcation that is currently in the process of being sent. **/
private var _noteCurrent:INotification;

/**
* Override notifyObservers() so notifications that are sent to this method are completely sent before a different notfication is sent.
*/
override public function notifyObservers(notification:INotification): void {
if(observerMap[notification.getName()] != null ) {
_vNotifications.push(notification);
if(_noteCurrent != null){
//If there is a previous notification still being sent, then do not proceed to notify the next notifcation
//until the previous notification has completely been sent to all observers.
return;
}
_noteCurrent = notification;
super.notifyObservers(notification);

//once the notification has been sent, remove the notification from _vNotifications
var iLength:int = _vNotifications.length;
for(var i:int = 0; i<=iLength-1 && iLength>0; i++){
if(_vNotifications[i] == notification){
//most likely this will be the 1st item in the Vector Array
_vNotifications.splice(i,1);
break;
}
}
_noteCurrent = null;
//if there are still notifications in _vNotifications, then notify the observers of the next 1st notification within the vector array
if(_vNotifications.length > 0){
notifyObservers(_vNotifications.shift());
}
}
}





Logged
Deril
Full Member
***
Posts: 22


View Profile Email
« Reply #5 on: August 29, 2011, 02:58:54 »

Do you see something wrong with wanting that a notification is received by all observers before subsequent notifications are received?

 The only thing that is wrong, is that your mediators has this dependency that should not be there.

My guess is that your data tear does not have everything it needs to handle state properly..

but hey.. do whatever works for you.
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #6 on: August 29, 2011, 08:47:20 »

Sorry to be popping in late on this discussion. Usually in these cases, the answer is not to rewrite the framework, but instead to devise a more sensible collaboration pattern that doesn't couple one mediator to another or make them keep state. Mediators and Proxies should not manage state.

You'd be far better off to use the State Machine utility to manage the application state. You can make your Mediators interested in responding to changes in overall application state, not each other.

The mediator that hears the keypress sends out a StateMachine.ACTION notification, which is heard by the State Machine, causing a transition to another application state if the action is mapped to a transition for the current state. If so, a transition to that state is started and a series of notifications are sent out announcing the fact that you are leaving state x, entering state y and have fully changed to state y. This gives you a way to cancel the transition out of the current state if certain conditions aren't met, cancel the transition to the new state if other conditions aren't met, and respond to the final state change by rearranging the view and/or firing off command logic.

This way Mediators are decoupled from each other, since they are notified because the state changed, not because some other Mediator had an internal change.

Take a look at the State Machine Introduction: http://puremvc.tv/#P003/

-=Cliff>
« Last Edit: August 29, 2011, 08:53:20 by puremvc » Logged
jaxim
Full Member
***
Posts: 22


View Profile Email
« Reply #7 on: September 01, 2011, 10:19:15 »

Thanks for chiming in, Cliff.

The thing is that my Mediators are already decoupled from each other. They don't communicate to each other directly but rather use notifications to indicate (for example) when a mediator's sprite has been displayed.

But putting aside how I implement puremvc, my question still stands:
Should observers of the notification system receive notifications that were not before other notifications? To me, this seems like an oversight which may not have been so obvious. But perhaps it was made this way by design. What are the use cases when one would want a later notification to be received by an earlier notification? Or should my code change be considered in a later version of PureMVC? What do ypou think, Cliff.

Much thanks!
Jack

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



View Profile WWW Email
« Reply #8 on: September 01, 2011, 10:46:03 »

Should observers of the notification system receive notifications that were not before other notifications?
That doesn't really make sense. If you are an observer of a note, you'll be notified.

What are the use cases when one would want a later notification to be received by an earlier notification?
This doesn't make sense either. Notifications don't receive notifications.

I think what you're wrestling with is the fact that notifications are sent immediately and we're executing in a single-threaded environment. That is by design, not oversight.

Lets say a notification is sent out and 12 observers will be notified. Lets say there is a progress bar somewhere and as each of these 12 observers receive the notification, they perform their 1/12 of the overall activity triggered by the notification, and then send out a progress note saying 'my part is done', which the ProgressMediator hears it and updates its visual progress control. If those progress notes were stored to be executed later, then what would happen? You'd wait until the entire operation completed without any progress feedback, and then it'd all fly by at once as those 'queued' notes were sent.

-=Cliff>
Logged
jaxim
Full Member
***
Posts: 22


View Profile Email
« Reply #9 on: September 02, 2011, 06:08:59 »

Sorry for not making sense. I should of proofread my last post. Let me try to explain it again.

When a notification is sent out, there is a potential that additional notifications may be sent and received before the 1st notification has completely been received. The 1st notification will eventually be received by all observers, but sometimes other notifications may be sent and received in the middle of sending out the 1st notification.

Your example with the preloader isn't the problem I am seeing. Your example has 12 separate notifications being sent out at separate times. For example, a "loaded" notification that the background image was been loaded, another "loaded" notification that an XML file was loaded, etc. In this use case, there is really only one observer of the "loaded" notifications.

What I am saying is that there are many observers listening to a single instance of a notification. For example, let's say that there are 12 observers listening to hear when the ENTER key is pressed. Each of these 12 observers have a different sprite associated with them. These observers only react to the ENTER key if their sprite is visible. So what here is a potential use case when the ENTER key is pressed.

1) the user presses the ENTER key
2) One class is listening for this event. When it hears this event, it sends out a notification "ENTER_PRESSED"
3) There are 12 mediators listening for this "ENTER_PRESSED" notification
4) The View class tells these observers about this "ENTER_PRESSED" notification by performing a for-loop
5) The 1st 5 observers within this for-loop do not react to the "ENTER_PRESSED" notification because their sprite is not visible.
6) However, the 6th observer does react because its sprite is visible.
7) Upon hearing that the ENTER key has been pressed, the 6th observer sends out a notification requesting a new display to be visible. The name of this notification is called "DISPLAY_LOGIN". This notification is either sent out directly by this 6th observer or by a command - it doesn't matter.
8) The "DISPLAY_LOGIN" notification has a few observers. The View class uses its for-loop to tell this new set of observers of this new notification.
9) One of the observers that is listening for the "DISPLAY_LOGIN" notification reacts and causes its associated sprite to be visible.
10) The "DISPLAY_LOGIN" notification for loop finishes.
11) Now the code continues with the "ENTER_PRESSED" notification for loop that was started from the beginning.
12) The 7th observer is told of the "ENTER_PRESSED" notification, then the 8th, 9th, 10th.
13) The 11th observer so happens to be the same observer that reacted to the "DISPLAY_LOGIN" notification. Because the "DISPLAY_LOGIN" notifcation caused the 11th observer to display its associated sprite, the "ENTER_PRESSED" notification causes the 11th observer to react. The 11th observer send out a "FIELD_COMPLETED" notification, which in turn causes any observers of that notification to react.
14) Eventually the 12th and final observer is notified of the "ENTER_PRESSED" notification.

Do understand why I think this isn't logical? Look at my sample code to see how I rectified the problem. With my modified/extended View class, the use case I laid out above would play out in the following manner:

1) the user presses the ENTER key
2) One class is listening for this event. When it hears this event, it sends out a notification "ENTER_PRESSED"
3) There are 12 mediators listening for this "ENTER_PRESSED" notification
4) The View class tells these observers about this "ENTER_PRESSED" notification by performing a for-loop
5) The 1st 5 observers within this for loop do not react to the "ENTER_PRESSED" notification because their sprite is not visible.
6) However, the 6th observer does react because its sprite is visible.
7) Upon hearing that the ENTER key has been pressed, the 6th observer sends out a notification requesting a new display to be visible. The name of this notification is called "DISPLAY_LOGIN". This notification is either sent out directly by this 6th observer or by a command - it doesn't matter.
8) The extended View class hears about the "DISPLAY_LOGIN" notification, but because the previous for-loop is still in progress, it places the "DISPLAY_LOGIN" notification in a queue.
9) The remain 12 observers are notified of the  "ENTER_PRESSED" notification. None of the remaining observers react because their associated sprites are not visible.
10) The extended View class then starts a new for-loop to tell a new set of observers of the next notification in its queue: the "DISPLAY_LOGIN" notification.
9) One of the observers that is listening for the "DISPLAY_LOGIN" notification reacts and causes its associated sprite to be visible.
10) The "DISPLAY_LOGIN" notification for-loop finishes.
 

With my extended View, the use case doesn't cause one of the observers to improperly react to the ENTER notification. You can argue that I should construct my notifications/mediators differently, but the point is that the framework should be flexible. I still can't see the use case where the programmer would want the 2nd "DISPLAY_LOGIN" notification to be sent and received by a new set of observers before the 1st "ENTER_PRESSED" notification.


Hopefully I explained myself more clearly this time. Please let me know if things are still not clear.
« Last Edit: September 02, 2011, 06:21:45 by jaxim » Logged
Deril
Full Member
***
Posts: 22


View Profile Email
« Reply #10 on: September 05, 2011, 03:41:21 »

Hi,

 Sorry I didn't read all your reply... but here is your problem:

These observers only react to the ENTER key if their sprite is visible.

... as we mentioned already. Mediator should not keep or manage state.

Proxy should keep the state..
Commands should manage state.
and mediator is that DUMB entity that just SHOWS IT.

so.. your sentence should sound more like this... :

"The ENTER key is pressed, and command gets trigered, it changes the proxy, then proxy sends the note that state have changed for all 12 observers, These observers react to the proxy note, then they check the proxy, and if it says they should show sprite.. they show it.. if it says it must be hidden... they hide it."



 Observers-mediators should not care about state of sprite, as view object. The mediator could (and most probable should) check if sprite is visible just to know if it needs to change it. For instance if sprite in not visible, there is no need to hide it. But it should not do LOGIC based on the sprite state.


 My guess is that you fixated on your current implementation, and you don't want to change it... but try to change everything around it to meet it. (including framework in this case...)
 Let it go! try to approach you problem differently!
« Last Edit: September 05, 2011, 03:53:48 by Deril » Logged
jaxim
Full Member
***
Posts: 22


View Profile Email
« Reply #11 on: September 06, 2011, 07:50:32 »

As I mentioned, please ignore how I implemented pureMVC, but rather concentrate on the logic of the for-loop of the View class. It doesn't make sense that a Notification that was sent after another notification would be received before that previous notification.

If you cannot get pass how I chose to implement pureMVC, then I guess we are at an impasse and I am not sure how to make my point.

Again, thanks for taking the time to review this topic.




p.s. You could still change the logic that I stated to the one you specified and the problem could persist due this for-loop logic. So instead of the mediator checking if its sprite is visible, it checks the proxy's state which you suggested. However, because the "DISPLAY_LOGIN" notification was sent while the "ENTER_PRESSED" was still being sent, that could have changed the state stored in the proxy and so when the for-loop got to the 7th mediator in my example, the Mediator would react to the "ENTER_PRESSED" notification.

But again, please try to concentrate on the for-loop of the View class and see if my suggested "queuing of notifications" code makes sense.
« Last Edit: September 06, 2011, 07:59:12 by jaxim » Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #12 on: September 06, 2011, 08:33:28 »

The framework was designed with just this sort of in-the-field modification in mind. The idea that someone may want to replace some part of the framework with their own implementation was definitely at the forefront of my mind as I wrote every class.

If you want your notifications to be sent in a different order, as you've seen, you can definitely change it.

As for folding that scheme back into the framework, it seems unlikely to be the right course of action for purely practical reasons. People all over the world have been using this framework for almost 5 years now. It has been stable for most of that time, so its behavior is well understood and relied upon by developers. To change it would likely break a lot of working code, causing a backward incompatibility.

Also, if your application is ever worked on by other developers with PureMVC experience, its different intrinsic behavior might cause problems for the project as the team members have varying mental models about how things work. So be sure to document your changes well for future team members.

-=Cliff>
Logged
Deril
Full Member
***
Posts: 22


View Profile Email
« Reply #13 on: September 08, 2011, 03:03:28 »

Hi,

 sorry if I misunderstood you in any way. All I meant is to help, and see how other people use PureMVC.

I think the reason of our miss-communication is because from my view point, you are braking the very reason we use PureMVC. And that reason is decouple mediators from data and from each other. And if you do that, the order of notifications makes no difference. (mediator will just show most recent data...)

 In any case.. as I mentioned before: do what works for you.


Have fun.

« Last Edit: September 08, 2011, 03:05:19 by Deril » Logged
jaxim
Full Member
***
Posts: 22


View Profile Email
« Reply #14 on: September 08, 2011, 07:09:55 »

Thanks, Deril and Cliff.

I appreciate you taking the time to entertain my questions and thoughts.
:-)
Logged
Pages: [1]
Print