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: How commands and mediators should interact  (Read 10212 times)
midget35
Newbie
*
Posts: 5


View Profile Email
« on: April 14, 2010, 02:19:10 »

Hi guys. I've been using PureMVC solidly for a year and have had a heck of a ride with it. Ups and downs galore! I am very grateful for it and would like to thank all involved. I'm using it in 2 active projects.

I have scoured these forums, the manual, and read everything I can on the subject of PureMVC. So if I am asking something here that has been covered elsewhere - sorry, I tried my best!

In a moment I am going to describe a basic workflow that I encounter daily, and would really appreciate some guidance and feedback on where I'm going wrong or am making too much work for myself. The key questions I have are:

1. I am keen to pass arguments directly from commands to mediators through exposed public methods, but am under the impression that I should always use notifications to do this?

2. If I am sending a notification that is picked up by many different 'types' of mediators, would it not be more logical for that one notification to be registered with a single command, and then have that command send out more specific notifications to interested mediators?

On an aside - I also struggle sometimes with the notion that commands cannot retain information.

Onto my scenario. Say I have a document creation tool (like Word) written in Flex with PureMVC. In order to load a new document I need to do several things. This is the workflow at the moment:

1. user clicks a button to open a previously saved document.

2. the document thumbnail viewer mediator sends a notification asking if another document is about to be overwritten: GET_CANVAS_AVAILABLE.

