The bus, from the plane

Before rushing into the actual implementation I'd like to show you a 10000 feet view of the bus. Just in case you want to give some feedback/suggestions. What I am thinking of is something like this (click to enlarge):

So basically there're three parts:

  • View: formed by the macro-components and, possibly, some "actuators" (more on this later).
  • Controller: formed by the mediators. Contains the business logic. Has read/write access to the model. Receives events from the components through the bus (component-events), through specific topics (XXX-event). Sends commands (application events) to the bus through specific topis (XXX-command) Does not contain any instances of the view.
  • Model: formed by data (current clipboard contents, currently selected file, whatever).

So what I am thinking of is something like this:

  • 1. Components send components through their specific topics towards the controllers.
  • 2. Controllers coordinate component events. May veto (discard) events depending on the model. Controllers may modify the model.
  • 3. Controllers create and send application events (commands) through specific channels in the bus. These events are business specific and need not be related to components.
  • 4. Actuators receive application components from the bus and modify the view accordingly. These actuators are the only responsible for holding instances to components.
From my point of view controllers are what we've called "Type II aggregators" (no instances to the view, no dynamic dependencies) whereas actuators are "Type I aggregators" (instances to the view, dynamic dependencies).

(Well, I hope I've made myself clear. If not then just email me!)

Doubts, design decissions, help appreciated

  • Vetoing. Shall we need actual vetoing of events? I think it's enough if controllers just ignore/react to events depending on the model. Can you think of an example where I could need vetoing for events? Tim, any idea about this?
  • No component-controller dynamic (runtime) dependencies. With the approach above I think we have dynamic decoupling of components and controllers. What I mean is that we don't need macro-components instantiated before controllers are instantiated. If components are absent then there's no problem for controllers. Controllers may be instantiated independently of components. This is right I think (am I right here?)
  • Component-controller static (compile-time) dependencies. In order to compile the controllers I'll need to have component events in place. This is, there's a static dependency between components and controllers. I don't think this is an issue, unless you need to compile controllers and components independently. I can't think a reason why these static dependencies are an issue. Any scenarios you can think of?
(Diagrams are here, OpenOffice/StarOffice, 9Kb, right-click/Save As... to download).

Thanks for any ideas!
Antonio

Comentarios:

Just got back from almost 2 weeks of vacation, oye I'm trying to digest all of this since the what next post!

Pending I can wrap my brain around it sometime soon, I'll say something... If its intelligent or not, thats to be seen! ;)

Enviado por Jeffrey Olson en septiembre 27, 2005 a las 05:02 PM CEST #

Antonio--have you downloaded and read the docs for InfoBus? Do a search for it--it was a complete messaging framework for Swing, originally built by Lotus, I think. It was abandoned (I think due to lack of interest) a number of years ago. Cheers, Patrick.

Enviado por Patrick Wright en septiembre 28, 2005 a las 04:05 AM CEST #

Regarding vetoing, one scenario where that may be useful/necessary is on a CloseRequested event (i.e., user clicks window close box). In some applications, this should pop a "Save your changes? (Yes/No/Cancel)" dialog; the veto would handle the [Cancel] scenario. Not having vetoing on the bus means the close box needs its own micro-controller with the business logic to determine if the model needs saving...unless somebody has a better idea!

Enviado por Mark Murphy en septiembre 28, 2005 a las 05:06 AM CEST #

Hi,

Thanks all for your comments. Some ideas that come to my mind.

InfoBus: Yes, we're aware of that. There're different event bus frameworks/examples we'be seen around: antidote, infobus, somnifugi, werx and elf.

Vetoing: Assume there's a WindowClosing event coming from the MainWindow macro-component (or an ActionEvent coming from the File/Exit menu in a MenuBar). These events are received by a ClosingMediator. Now, that ClosingMediator is able to see the model, see if any file is still not saved and, if so, ask the user for further info. If the user agrees to save without saving then a ApplicationExitEvent is sent to actuators. No vetoing needed, right? I mean, it's the controller mediators those responsible for vetoing (after all they contain the business logic). The decission on whether to save or not is contained in the controllers, not in the views, so there's no reason to implement vetoing in the actuators. Don't you think?

Deciding what is a macro-component. I'd say a macro-component is an isolated, independent component in the application. A "FileSystemViewer" may be a macro-component, but a service to talk SOAP to an external site may be a macro-component as well. It may or may not be a view. The level of granularity for macro-components is a design-time decission. Macro-components may be, of course, some other "applications" (possibly containing event buses themselves as well). To summarize: I'd define a macro-component as a component (visual or not) that is able to send events and receive commands. Now fit whatever you need in there.

Thanks!!

Antonio

Enviado por Antonio en septiembre 28, 2005 a las 06:20 AM CEST #

I had already done something similar, and I have used InfoBus. It worked, but I never finished the app that was using it... in any case, here is a link to the code, in case you might find it interesting.

Enviado por Nicola Ken Barozzi en septiembre 28, 2005 a las 06:21 AM CEST #

Looking good. I agree with the mediator being able to handle the "veto" if needed, as you said it has access to the model. Any update on the java.net project?

Enviado por codecraig en septiembre 28, 2005 a las 07:29 AM CEST #

The idea of vetoing will come into play, I believe, because of the two situations when the Controller or Action needs to know whether of not an event (a command event) was successful.

1. When the user or state of the system (or component) precludes the completion of an event.

The first case could be a result of a user interaction. The scenario of the application closing (or opening a new file while an existing file needs saving) shows this.

Handling the Save functionality in the Closing Mediator doesn't seem the correct place, considering you will have to save during operations such as: OpenFile, NewFile?, SaveFile, and WindowClosing, etc..., and we would want to reuse code as much as possible (hence the idea of creating individual events)

WindowClosing would require you to send a saveEvent and if successful a closEvent to close the file, and then an AppExit event. For OpenFile you would have saveEvent, closeEvent, openEvent. A sequence of events will have to occur in an action or in a mediator, which may need to send events to other mediators in order to complete successfully. Either way, I think, you will have to have veto for flow control in an action or mediator. Actions and mediators are aggregators of command sequences.

2. An error while processing the event

The second example is if an error occurs while saving. Say you click the File Open action, you first command is saveFile for the existing file and it fails for some IO reason. I don't think you would want to discard changes to the file and press on. You would want to let the Action or mediator that fired savFile know not to continue with it's sequence of events (FileOpen). Make sense, or did I go off the deep end? Tim

Enviado por TIm Osten en septiembre 28, 2005 a las 08:13 AM CEST #

Hi Everybody, fascinating discussion! <p/> On the veto issue, vetoing would impact the synch/asynch nature of the implementation. With no veto you can have a worker thread dedicated to reading from the bus and forwarding events; with veto you will need to query all the registered listeners (mediators?) and return a yes/no reply, while blocking on the caller thread. <p/> I would vote for supporting just one model (I wrote "keeping it simple" but this is not necessarily the case). Regarding the scenarios Tim described above, I think both boil down to the same problem: dealing with "forks" in the flow, either from the user (ok/cancel decision), or from the system (an error, or a bad state). <p/> One way to deal with that is to code your aggregator as a state machine. Every time you have a potential fork in your logic, you would have to go to a new state and wait for an event that tells you which path to follow next. <p/> For example, after sending the saveEvent, you would actually "transition" to a new state and wait (I mean return control) for an event that either confirms or denies that the save was successful. <p/> That implies that the code that saves files has to try/catch IO exceptions and feed them back on the bus as an event. Same for remote calls, database access calls and user replies - we might have a UserCancellationEvent. <p/> Regards,</br> -- Nascif <p/> PS: Can we keep the implementation 1.4 compatible? Please? <p/> PS: How about hierarchical topics? It might be helpful (even if just for loggin purposes) to support subscription to topics like "FILE.\*" instead of just to "FILE.OPEN", "FILE.CLOSE", etc.

Enviado por Nascif A. Abousalh Neto en septiembre 28, 2005 a las 09:41 AM CEST #

The implementation is being done in java5 so Antonio can get better with annotations, at least I recall something like that from the previous posts.

Enviado por Jeffrey Olson en septiembre 28, 2005 a las 10:00 AM CEST #

To add to what Nascif said:

When sending a command event (a directive event) we could always send the event async, then wait for the appropriate State Event to inform us as to the result of the command.

Send FILE.OPEN

Wait for FILE.OPENED or a (vetoish?) event with a reason (USER_CANCELLATION, ERROR, etc...) describing what happened so we can determine whether the next course of action.

When sending a state event (informative event) I think we could just send the event asnc as well.

Now we have all of our events being sent asynchronously and we only listen (synchronously or pseudo synchronously in the case of the EDT) for command events! I was against this at first because of the wait after Command events, but since we can deliver all of our events async that seems like decent tradeoff.

???

Tim

Enviado por guest en septiembre 28, 2005 a las 10:44 AM CEST #

It is not clear to me how the blocking will work with regards to the threading architecture. Wait on what? On which thread?

I thought event consumers would be notified using a callback like a generic Swing event listener. Should each event consumer have its own event queue? That would mean also a separate thread per consumer, instead of just one additional thread for the TopicManager queue. Perhaps we can have both...

Enviado por Nascif A. Abousalh Neto en septiembre 28, 2005 a las 04:41 PM CEST #

Enviar un comentario:
Los comentarios han sido deshabilitados.
About

swinger

Search

Archives
« abril 2015
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