About the bus driver

Spot the difference!

What's the difference between these two figures?

Which one do you think is the correct one? Which one do you prefer?

Well, if we try to follow the Model-View-Controller paradigm, then:

Controller: This responds to events, typically user actions, and invokes changes on the model (but \*not\* the view).

So it seems that the second one is the correct one. It's the model that notifies the view about any change, and not the controller handling the view directly. (Of course that's the way things are done in Swing, so that approach is possibly more intuitive than the previous one, right?).

So I propose being the model that pushes events into the bus whenever it is changed. The model should drive the bus. Actuators will then receive these changes and update the views accordingly.

The flow of events would then be as follows:

  • 1. Macro-components generate events, that travel the event bus using topics.
  • 2. Controllers receive and coordinate these events, and modify the model accordingly.
  • 3. The model fires events when changed, and these travel through the bus using (one or more?) topics.
  • 4. The actuators are updated of changes and update the view accordingly.

Opinions on this? What do you think?

Since I'm afraid this is getting too academic let's see things by example.

Opening files

Let's assume the user wants to open a file.

  • 1. The user selects "File/Open" in the menu (or in a toolbar) and an ActionEvent is generated from the menubar (toolbar) through the "menubar.events" or "toolbar.events" topics in the bus.
  • 2. A controller is connected to both the "menubar.events" and "toolbar.events" topics and asynchronously reads the file and creates a javax.swing.text.Document for the file.
  • 3. The controller updates the model inserting this javax.swing.text.Document in the model (possibly in the Swing thread). Once the model is updated it generates a DocumentOpenedEvent event through the "model.documents" topic in the bus.
  • 4. There're different actuators listening on this "model.documents". The "MenubarActuator" will insert an entry in the "Recently opened" menu. The "EditorActuator" will open a new editor tab and include the new javax.swing.text.Document in an EditorPane. The "StatusBarActuator" will update the message in the status bar indicating that the file was opened.

Note: if there's an IOException in step 2 above then steps 3 and 4 are not executed, but instead:

  • 3. The controller updates the model inserting an Exception in the model's "errors" list. Once the model is updated the model itself generates a "ApplicationErrorEvent" through the "application.errors" topic in the bus.
  • 4. There're different actuators listening on this "application.errors" topic. The StatusBarActuator, for instance, will show a red label with the error.
Note there's no veto here: the controller detects the error and generates an event.

Another example: closing the application

  • 1. The user selects "File/Exit" in the menu (or clicks on the close window button in the window) and an ActionEvent is generated from the menubar (or a WindowEvent is generated). These events travel through the "menubar.events" or the "window.events" topics in the bus.
  • 2. A controller is connected to both the "menubar.events" and "window.events" topics in the bus.
  • The controller checks the model to see if all files are closed. If not then it will ask the user (in the event thread) if he wants to quit without closing. If the user selects "YES" then the controller updates the model indicating that the application has to be closed. If the user selects "NO" then the controller does nothing.
  • 3. If the application has to be closed then the model fires an "ApplicationQuit" event through the "application.control" topic.
  • 4. The "ApplicationActuator" releases all resources used by the views, closes and disposes all windows.
Just one more example before continuing...

Another example: saving

Let's assume the user wants to save a file.

  • 1. The user selects "File/Save" in the menu (or clicks the save button in the toolbar). An ActionEvent is generated from the menubar (or an ActionEvent is generated in the toolbar). These events travel through the "menubar.events" or the "toolbar.events" topics in the bus. li>2. A controller is connected to both the "menubar.events" and "toolbar.events" topics in the bus.
  • The controller asynchronously saves the document (contained in a javax.swing.text.Document in the model). And then updates the model indicating that the document is saved.
  • 3. When the document in the model is saved an "DocumentSavedEvent" is sent through the "model.documents" topic.
  • 4. There're different actuators listening on this "model.documents" topic. The "MenubarActuator" will disable the save menu (because the document is saved). The "StatusBarActuator" will set a message indicating that the document was saved.
What about errors? If there's an error saving the document in step 2 then the model won't be updated and steps 3 and 4 above will not be executed. The behaviour could be similar to the one when opening the file above.

Vetoing and threading

Note that in the examples above there's no need to veto events: it's controllers who are responsible for handling errors and unsaved situations, so all the hassle about handling vetoing in different threads just dissappears. Again, I can't think of a situation where vetoing is strictly needed (any ideas here would be appreciated).

I think we need more brainstorming for the threading issues. Let's say we accept the model as the bus driver. The one that rules actuators. Then that's probably a good hint on how threading should work. The model should be modified by a single thread, I suggest. So probably the easiest thing to do is to use the EDT as the one responsible for modifying the model. So all events to actuators should be genereated in the EDT. That's probably the easiest thing to do, right?

State machines

I keep on thinking of state machines in the background. Sorry I can't resist! Interesting things I've found about state machines for GUIs and that need further investigation:

I think the next step could be to modify the demo application to make the model drive the bus. Don't you think?

Thanks for any suggestions,
Antonio

Comentarios:

I agree, models should drive the bus. As you mentioned the standard pardigm has the model notify the view that it has changed, which seems to work quite well. In this case, the model actually notifies Actuators who are listening. I think posting a code sample, i.e. update the demo, would certainly help clear things up and make it more tangible for the followers of this topic.

Enviado por codecraig en octubre 03, 2005 a las 02:35 PM CEST #

Looks good to me. Note that now the actuator is basically the mirror image of the controller; if you move the model inside the right-side box the diagram will be almost symmetrical, in a very interesting way. This must mean you are on the right track! :-)

Enviado por Nascif A. Abousalh Neto en octubre 04, 2005 a las 09:10 AM CEST #

Question:

If your File/Open example has to Save the file and remove the View before Opening another file (as an example), your controller would have to wait until Save was finished in order to Open the file. In the event of an error in Save you would be waiting on an event (either error or model). This means that your commands would have to be synchronous, or able to be synchronous, or at least you would have to wait for an event to be generated after issuing the command before you could proceed. This would end up acting like a Veto. Wouldn't it be better to hide that waiting inside the Bus or support object that fires the event? Or just have vetoes?

Also, for the delivery of events the support object or Bus could be set up with a strategy for delivering event (i.e. on the event dispatch thread). This would eliminate the user knowing the delivery method of an event. You could have four types of delivery mechanisms (SYNC, ASYNC, SYNC_SWING, ASYNC_SWING). They could vary from command event to state event. For example a File/Open command event could be guaranteed to be SYNC_SWING while a File/Opened event could be guaranteed to be ASYNC_SWING or ASYNC.

Your model example seems very close to an Application context like some apps have. I like it!.

P.S. I have to agree with craig...A code example would help...:-)

Tim

Enviado por Tim Osten en octubre 07, 2005 a las 01:11 PM CEST #

I'm following the blog and it's very interessting. I'm writing currently my master thesis and haven't much time to think about it.

But why and where do you want to use Annotations?

(I read some time ago, they aren't real meta data and have some disadvantages. Sorry, i can't remember where i read that some time ago.)

Enviado por Ingo Siebert en octubre 10, 2005 a las 02:10 AM CEST #

Enviar un comentario:
Los comentarios han sido deshabilitados.
About

swinger

Search

Archives
« abril 2014
lunmarmiéjueviesábdom
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    
       
Hoy