3. The note is received by command A which directly asks the canvas mediator if its view is empty (and thus ready to receive a new document because there's no risk of overwriting anything).

4. Assuming it is empty, command A then sends another note back to thumbnail viewer: CANVAS_IS_AVAILABLE.

5. Thumbnail viewer then directly calls a public method in documentProxy and passes a document id so the doc can be retrieved from a remote DB.

6. the proxy then immediately sends another note to disable the application while the download is in progress (this is picked up by the application mediator): APPLICATION_DISABLE.

7.  documentProxy eventually downloads the document and sends another note: DOCUMENT_DOWNLOADED

8. the application mediator receives this note and re-enables the application.

9. The canvas mediator gets the same notification and loads the note body (html text) into the view.

10. Other mediators also receive the DOCUMENT_DOWNLOADED notification - say, a summary mediator, and a footer mediator (to show word count and whatnot).

11. The thumbnail viewer also receives the note and makes the thumbnail viewer invisible

12. And that's it - the workflow is complete.

Does it look like I am doing the right thing here? What would you guys do differently to optimise & centralise the flow of logic?

I'm sure this post is pretty dense so please ask me to expand if it will help.

Thanks again - I look forward to your response!
 
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #1 on: April 16, 2010, 12:51:13 »

1. I am keen to pass arguments directly from commands to mediators through exposed public methods, but am under the impression that I should always use notifications to do this?
Sometimes this is needed if a command is doing a lot of complex logic that involves two-way communications with various Mediators. In this case, you often need to expose methods on the Mediators and invoke them from Commands. This happens, but it is rare.

99% of Commands don't need to do this, and by sending notes instead of retrieving the Mediator and invoking a method on it, you are more loosely-coupled, and in OOP, this is generally considered a good thing.

2. If I am sending a notification that is picked up by many different 'types' of mediators, would it not be more logical for that one notification to be registered with a single command, and then have that command send out more specific notifications to interested mediators?
Certainly.

1. user clicks a button to open a previously saved document.

2. the document thumbnail viewer mediator sends a notification asking if another document is about to be overwritten: GET_CANVAS_AVAILABLE.

3. The note is received by command A which directly asks the canvas mediator if its view is empty (and thus ready to receive a new document because there's no risk of overwriting anything).

4. Assuming it is empty, command A then sends another note back to thumbnail viewer: CANVAS_IS_AVAILABLE.
There is absolutely no need for the Command in this case. OPTIMIZE like so:

1. user clicks a button to open a previously saved document.

2. the document thumbnail viewer mediator sends a notification asking if another document is about to be overwritten: GET_CANVAS_AVAILABLE.

3. The canvas mediator hears this and if its view is empty sends another note back to thumbnail viewer: CANVAS_IS_AVAILABLE, otherwise it sends CANVAS_NOT_AVAILABLE.

5. Thumbnail viewer then directly calls a public method in documentProxy and passes a document id so the doc can be retrieved from a remote DB.

6. the proxy then immediately sends another note to disable the application while the download is in progress (this is picked up by the application mediator): APPLICATION_DISABLE.
This is where a Command is needed. The responsibility for disabling the app does not lie with the Proxy, whose only concern is the Model. Nor does it lie with the Mediator who is asking for the data. This is what commands are for. Coordinating activities that affect both the View and Model. Give it a try like this:

5. Thumbnail viewer sends a notification called GET_DOCUMENT with Document ID in the body, which triggers a Command.

6.1 The Command then sends another note to disable the application (this is picked up by the application mediator): APPLICATION_DISABLE.

6.2 The Command then fetches the DocumentProxy and calls a public method, passes a document id so the doc can be retrieved from a remote DB.

The rest looks pretty standard.

Cheers,
-=Cliff>

Logged
midget35
Newbie
*
Posts: 5


View Profile Email
« Reply #2 on: April 19, 2010, 03:50:58 »

Thanks so much for taking the time to reply personally Cliff. Greatly appreciated.

I forgot to add that the project we are working on is located here should you like to check it out:
http://www.sparkol.com/

Thanks again.
Logged
jpwrunyan
Sr. Member
****
Posts: 84


View Profile WWW Email
« Reply #3 on: April 19, 2010, 09:11:37 »

1. I am keen to pass arguments directly from commands to mediators through exposed public methods, but am under the impression that I should always use notifications to do this?
Sometimes this is needed if a command is doing a lot of complex logic that involves two-way communications with various Mediators. In this case, you often need to expose methods on the Mediators and invoke them from Commands. This happens, but it is rare.

99% of Commands don't need to do this, and by sending notes instead of retrieving the Mediator and invoking a method on it, you are more loosely-coupled, and in OOP, this is generally considered a good thing.

I have a question.  What if the command is used to register the mediator and its proxies?  Wouldn't directly setting some basic/common properties on the Mediator actually make a lot of sense (ie apply to more than 1% of Commands)? 

I have an app which opens a pop-up via a command notification when the user clicks the screen.  Depending on where the user clicks, the initial state of the pop-up is different (imagine different buttons for different employees where the pop-up is the same, but the employee information to display depends upon the button pressed).  So I send a SHOW_EMPLOYEE_POPUP notification which has the employee id.  I use a ShowEmployeePopup command to register the Mediator and Proxies necessary to initialize the popup (on subsequent calls, this is not necessary and is skipped).  Once the view is set-up, in the same command, I then just set the employee id on a public property of the Mediator which then does some other things as necessary (like grabbing the employee's info from various proxies).

So, ShowEmployeePopUp sets up the view the first time it is called.  Then it immediately sets the employee id (located in its notification) to the EmployeePopUpMediator (and tells it to become visible).  I found this convenient because it allowed me to contain the relatively simple initialization and "show" logic in one command instead of two (and also centralize the check-if-instantiated logic).  Finally, since this command has to register the EmployeePopUpMediator, why not just keep it simple and directly access its properties?  Why would I send a notification to set a property on a Mediator which I already have a reference for? -- that's my thinking anyway.

So did I just happen to fall in that 1% sweet spot?  Or am I doing something wrong?
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #4 on: April 21, 2010, 09:24:41 »

The role of the mediators is to mediate. That is, to broker communications between a view component and the rest of the system. It should act as nothing more than a switchboard operator.

Don't create lots (any really) of state-related properties on your Mediators. Your view components are responsible for maintaining their own states and behaviors. If you start splitting the state between your Mediator and its view component, the view component becomes less portable.

And as soon as you start exposing methods on your Mediator for this, that and the other thing, you begin a slide down the slippery slope, at the bottom of which lies 'code behind'. There is a tendency for those methods to know more and more about the guts of the component and to blur the encapsulation boundary that should exist between them.

-=Cliff>
Logged
jpwrunyan
Sr. Member
****
Posts: 84


View Profile WWW Email
« Reply #5 on: April 21, 2010, 06:11:31 »

Right, I fully comprehend all too well what you are saying.  People on my project have already gone slaloming down that slope (myself included), bloating Mediators with code to the point that the difference between the Mediators and their views is often arbitrary.  So, allow me to just apply your advice concretely to the above example:

Rather than have the ShowEmployeePopUpCommand directly set the employee id (contained in its notification) via a public method on the EmployeePopUpMediator instance that it registers, it should dispatch a new notification (call it "SetEmployeeId") which the EmployeePopUpMediator would then respond to.

I would still get the show-and-set-state functionality out of one Command, but the two tasks would be articulated with separate Notifications and the Mediator would no longer have/require a public method for setting a state.

This seemed a bit verbose to me but... well, slippery slope.  It would be nice if the Mediator and the Command could respond to the same notification, but since the command actually registers the Mediator (if it's not registered already, ie the first time), I don't think this is possible.

Anyway, thanks and please correct me (yet again) if I am wrong.
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #6 on: April 23, 2010, 09:19:12 »

Rather than have the ShowEmployeePopUpCommand directly set the employee id (contained in its notification) via a public method on the EmployeePopUpMediator instance that it registers, it should dispatch a new notification (call it "SetEmployeeId") which the EmployeePopUpMediator would then respond to.

I would still get the show-and-set-state functionality out of one Command, but the two tasks would be articulated with separate Notifications and the Mediator would no longer have/require a public method for setting a state. This seemed a bit verbose to me but...
Yes, that's it. You can just as easily send the notification as opposed to retrieving the mediator and setting a property. That's one less step in the command as I count them. While the mediator has to respond to the note, it would also have had to expose a setter, Not a lot of net code difference, but you come out more loosely coupled; a constant aim of the OOP developer.

-=Cliff>
Logged
Pages: [1]
Print