In my experience in supporting users of the EventBus, in both the open source world and in professional teams, weak references are not something to be feared. This is because: 1) Weak references fail fast. 2) Weak reference semantics can be documented. Make the API's clear, make the doc clear, make the examples clear. Document the anti-pattern, put it in the FAQ. 3) Assume your users are smarter than you might think. WeakReferences are pretty easy to understand. Even if a rookie doesn't understand them, you can make it a teachable moment. 4) WeakReferences are clean and simple. Managaging listener lifecycle is like managing memory in C- it a buggy job that sucks productivity and bloats code. 5) In the 6 years of the EventBus' life, only one user posted a "this doesn't work" question because they didn't RTFM.
Greg, you didn't detail many of the "number of issues" with WeakReferences, so I'm not sure what the perception is, but in my experience WeakReferences are better since the lifecycle of the listener is generally (90%+) equivalent to the lifecycle of the component that defines the listener. One issue mentioned is the use of an anonymous inner class (a questionable pattern anyway), but when annotations are available users generally use that more terse route rather than using an anonymous class. When developers use the anonymous class anti-pattern, it fails quickly and they change it - often forcing them to think about garbage collection in their apps, which is a great thing. The corollary of using .subscribe(new XXXSubscriber()) is even worse when using strong references - without a reference it's impossible to clean up. I think the encapsulation argument is extremely weak. Firstly, most UI developers don't care too much about building extensible classes, but even when they do, I prefer the opposite effect: Each method that is annotated as a subscriber becomes part of the contract of the component. This is a form of programming by contract that is very powerful. It says, "whenever this event is fired, I'm going to call this method." Derived classes can manipulate the behavior as needed. Hiding it is equivalent to the static final listeners that are all over the Swing framework - it stops extension and customization in it's tracks. I went into this pub/sub programming-by-contract method quite a bit in the article<http://eventbus.org/confluence/pages/viewpage.action?pageId=819222#EventBus%26ApachePivotorRefactoringUIstoUsePub-Sub-Contracts>I wrote on the EventBus+Pivot. Lastly, if you don't like that idea, you can easily create private fields that are listeners. The best argument for weak references is that strong references generally suck. Strong references have the opposite effects listed above: 1) Strong references cause memory "leaks" that don't fail fast. They fail very slowly and insiduously. They are often not caught until production. 2) Strong reference issues are hard to document. 3) Even smart, experienced developers wind up wasting hours or days tracking down memory leaks before they find the culprit. 4) Lifecycle management of listeners is not always easy. It is error prone and bloats code. Even in the easy cases, it's easily forgotten and difficult to test for. Note: The Spring ActionScript EventBus shifted (is shifting?) from defaulting to strong to defaulting to weak. I look forward to seeing how the MessageBus API develops. Michael Bushe Principal Bushe Enterprises, Inc. [email protected] www.bushe.com www.mindfulsoftware.com www.eventbus.org On Mon, Jun 21, 2010 at 4:33 PM, aappddeevv <[email protected]> wrote: > I think that's fair to do. > > -----Original Message----- > From: Greg Brown [mailto:[email protected]] > Sent: Monday, June 21, 2010 2:11 PM > To: [email protected] > Subject: Re: [jira] Commented: (PIVOT-535) Add a @MessageListener > annotation > and an annotation processor for application context message listener > > It doesn't necessarily need to be used by other parts of the framework to > go > in pivot-core. It just needs to be generally useful and not have any > dependencies on the other libraries. > > I'm not sure what else, if anything, I would want it to do - it is really > only meant to provide simple intra-application messaging services without a > lot of overhead or the need for an external library. > > One advantage to moving it to org.apache.pivot.util is that listener > implementations would not require so much typing (MessageBusListener is > shorter than ApplicationContextMessageListener). Also, since (like > WTKXSerializer) it isn't strictly dependent on WTK, it probably does not > belong there. > > G > > On Jun 21, 2010, at 11:53 AM, aappddeevv wrote: > > > Yes. But I would leave it there for now. For simple messaging it is > > sufficient. More thought is needed. My current thinking is that unless it > > used by pivot internally, and hence drives need & evolution, it could be > > better to use something else. > > > > > > -----Original Message----- > > From: Greg Brown [mailto:[email protected]] > > Sent: Monday, June 21, 2010 9:52 AM > > To: [email protected] > > Subject: Re: [jira] Commented: (PIVOT-535) Add a @MessageListener > annotation > > and an annotation processor for application context message listener > > > >> One thing I am finding is for annotations and auto-registering, that the > >> machinery dominates the actual messaging code in ApplicationContext. > > > > ApplicationContext is large, but the message handling code itself is > pretty > > small - it is just a few methods: > > > > subscribe() > > unsubscribe() > > sendMessage() > > queueMessage() > > > > I have actually been wondering if it might make sense to move it to a > core > > class, such as org.apache.pivot.util.MessageBus so that non-UI > applications > > can also use it. The only thing specific to WTK is queueMessage(), but > that > > could either remain in ApplicationContext and be implemented in terms of > > MessageBus, or it could potentially be eliminated - the code in that > method > > could easily be implemented at the application level. > > > >
