I did not attend Google I/O but as soon as the video "Google I/O 2009
- Best Practices for Architecting GWT App" (http://www.youtube.com/ watch?v=PDuhR18-EdM) was posted I reviewed it and was a bit confused
by the idea of an EventBus.
From what I can tell the idea is that UI widgets requiring data from
the server are able to fire off requests for some form of data like
"void getTransactionsForAccount(Account acct)" then at some unknown
later time (ms to seconds ussually) when a response comes in from the
RPC call the eventbus is what actually directly recives the data and
then it is dispatched
Client UI: "Hey call some RPC method with these parameters, my
AsyncCallback is this EventBus thing"
...some unknown time passes while the server does magic...
Client Event Bus: "A response came in of type X/Y/Z I should fire an
event to all interested parties"
Client UI: "According to this event I just recieved some of my UI code
needs to change"
A few things are still very hazy for me...
1- What is missing here is when would the Client UI typically
subscribe/unsubscribe from the event bus. If this were a desktop
application I would simply use weak reference so I would not have to
unsubscribe my UI manually to prevent a memory leak.
2- Is there some EventBus code I should be using that already exists
in the GWT SDK? Is this the same code that is used for handling
widget events like clicking a button?
3- Would you typically have one eventbus code for everything?
4- How does this tie in with the MVP pattern?
If anybody else watched the video I would be curious what they have to
say. Also Ray Ryan mentioned he was going to be creating a new demo
application for GWT developers to see this sort of thing in action.
That would be awesome, does anybody have any thoughts on this as well?
On 11 juin, 21:34, Benju <b...@fastcastmedia.com> wrote:
> I did not attend Google I/O but as soon as the video "Google I/O 2009
> - Best Practices for Architecting GWT App" (http://www.youtube.com/ > watch?v=PDuhR18-EdM) was posted I reviewed it and was a bit confused
> by the idea of an EventBus.
For my part, I was pleased to see it as a best practice, as that's
what I'm thinking about for nearly a year (would require a huuuuuuge
refactoring of our app, so it's still "just an idea floating in the
air")
(I didn't watch the video, just looked at the slides)
> From what I can tell the idea is that UI widgets requiring data from
> the server are able to fire off requests for some form of data like
> "void getTransactionsForAccount(Account acct)" then at some unknown
> later time (ms to seconds ussually) when a response comes in from the
> RPC call the eventbus is what actually directly recives the data and
> then it is dispatched
Well, not necessarily, though yes, that's what they said at Google I/
O. One of the reasons is that there are probably more than a single
place where you use that same data in your app (in GMail it could be
the list of mails, the unread count for the "box" and/or label(s), and
the conversation view of course). That way, all places are informed,
wherever the initial request came from.
> Client UI: "Hey call some RPC method with these parameters, my
> AsyncCallback is this EventBus thing"
> ...some unknown time passes while the server does magic...
> Client Event Bus: "A response came in of type X/Y/Z I should fire an
> event to all interested parties"
> Client UI: "According to this event I just recieved some of my UI code
> needs to change"
> A few things are still very hazy for me...
> 1- What is missing here is when would the Client UI typically
> subscribe/unsubscribe from the event bus. If this were a desktop
> application I would simply use weak reference so I would not have to
> unsubscribe my UI manually to prevent a memory leak.
As with any event, I'd subscribe in the onLoad and unsubscribe in the
onUnload (would be even better if there was a destructor, so that even
when not attached to the DOM, your widget could receive events and
enter a "dirty" state, so that when it is attached again to the DOM it
knows if it has to refresh or not)
> 2- Is there some EventBus code I should be using that already exists
> in the GWT SDK? Is this the same code that is used for handling
> widget events like clicking a button?
Wasn't the code shown in the slides? (page #73 in the PDF, the event
bus is just a HandlerManager (GWT 1.6 and upwards))
> 3- Would you typically have one eventbus code for everything?
If your event bus is just a HandleManager as in the presentation's
sample code, then yes.
You would probably have one event bus (instance) for the whole app,
but you could also use some kind of HMVC (HMVP?) with "component-wide"
event buses.
(I'd rather have a single event bus though, and just use "component-
specific" events)
> 4- How does this tie in with the MVP pattern?
slide #73, he seems to be injecting the event bus into the presenter
(I'm not used to MVP but it seems pretty logical to me).
Thanks for the reply I have some further thoughts...
Looking at the source code for the event handling in GWT 1.6 it seems
the fundamental difference is as follows...
Old way with listeners
"I am adding this event listener to this component, when the listener
is triggered I know the source must be this component as it is the
only one added to the listener list"
New way with listeners
"I am adding this handler to this component, when something happens to
the component firing and event I will receive a notification, the
event itself will contain enough information such as the source or
custom properties which let me determine how to do something."
The more I think about the architecture outlined by the tech talk the
smarter it seems. For example by using this event driven application
you can swap out the UI much easier. Instead of having a button run
an RPC which on result runs code that that one component you have a
button trigger an RPC request which fires back to a central event
handler which then notifies all interested parties regardless of which
component initiated the request. When swapping out the UI for
browsers to an iPhone specific version it would be much much easier
to just have the exact same handlers and events but swap out the
components which render things to the display.
In the video at 27:3# Ray Ryan shows some MVP code which seems to tie
in with this it uses methods like "HasClickHandlers" to define the
interface for the UI. Does anybody know if this is typical of MVP or
a flavour cooked up by Google? I am having a hard time finding
quality resources describing MVP in the sort of context appropriate to
GWT.
On Jun 12, 7:39 am, Thomas Broyer <t.bro...@gmail.com> wrote:
> On 11 juin, 21:34, Benju <b...@fastcastmedia.com> wrote:
> > I did not attend Google I/O but as soon as the video "Google I/O 2009
> > - Best Practices for Architecting GWT App" (http://www.youtube.com/ > > watch?v=PDuhR18-EdM) was posted I reviewed it and was a bit confused
> > by the idea of an EventBus.
> For my part, I was pleased to see it as a best practice, as that's
> what I'm thinking about for nearly a year (would require a huuuuuuge
> refactoring of our app, so it's still "just an idea floating in the
> air")
> (I didn't watch the video, just looked at the slides)
> > From what I can tell the idea is that UI widgets requiring data from
> > the server are able to fire off requests for some form of data like
> > "void getTransactionsForAccount(Account acct)" then at some unknown
> > later time (ms to seconds ussually) when a response comes in from the
> > RPC call the eventbus is what actually directly recives the data and
> > then it is dispatched
> Well, not necessarily, though yes, that's what they said at Google I/
> O. One of the reasons is that there are probably more than a single
> place where you use that same data in your app (in GMail it could be
> the list of mails, the unread count for the "box" and/or label(s), and
> the conversation view of course). That way, all places are informed,
> wherever the initial request came from.
> > Client UI: "Hey call some RPC method with these parameters, my
> > AsyncCallback is this EventBus thing"
> > ...some unknown time passes while the server does magic...
> > Client Event Bus: "A response came in of type X/Y/Z I should fire an
> > event to all interested parties"
> > Client UI: "According to this event I just recieved some of my UI code
> > needs to change"
> > A few things are still very hazy for me...
> > 1- What is missing here is when would the Client UI typically
> > subscribe/unsubscribe from the event bus. If this were a desktop
> > application I would simply use weak reference so I would not have to
> > unsubscribe my UI manually to prevent a memory leak.
> As with any event, I'd subscribe in the onLoad and unsubscribe in the
> onUnload (would be even better if there was a destructor, so that even
> when not attached to the DOM, your widget could receive events and
> enter a "dirty" state, so that when it is attached again to the DOM it
> knows if it has to refresh or not)
> > 2- Is there some EventBus code I should be using that already exists
> > in the GWT SDK? Is this the same code that is used for handling
> > widget events like clicking a button?
> Wasn't the code shown in the slides? (page #73 in the PDF, the event
> bus is just a HandlerManager (GWT 1.6 and upwards))
> > 3- Would you typically have one eventbus code for everything?
> If your event bus is just a HandleManager as in the presentation's
> sample code, then yes.
> You would probably have one event bus (instance) for the whole app,
> but you could also use some kind of HMVC (HMVP?) with "component-wide"
> event buses.
> (I'd rather have a single event bus though, and just use "component-
> specific" events)
> > 4- How does this tie in with the MVP pattern?
> slide #73, he seems to be injecting the event bus into the presenter
> (I'm not used to MVP but it seems pretty logical to me).
Hi Benju,
The use of the HasClickHandlers interface (and other Handler interfaces) is
actually just a piece of event-driven architecture that GWT subscribes to
in the 1.6 event handler architecture. Basically, anything that implements
the HasClickHandlers interface must provide an implementation for the
methods that manage ClickHandlers added to it.
You can apply this principle more generally to your own components. For
example, a component that sends EmergencyEvacEvents or wraps a widget that
does so might also implement a HasEmergencyEvacHandlers. Whenever the
EmergencyEvacEvent occurs, components implementing HasEmergencyEvacHandlers
will be responsible for notifying each of the handlers to handle the
emergency event.
The following article also explains the same concept through a more complete
example (though the article is outdated as it pertains to GWT 1.4).
Although the article focuses on testing methodologies, the MVP pattern is
explained in code as it helps make it easy to isolate components that we
want to test and mock out any other components that it might interact with.
On Fri, Jun 12, 2009 at 10:19 AM, Benju <b...@fastcastmedia.com> wrote:
> Thanks for the reply I have some further thoughts...
> Looking at the source code for the event handling in GWT 1.6 it seems
> the fundamental difference is as follows...
> Old way with listeners
> "I am adding this event listener to this component, when the listener
> is triggered I know the source must be this component as it is the
> only one added to the listener list"
> New way with listeners
> "I am adding this handler to this component, when something happens to
> the component firing and event I will receive a notification, the
> event itself will contain enough information such as the source or
> custom properties which let me determine how to do something."
> The more I think about the architecture outlined by the tech talk the
> smarter it seems. For example by using this event driven application
> you can swap out the UI much easier. Instead of having a button run
> an RPC which on result runs code that that one component you have a
> button trigger an RPC request which fires back to a central event
> handler which then notifies all interested parties regardless of which
> component initiated the request. When swapping out the UI for
> browsers to an iPhone specific version it would be much much easier
> to just have the exact same handlers and events but swap out the
> components which render things to the display.
> In the video at 27:3# Ray Ryan shows some MVP code which seems to tie
> in with this it uses methods like "HasClickHandlers" to define the
> interface for the UI. Does anybody know if this is typical of MVP or
> a flavour cooked up by Google? I am having a hard time finding
> quality resources describing MVP in the sort of context appropriate to
> GWT.
> On Jun 12, 7:39 am, Thomas Broyer <t.bro...@gmail.com> wrote:
> > On 11 juin, 21:34, Benju <b...@fastcastmedia.com> wrote:
> > > I did not attend Google I/O but as soon as the video "Google I/O 2009
> > > - Best Practices for Architecting GWT App" (http://www.youtube.com/ > > > watch?v=PDuhR18-EdM) was posted I reviewed it and was a bit confused
> > > by the idea of an EventBus.
> > For my part, I was pleased to see it as a best practice, as that's
> > what I'm thinking about for nearly a year (would require a huuuuuuge
> > refactoring of our app, so it's still "just an idea floating in the
> > air")
> > (I didn't watch the video, just looked at the slides)
> > > From what I can tell the idea is that UI widgets requiring data from
> > > the server are able to fire off requests for some form of data like
> > > "void getTransactionsForAccount(Account acct)" then at some unknown
> > > later time (ms to seconds ussually) when a response comes in from the
> > > RPC call the eventbus is what actually directly recives the data and
> > > then it is dispatched
> > Well, not necessarily, though yes, that's what they said at Google I/
> > O. One of the reasons is that there are probably more than a single
> > place where you use that same data in your app (in GMail it could be
> > the list of mails, the unread count for the "box" and/or label(s), and
> > the conversation view of course). That way, all places are informed,
> > wherever the initial request came from.
> > > Client UI: "Hey call some RPC method with these parameters, my
> > > AsyncCallback is this EventBus thing"
> > > ...some unknown time passes while the server does magic...
> > > Client Event Bus: "A response came in of type X/Y/Z I should fire an
> > > event to all interested parties"
> > > Client UI: "According to this event I just recieved some of my UI code
> > > needs to change"
> > > A few things are still very hazy for me...
> > > 1- What is missing here is when would the Client UI typically
> > > subscribe/unsubscribe from the event bus. If this were a desktop
> > > application I would simply use weak reference so I would not have to
> > > unsubscribe my UI manually to prevent a memory leak.
> > As with any event, I'd subscribe in the onLoad and unsubscribe in the
> > onUnload (would be even better if there was a destructor, so that even
> > when not attached to the DOM, your widget could receive events and
> > enter a "dirty" state, so that when it is attached again to the DOM it
> > knows if it has to refresh or not)
> > > 2- Is there some EventBus code I should be using that already exists
> > > in the GWT SDK? Is this the same code that is used for handling
> > > widget events like clicking a button?
> > Wasn't the code shown in the slides? (page #73 in the PDF, the event
> > bus is just a HandlerManager (GWT 1.6 and upwards))
> > > 3- Would you typically have one eventbus code for everything?
> > If your event bus is just a HandleManager as in the presentation's
> > sample code, then yes.
> > You would probably have one event bus (instance) for the whole app,
> > but you could also use some kind of HMVC (HMVP?) with "component-wide"
> > event buses.
> > (I'd rather have a single event bus though, and just use "component-
> > specific" events)
> > > 4- How does this tie in with the MVP pattern?
> > slide #73, he seems to be injecting the event bus into the presenter
> > (I'm not used to MVP but it seems pretty logical to me).
EventBus(es) work incredible well. I got the chance to test the
pattern in a GWT 1.5 app and it proved to be "magical" :) However,
using a GWT 1.6 handler manager as a application wide event bus, as it
is stated at Google I/O 2009, seems to have some limitations. One of
the biggest I could spot is that the event source would always be some
top level component that instantiated the HandlerManager, not the
actual component that emited the event.
For the moment I'm sticking to my home brewed EventBus. What do you
think?
On 17 juin, 14:08, "cristian.vrabie" <cristian.vra...@gmail.com>
wrote:
> EventBus(es) work incredible well. I got the chance to test the
> pattern in a GWT 1.5 app and it proved to be "magical" :) However,
> using a GWT 1.6 handler manager as a application wide event bus, as it
> is stated at Google I/O 2009, seems to have some limitations. One of
> the biggest I could spot is that the event source would always be some
> top level component that instantiated the HandlerManager,
Or 'null' actually (from the code in the slides)
> not the
> actual component that emited the event.
> For the moment I'm sticking to my home brewed EventBus. What do you
> think?
Well, why would you need to know the source of the event? Wouldn't
that somehow defeat the use of an event bus in the beginning?
I mean, whether you clicked on a datagrid row or a dataviz plot (drill
down) or a "go up" link (drill up) or the browser's "back" or
"forward" button, you still mean "show X". Does it really matter where
the event comes from?
(as I'm not yet using an event bus, this is a real question; I might
be wrong assuming the actual event source isn't that important)
> > 1- What is missing here is when would the Client UI typically > > subscribe/unsubscribe from the event bus. If this were a desktop > > application I would simply use weak reference so I would not have to > > unsubscribe my UI manually to prevent a memory leak.
> As with any event, I'd subscribe in the onLoad and unsubscribe in the > onUnload (would be even better if there was a destructor, so that even > when not attached to the DOM, your widget could receive events and > enter a "dirty" state, so that when it is attached again to the DOM it > knows if it has to refresh or not)
I didn't understand that bit.
The presenter needs to subscribe but is just a class and doesn't have an onUnload method. Even if you make it a widget, having subscribed, since the eventbus has a reference to it, you won't get an unload.
> > > 1- What is missing here is when would the Client UI typically
> > > subscribe/unsubscribe from the event bus. If this were a desktop
> > > application I would simply use weak reference so I would not have to
> > > unsubscribe my UI manually to prevent a memory leak.
> > As with any event, I'd subscribe in the onLoad and unsubscribe in the
> > onUnload (would be even better if there was a destructor, so that even
> > when not attached to the DOM, your widget could receive events and
> > enter a "dirty" state, so that when it is attached again to the DOM it
> > knows if it has to refresh or not)
> I didn't understand that bit.
> The presenter needs to subscribe but is just a class and doesn't have an
> onUnload method.
Right!
(couldn't we make the presenters all have onLoad/onUnload methods to
be called by other components when they make use of a presenter; in
the Google I/O slides, the presenter as a method go(Widget) which is
almost equivalent to Widget::onLoad, what happens when you don't need
the component any more, it must have some other method that would be
similar to Widget::onUnload, no? of course, it would mean that
developers have to make sure they call that onUnload method when they
no longer need a component; some asserts in a window.onunload could
make it easier to discover those leaks: the eventbus shouldn't have
any subscriber left. Did I say I'm not really used to MVC/MVP?)
> Even if you make it a widget, having subscribed, since the
> eventbus has a reference to it, you won't get an unload.
This I don't understand, onUnload is called by the parent widget
(through onDetach) when you remove its child (and it thus is detached
from the DOM). Whether the eventbus has a reference to the widget is
orthogonal.
> On 18 juin, 18:01, Ian Bambury < ianbamb...@gmail.com> wrote: > > 2009/6/12 Thomas Broyer <t.bro...@gmail.com>
> > > As with any event, I'd subscribe in the onLoad and unsubscribe in the > > > onUnload (would be even better if there was a destructor, so that even > > > when not attached to the DOM, your widget could receive events and > > > enter a "dirty" state, so that when it is attached again to the DOM it > > > knows if it has to refresh or not)
> > I didn't understand that bit.
> > The presenter needs to subscribe but is just a class and doesn't have an > > onUnload method.
> Right! > (couldn't we make the presenters all have onLoad/onUnload methods to > be called by other components when they make use of a presenter; in > the Google I/O slides, the presenter as a method go(Widget) which is > almost equivalent to Widget::onLoad, what happens when you don't need > the component any more, it must have some other method that would be > similar to Widget::onUnload, no? of course, it would mean that > developers have to make sure they call that onUnload method when they > no longer need a component; some asserts in a window.onunload could > make it easier to discover those leaks: the eventbus shouldn't have > any subscriber left. Did I say I'm not really used to MVC/MVP?)
That was my point, really, that there is no method you can just shove the unsubscribe into and have it just happen. You have to create one (calling it what you will, unload(), teardown(), destroy(), etc) and hope the developers will remember to call it.
> > Even if you make it a widget, having subscribed, since the > > eventbus has a reference to it, you won't get an unload.
> This I don't understand, onUnload is called by the parent widget > (through onDetach) when you remove its child (and it thus is detached > from the DOM). Whether the eventbus has a reference to the widget is > orthogonal.
I didn't realise that widgets were bird-watchers! :-)
Maybe an example would help explain the problem (either the problem in general, or my problem).
There's an eventbus which is just a singleton for a HandlerManager with some methods for it for requesting data and for registering handlers. The requests might be batched and/or the data might be cached or retrieved from the server, it doesn't matter. If getTemperature() is called, some time later the data will arrive and all the TemperatureUpdateHandlers will get the onTemperatureUpdate(TemperatureUpdateEvent event) methods called.
Anything anywhere requests a current temperature, then everything interested gets told when the news arrives.
The TemperatureAsTextView class extends Composite and is just a label with the temperature in text
The TemperatureAsText class is the presenter. It extends nothing.
To use all this, you need to create a TemperatureAsTextView object, passing it the panel it is to add itself to.
TemperatureAsTextView view = new TemperatureAsTextView (panel);
The view adds itself to the panel.
In some way or another, the view is bound to an instance of the presenter. The view might create the presenter for example. Let's stick with that.
So we have a view on a panel being controlled by a presenter. And we have a bus which lets us register TemperatureUpdateHandlers and also request the temperature.
The presenter registers itself with the bus.
This is my problem, I can't see a way to automatically unregister the presenter. You have to hope the programmer remembers to do it (via whatever name you chose - unload/destroy/zap...) You can't easily make it safe.
You can't register the view or any part of it because the whole idea is that the logic is in the presenter, and you can't have the presenter be part of the view because that is against the principles of MVP
So you have to hope the programmer knows to and remembers to call the method to remove the handlers.
On Thu, Jun 18, 2009 at 3:56 PM, Ian Bambury<ianbamb...@gmail.com> wrote: > 2009/6/18 Thomas Broyer <t.bro...@gmail.com> >> This I don't understand, onUnload is called by the parent widget >> (through onDetach) when you remove its child (and it thus is detached >> from the DOM). Whether the eventbus has a reference to the widget is >> orthogonal.
> I didn't realise that widgets were bird-watchers! :-)
Do you mean ornithologists?
Anyway, I think Thomas is talking about the presenter either being a widget or wrapping a widget. Widgets are notified when their elements are removed from the DOM, so you could conceivable make the presenter aware of the DOM detachment and use that as a convenient time to "get off the bus". As someone mentioned, though, if the widget is detached from the DOM but still "alive" then it might get reattached at some future time. If there was a real destructor then detached widgets could continue to track state until destruction so they'd be up to date when reattached. Of course, if wishes were horses....
> On Thu, Jun 18, 2009 at 3:56 PM, Ian Bambury<ianbamb...@gmail.com> wrote: > > 2009/6/18 Thomas Broyer <t.bro...@gmail.com> > >> Whether the eventbus has a reference to the widget is > >> orthogonal.
> > I didn't realise that widgets were bird-watchers! :-)
> Do you mean ornithologists?
Aren't they eye-doctors?
> Anyway, I think Thomas is talking about the presenter either being a > widget or wrapping a widget. Widgets are notified when their elements > are removed from the DOM, so you could conceivable make the presenter > aware of the DOM detachment and use that as a convenient time to "get > off the bus".
My (limited) understanding of what Ray Ryan was saying (and what I understand of MVP) is that the presenter is completely separated from the DOM elements (in order to facilitate testing, and because the view is solely responsible for the view so you can swap views in and out as you please). E.g. the example of a presenter would be something like this:
The presenter isn't (or shouldn't be) a widget. It doesn't get notified of any attachment or detachment because it has no way to know. It might be swapping between two different views (?) and in any case, even if the view is detached from the DOM, you may want it to be updated in case the user switches back to it.
> That was my point, really, that there is no method you can just shove the
> unsubscribe into and have it just happen. You have to create one (calling it
> what you will, unload(), teardown(), destroy(), etc) and hope the developers
> will remember to call it.
[...]
> The presenter registers itself with the bus.
> This is my problem, I can't see a way to automatically unregister the
> presenter. You have to hope the programmer remembers to do it (via whatever
> name you chose - unload/destroy/zap...) You can't easily make it safe.
As I said, you can at least tell the programmer he didn't "dispose"
the presenter before the page unloads. That's better than nothing...
> You can't register the view or any part of it because the whole idea is that
> the logic is in the presenter, and you can't have the presenter be part of
> the view because that is against the principles of MVP
> So you have to hope the programmer knows to and remembers to call the method
> to remove the handlers.
> And that is not ideal in my book.
That's the way it is in a world without destructors and weak
references... that's why onLoad/onUnload is baked into Widget and you
have to call RootPanel.detachNow or RootPanel.detachOnWindowClose
(baked into RootPanel and the widget's wrap(), but if write a wrap()
method yourself, don't forget to call detachOnWindowClose or you'll
have memory leaks).
I personally have no problem with having a MVP micro-framework and
having to extend a Presenter class with those onLoad/onUnload and
detachOnWindowClose (as a last resort when you don't explicitly
dispose the component when you no longer need it); moreover if you can
spot missing disposals at dev/testing time.
On Thu, Jun 18, 2009 at 5:38 PM, Ian Bambury<ianbamb...@gmail.com> wrote: > 2009/6/19 Ian Petersen <ispet...@gmail.com>
>> On Thu, Jun 18, 2009 at 3:56 PM, Ian Bambury<ianbamb...@gmail.com> wrote: >> > 2009/6/18 Thomas Broyer <t.bro...@gmail.com> >> >> Whether the eventbus has a reference to the widget is >> >> orthogonal.
>> > I didn't realise that widgets were bird-watchers! :-)
>> Do you mean ornithologists?
> Aren't they eye-doctors?
Oh! You mean opthamologists! :D
>> Anyway, I think Thomas is talking about the presenter either being a >> widget or wrapping a widget. Widgets are notified when their elements >> are removed from the DOM, so you could conceivable make the presenter >> aware of the DOM detachment and use that as a convenient time to "get >> off the bus".
> My (limited) understanding of what Ray Ryan was saying (and what I > understand of MVP) is that the presenter is completely separated from the > DOM elements (in order to facilitate testing, and because the view is solely > responsible for the view so you can swap views in and out as you please).
Your understanding of MVP is probably less limited than mine--I assumed it was a riff on MVC. Anyway, couldn't you design an MVP framework to include "I'm done paying attention to changes" events, and use onUnload to trigger them when the presenter is using a widget and use some other means when it's using something besides a widget? Maybe we've drifted off into the weeds...
Finally found a thread talking about this presentation. It is very
interesting for me as well.
Thomas, you mentioned slide #73, actually I have some question about
this. In this slide, from my point of view, both PhoneEditWidget and
ContactWidget are just Views in MVP. Phone Editor is Presenter in MVP.
So is ContactViewer a presenter as well? If so, I understand that it
passes Event Bus into Contact Viewer, why it doesn't pass the same
Event Bus into PhoneEditor?
For me, I am still not very clear about how this event bus works.
Thanks,
On Jun 12, 9:39 am, Thomas Broyer <t.bro...@gmail.com> wrote:
> On 11 juin, 21:34, Benju <b...@fastcastmedia.com> wrote:
> > I did not attend Google I/O but as soon as the video "Google I/O 2009
> > - Best Practices for Architecting GWT App" (http://www.youtube.com/ > > watch?v=PDuhR18-EdM) was posted I reviewed it and was a bit confused
> > by the idea of an EventBus.
> For my part, I was pleased to see it as a best practice, as that's
> what I'm thinking about for nearly a year (would require a huuuuuuge
> refactoring of our app, so it's still "just an idea floating in the
> air")
> (I didn't watch the video, just looked at the slides)
> > From what I can tell the idea is that UI widgets requiring data from
> > the server are able to fire off requests for some form of data like
> > "void getTransactionsForAccount(Account acct)" then at some unknown
> > later time (ms to seconds ussually) when a response comes in from the
> > RPC call the eventbus is what actually directly recives the data and
> > then it is dispatched
> Well, not necessarily, though yes, that's what they said at Google I/
> O. One of the reasons is that there are probably more than a single
> place where you use that same data in your app (in GMail it could be
> the list of mails, the unread count for the "box" and/or label(s), and
> the conversation view of course). That way, all places are informed,
> wherever the initial request came from.
> > Client UI: "Hey call some RPC method with these parameters, my
> > AsyncCallback is this EventBus thing"
> > ...some unknown time passes while the server does magic...
> > Client Event Bus: "A response came in of type X/Y/Z I should fire an
> > event to all interested parties"
> > Client UI: "According to this event I just recieved some of my UI code
> > needs to change"
> > A few things are still very hazy for me...
> > 1- What is missing here is when would the Client UI typically
> > subscribe/unsubscribe from the event bus. If this were a desktop
> > application I would simply use weak reference so I would not have to
> > unsubscribe my UI manually to prevent a memory leak.
> As with any event, I'd subscribe in the onLoad and unsubscribe in the
> onUnload (would be even better if there was a destructor, so that even
> when not attached to the DOM, your widget could receive events and
> enter a "dirty" state, so that when it is attached again to the DOM it
> knows if it has to refresh or not)
> > 2- Is there some EventBus code I should be using that already exists
> > in the GWT SDK? Is this the same code that is used for handling
> > widget events like clicking a button?
> Wasn't the code shown in the slides? (page #73 in the PDF, the event
> bus is just a HandlerManager (GWT 1.6 and upwards))
> > 3- Would you typically have one eventbus code for everything?
> If your event bus is just a HandleManager as in the presentation's
> sample code, then yes.
> You would probably have one event bus (instance) for the whole app,
> but you could also use some kind of HMVC (HMVP?) with "component-wide"
> event buses.
> (I'd rather have a single event bus though, and just use "component-
> specific" events)
> > 4- How does this tie in with the MVP pattern?
> slide #73, he seems to be injecting the event bus into the presenter
> (I'm not used to MVP but it seems pretty logical to me).
The PhoneEditor doesn't need the event bus since it doesn't respond to any
events.
The ContactWidget needs the event bus in case the details change in real
time, then it can update itself.
If you (the user) want to change the phone number while you are looking at
the contact details (the ContactWidget is the view) then you use the
PhoneEditor (which shows the PhoneEditWidget).
Basically, you're looking at a phone number display which will update if the
phone number changes. If you want to change it, you get a popup editor that
lets you do that.
The phone number display subscribes to updates so it will be up-to-date. The
popup editor gets populated and then you edit it. You don't want the popup
to update while you are putting the new number in so it doesn't do the
update thing.
So you are displaying the actual phone number, you decide to update it and
get the popup. You put the new number in the popup and submit it
(the PhoneEditor knows how to update, it was passed the rpcService).
The data (i.e. the model) gets updated and feeds the change back. This
feedback is to the event bus which fires an event to tell every interested
widget that the phone number for contact nnn has changed. Including the
display you were just looking at.
The way they have done it in the presentation is 'optimistic'. I.e. they
update the screen immediately, without waiting for the data to do the round
trip. If the update fails and the resulting error doesn't get back, then
your screen is showing different data to the model. Ideally, you should
change the phone number label to 'updating' and let the feedback put the new
number in there. That way the screen has more of a chance of showing the
right information (there's still a chance that the update works and the data
doesn't get fed back, but at least then the label shows 'updating' rather
than out-of-sync information.
I rather suspect that hasn't clarified anything :-)
> Finally found a thread talking about this presentation. It is very
> interesting for me as well.
> Thomas, you mentioned slide #73, actually I have some question about
> this. In this slide, from my point of view, both PhoneEditWidget and
> ContactWidget are just Views in MVP. Phone Editor is Presenter in MVP.
> So is ContactViewer a presenter as well? If so, I understand that it
> passes Event Bus into Contact Viewer, why it doesn't pass the same
> Event Bus into PhoneEditor?
> For me, I am still not very clear about how this event bus works.
> Thanks,
> On Jun 12, 9:39 am, Thomas Broyer <t.bro...@gmail.com> wrote:
> > On 11 juin, 21:34, Benju <b...@fastcastmedia.com> wrote:
> > > I did not attend Google I/O but as soon as the video "Google I/O 2009
> > > - Best Practices for Architecting GWT App" (http://www.youtube.com/ > > > watch?v=PDuhR18-EdM) was posted I reviewed it and was a bit confused
> > > by the idea of an EventBus.
> > For my part, I was pleased to see it as a best practice, as that's
> > what I'm thinking about for nearly a year (would require a huuuuuuge
> > refactoring of our app, so it's still "just an idea floating in the
> > air")
> > (I didn't watch the video, just looked at the slides)
> > > From what I can tell the idea is that UI widgets requiring data from
> > > the server are able to fire off requests for some form of data like
> > > "void getTransactionsForAccount(Account acct)" then at some unknown
> > > later time (ms to seconds ussually) when a response comes in from the
> > > RPC call the eventbus is what actually directly recives the data and
> > > then it is dispatched
> > Well, not necessarily, though yes, that's what they said at Google I/
> > O. One of the reasons is that there are probably more than a single
> > place where you use that same data in your app (in GMail it could be
> > the list of mails, the unread count for the "box" and/or label(s), and
> > the conversation view of course). That way, all places are informed,
> > wherever the initial request came from.
> > > Client UI: "Hey call some RPC method with these parameters, my
> > > AsyncCallback is this EventBus thing"
> > > ...some unknown time passes while the server does magic...
> > > Client Event Bus: "A response came in of type X/Y/Z I should fire an
> > > event to all interested parties"
> > > Client UI: "According to this event I just recieved some of my UI code
> > > needs to change"
> > > A few things are still very hazy for me...
> > > 1- What is missing here is when would the Client UI typically
> > > subscribe/unsubscribe from the event bus. If this were a desktop
> > > application I would simply use weak reference so I would not have to
> > > unsubscribe my UI manually to prevent a memory leak.
> > As with any event, I'd subscribe in the onLoad and unsubscribe in the
> > onUnload (would be even better if there was a destructor, so that even
> > when not attached to the DOM, your widget could receive events and
> > enter a "dirty" state, so that when it is attached again to the DOM it
> > knows if it has to refresh or not)
> > > 2- Is there some EventBus code I should be using that already exists
> > > in the GWT SDK? Is this the same code that is used for handling
> > > widget events like clicking a button?
> > Wasn't the code shown in the slides? (page #73 in the PDF, the event
> > bus is just a HandlerManager (GWT 1.6 and upwards))
> > > 3- Would you typically have one eventbus code for everything?
> > If your event bus is just a HandleManager as in the presentation's
> > sample code, then yes.
> > You would probably have one event bus (instance) for the whole app,
> > but you could also use some kind of HMVC (HMVP?) with "component-wide"
> > event buses.
> > (I'd rather have a single event bus though, and just use "component-
> > specific" events)
> > > 4- How does this tie in with the MVP pattern?
> > slide #73, he seems to be injecting the event bus into the presenter
> > (I'm not used to MVP but it seems pretty logical to me).
> The PhoneEditor doesn't need the event bus since it doesn't respond to any
> events.
> The ContactWidget needs the event bus in case the details change in real
> time, then it can update itself.
> If you (the user) want to change the phone number while you are looking at
> the contact details (the ContactWidget is the view) then you use the
> PhoneEditor (which shows the PhoneEditWidget).
> Basically, you're looking at a phone number display which will update if the
> phone number changes. If you want to change it, you get a popup editor that
> lets you do that.
> The phone number display subscribes to updates so it will be up-to-date. The
> popup editor gets populated and then you edit it. You don't want the popup
> to update while you are putting the new number in so it doesn't do the
> update thing.
> So you are displaying the actual phone number, you decide to update it and
> get the popup. You put the new number in the popup and submit it
> (the PhoneEditor knows how to update, it was passed the rpcService).
> The data (i.e. the model) gets updated and feeds the change back. This
> feedback is to the event bus which fires an event to tell every interested
> widget that the phone number for contact nnn has changed. Including the
> display you were just looking at.
> The way they have done it in the presentation is 'optimistic'. I.e. they
> update the screen immediately, without waiting for the data to do the round
> trip. If the update fails and the resulting error doesn't get back, then
> your screen is showing different data to the model. Ideally, you should
> change the phone number label to 'updating' and let the feedback put the new
> number in there. That way the screen has more of a chance of showing the
> right information (there's still a chance that the update works and the data
> doesn't get fed back, but at least then the label shows 'updating' rather
> than out-of-sync information.
> I rather suspect that hasn't clarified anything :-)
> > Finally found a thread talking about this presentation. It is very
> > interesting for me as well.
> > Thomas, you mentioned slide #73, actually I have some question about
> > this. In this slide, from my point of view, both PhoneEditWidget and
> > ContactWidget are just Views in MVP. Phone Editor is Presenter in MVP.
> > So is ContactViewer a presenter as well? If so, I understand that it
> > passes Event Bus into Contact Viewer, why it doesn't pass the same
> > Event Bus into PhoneEditor?
> > For me, I am still not very clear about how this event bus works.
> > Thanks,
> > On Jun 12, 9:39 am, Thomas Broyer <t.bro...@gmail.com> wrote:
> > > On 11 juin, 21:34, Benju <b...@fastcastmedia.com> wrote:
> > > > I did not attend Google I/O but as soon as the video "Google I/O 2009
> > > > - Best Practices for Architecting GWT App" (http://www.youtube.com/ > > > > watch?v=PDuhR18-EdM) was posted I reviewed it and was a bit confused
> > > > by the idea of an EventBus.
> > > For my part, I was pleased to see it as a best practice, as that's
> > > what I'm thinking about for nearly a year (would require a huuuuuuge
> > > refactoring of our app, so it's still "just an idea floating in the
> > > air")
> > > (I didn't watch the video, just looked at the slides)
> > > > From what I can tell the idea is that UI widgets requiring data from
> > > > the server are able to fire off requests for some form of data like
> > > > "void getTransactionsForAccount(Account acct)" then at some unknown
> > > > later time (ms to seconds ussually) when a response comes in from the
> > > > RPC call the eventbus is what actually directly recives the data and
> > > > then it is dispatched
> > > Well, not necessarily, though yes, that's what they said at Google I/
> > > O. One of the reasons is that there are probably more than a single
> > > place where you use that same data in your app (in GMail it could be
> > > the list of mails, the unread count for the "box" and/or label(s), and
> > > the conversation view of course). That way, all places are informed,
> > > wherever the initial request came from.
> > > > Client UI: "Hey call some RPC method with these parameters, my
> > > > AsyncCallback is this EventBus thing"
> > > > ...some unknown time passes while the server does magic...
> > > > Client Event Bus: "A response came in of type X/Y/Z I should fire an
> > > > event to all interested parties"
> > > > Client UI: "According to this event I just recieved some of my UI code
> > > > needs to change"
> > > > A few things are still very hazy for me...
> > > > 1- What is missing here is when would the Client UI typically
> > > > subscribe/unsubscribe from the event bus. If this were a desktop
> > > > application I would simply use weak reference so I would not have to
> > > > unsubscribe my UI manually to prevent a memory leak.
> > > As with any event, I'd subscribe in the onLoad and unsubscribe in the
> > > onUnload (would be even better if there was a destructor, so that even
> > > when not attached to the DOM, your widget could receive events and
> > > enter a "dirty" state, so that when it is attached again to the DOM it
> > > knows if it has to refresh or not)
> > > > 2- Is there some EventBus code I should be using that already exists
> > > > in the GWT SDK? Is this the same code that is used for handling
> > > > widget events like clicking a button?
> > > Wasn't the code shown in the slides? (page #73 in the PDF, the event
> > > bus is just a HandlerManager (GWT 1.6 and upwards))
> > > > 3- Would you typically have one eventbus code for everything?
> > > If your event bus is just a HandleManager as in the presentation's
> > > sample code, then yes.
> > > You would probably have one event bus (instance) for the whole app,
> > > but you could also use some kind of HMVC (HMVP?) with "component-wide"
> > > event buses.
> > > (I'd rather have a single event bus though, and just use "component-
> > > specific" events)
> > > > 4- How does this tie in with the MVP pattern?
> > > slide #73, he seems to be injecting the event bus into the presenter
> > > (I'm not used to MVP but it seems pretty logical to me).
On Jun 20, 1:33 am, Ian Petersen <ispet...@gmail.com> wrote:
> > My (limited) understanding of what Ray Ryan was saying (and what I
> > understand of MVP) is that the presenter is completely separated from the
> > DOM elements (in order to facilitate testing, and because the view is solely
> > responsible for the view so you can swap views in and out as you please).
> Your understanding of MVP is probably less limited than mine--I
> assumed it was a riff on MVC. Anyway, couldn't you design an MVP
> framework to include "I'm done paying attention to changes" events,
> and use onUnload to trigger them when the presenter is using a widget
> and use some other means when it's using something besides a widget?
> Maybe we've drifted off into the weeds...
I'm also still wrapping my head around the presentation, but I agree-
Presenter objects are separate from the Widget hierarchy - the just
connect via the Widgets/interfaces exposed in the Display interface.
I think the way to have Presenter objects clean up after themselves
would be to have a Presenter superclass that registers itself with the
event bus to listen for 'Window Closing' events, and cleans itself up.
The main app would have an event listener for 'document.onUnload'
events that notifies the event bus and any Presenters can then tidy
up.
I'd love to see some code for the PlaceManager though...
I am currious what whould be the performance impact of removing
listeners in the onUnload method instead of leaving them there
(assuming we don't create memory leaks).
I mean: in my case I have a left menu that shows screens on the right
side. These screens are a bit complex and contains much logic that is
contained in the presenter following the MVP pattern. Once the display
is created I leave it created and the user merely swiches screens when
going to another screen.
I don't remove any (local) listeners when switching screens, but could
do that and I am currious if removing (deactivating) about 10
listeners would result in a better performance. I mean: suppose I have
20 menu items, with about 10 listeners, I would have 200 listeners
(own and direct gwt listeners). But when I remove them, I would never
have more then around 10 listeners active as the others are removed
when the screen isn't visible.
The only thing is that, like mentioned above, I have to inform my
presenter about the onUnload event, and often more fine-grained
components that contain the listener (that are connected to the
presenter). This isn't always very elegant I think.
Talking about the event bus. I use a MVC implementation which is
similar to the one used by mygwt (when it was still called mygwt), for
the course grain events, like start app, load app data, init app, etc.
And use the MVP for the fine (local) grain events. This seems to work
fine in my case.
Example: I have about 10 course grain controllers like ControllerMenu,
ControllerHeader, etc... These will contain their own child
controllers that are well controlled by their parent. The controllers
are connected through a super Controller class to an event dispatcher
(the event bus). The controller will register the interested events
and get informed when the event happens (example: app init, load app
data). The dispatcher will wait dispatching events when needed like
when data is loaded from the server (kind of the Handler Manager has
an intern queue to overcome concurrent access problems).
The controller always has at least one View implementation class that
is responsible of creating the screen. The controller will forward his
event to his View when needed.
Just a brief overview how I use the "event bus" system.
I am not so crazy about a global handlermanager as event bus as it's
very sensitive to memory leaks as we don't have weak references in
javascript.
I also have a global model that contains some global data, like member/
partner name, etc... But I don't permit any listener subscription to
this data. I had this in the past, but it's too tricky and if a
developer forget to clean up his listener you have a memory leak (like
mentioned above).
I "solved" this by pushing a Global data change event on my event bus
to the controller that are interested in this event. The controller
will push it to the view and then the view can do whatever he want and
have his own listeners if he wants.
This works in my case, as: I have a fixed number of controllers so the
number of "global listeners" can't grow. Note that memory leaks can
still exists, but then only in a local view, such that the damage is
much less severe. Also because I am planning to remove the complete
view in the future when too many views exists I won't the problem at
all. I mean: the view will automatically be created if it doesn't
exist.
I may be missing something from the original presentation, but your
description of a limited number of Controllers interacting with your
event bus seems identical in principle to a limited number of
presenters interacting with the event bus (as in Ray Ryan's talk).
Your limit on the number of controllers could be made as a similar
limit on Presenters, and the concepts wouldn't really change (other
than the location of where the event bus lives).
My take away on the event bus is that its still up to the programmer
to exercise rigor in cleaning up references. With regard to the MVP
design pattern and an event bus, there would seem to be a few ways to
handle cleaning up Handlers on unload or navigation: your application
could put all event bus handlers in the Presenter and use a
Windows.ClosingHandler to place the Windows.Closing event on the event
bus for all interested Presenters to handle, or you could supply an
event between your Custom Widget/View to transfer the unload/detach
event to the Presenter (note, this seems to follow the practice of
passing events from View to Presenter as described in the talk.
I do not claim to completely understand all aspects, but I like the
concept of decoupling that actually seems a bit more logical, and the
separation and testing capabilities afford by the MVP design pattern
and Event Bus.
Yep, you are right, it's just with my MVC setup you can't just
subscribe to the bus in with a global event handler you can.
For me, it would be ur second option as the Windows.Close event is way
to course grain for me as the application is too complex and there
happens too much for a long time, such that memory leaks can already
have caused big problems before this event occurs.
> Yep, you are right, it's just with my MVC setup you can't just
> subscribe to the bus in with a global event handler you can.
> For me, it would be ur second option as the Windows.Close event is way
> to course grain for me as the application is too complex and there
> happens too much for a long time, such that memory leaks can already
> have caused big problems before this event occurs.
Now I look at this, I realize that for this example, the phoneEditor
is a pop-up.
But the case is still valid in general terms.
The widget implements a widgetInterface, and to bind that widget to
the rootpanel, a cast is necessary in the go() function. How do I
avoid the cast or if I don't, is this best practice?
On 25 jun, 13:02, mabogie <mabo...@gmail.com> wrote:
> I'm having trouble with one other thing in that presentation.
> In the end of theMVPpart, Ray concludes with
> contactViewer.go(RootPanel.get());
> But, since phoneEditor is a presenter, and display a interface, to
> bind the widget to the rootpanel one needs to cast it:
> rootPanel.add((Widget)phoneEditor.display);
> I want to avoid casting this, how should I do that?
> On 23 jun, 08:59, Ed <post2edb...@hotmail.com> wrote:
> > He Jason,
> > Yep, you are right, it's just with my MVC setup you can't just
> > subscribe to the bus in with a global event handler you can.
> > For me, it would be ur second option as the Windows.Close event is way
> > to course grain for me as the application is too complex and there
> > happens too much for a long time, such that memory leaks can already
> > have caused big problems before this event occurs.
May i know will the sample app(using MVP + command pattern+ EventBus)
for the talk will be uploaded any sooner? I think many are asking the
same questions.
Does anyone have a working MVP/Eventbus sample of something simple like the PhoneEditor? I don't think I'm doing it right. The code from the IO presentation leaves out enough details so that I'm not sure what to do. For instance, in my Presenter.class,
I have something like this: public class Presenter { ... private Display display; interface Display { HasClickHandlers getSaveButton(); HasClickHandlers getCancelButton(); HasClickHandlers getNumberField(); HasClickHandlers getLabelPicker(); } void editPhone(Phone phone) { this.phone = Phone.from(phone); display.getNumberField().setValue(phone.getNumber()); display.getLabelPicker().setValue(phone.getLabel()); } ...
}
Obviously, a HasClickHandlers object doesn't have a setValue method. It doesn't feel like I should be casting to the widget here, since we went through all the trouble of using the Display interface.
I started looking at Mvp4g, but it seems to go off on a tangent with a code generation class to wire up presenters and views via xml. http://code.google.com/p/mvp4g/ It's also intertwined with some mvc4g classes.
I just want something basic that works, so I can seed my project from there. A minimalist, working command style RPC example would be nice too. Anyone? If you're in the DC area, I'll buy you a drink!
I left out the model (Phone class here) and the command pattern, since
I'm not using it yet.
For your comment on the casting: I'm having trouble with that too.
When I want to attach the widgets to the root panel or whatever other
panel, I can't do anything but cast them. But nobody seems to have a
good solution...
On 29 jun, 23:13, Daniel Jue <teamp...@gmail.com> wrote:
> Does anyone have a working MVP/Eventbus sample of something simple
> like the PhoneEditor?
> I don't think I'm doing it right. The code from the IO presentation
> leaves out enough details so that I'm not sure what to do.
> For instance, in my Presenter.class,
> Obviously, a HasClickHandlers object doesn't have a setValue method.
> It doesn't feel like I should be casting to the widget here, since we
> went through all the trouble of using the Display interface.
> I started looking at Mvp4g, but it seems to go off on a tangent with a
> code generation class to wire up presenters and views via xml.http://code.google.com/p/mvp4g/ > It's also intertwined with some mvc4g classes.
> I just want something basic that works, so I can seed my project from
> there. A minimalist, working command style RPC example would be nice
> too.
> Anyone? If you're in the DC area, I'll buy you a drink!