Talk:DesignObservablePattern

From JQuantLib

Jump to: navigation, search

This is the discussion about Observer/Observable pattern initially started by Srinivas. I transposed our emails here so you are able to get informed about our ideas and, of course, you are invited to participate.

RichardGomes 14:43, 15 March 2008 (UTC)




Richard,

Few comments on the api.

Ideally, Observable shouldn't expose notify trigger methods to the external world. To make the api cleaner, I suggest removing notifyObservers methods from Observable interface. Observable implementations can directly refer to DefaultObservable.notifyObserver methods. Thoughts ?

Attaching the patch with the modifcations. If you are ok with the changes i can check in the changes and also update api references in the project.

Also, any reason why we are using WeakReferences in DefaultObservable ? Is it to help with memory utilization ? i am concerned that it would introduce undeterministic behavior when there are no references to the observers other than observable. This would mean we have to dictate that the client has to hold onto the observer reference if they wish to get called. I think by default we should use regular references and provide WeakRefernceObservable impl that some Observable impls can use.

Thanks

-- Srinivas




Hi Srinivas,

Why Observable shouldn't expose notifyObservers? I'd say that it does make sense for a certain class which has a composition of an Observable... to not only control the life cycle of the Observable, but also trigger its functionalities, such as notifyObservers().

For your information... when I first adapted the code from the original author, I've tried to mimic Observable from JDK, in order to keep the maximum resemblance to it as possible. In the end, I removed methods that QuantLib/C++ was not using at all. I'm not sattisfied with my own simplistic approach. I'd say that the desired approach would be mimic Observable from JDK as close as possible in order to provide what Java programmers expect.

I understood pretty well the changes you've made and they make sense. But I'd say that strategically, our flavor of Observable should converge to the JDK's one... and not diverge from it. Let's discuss. :)

> Also, any reason why we are using WeakReferences in DefaultObservable ?  Is
> it to help with memory utilization ? i am concerned that it would introduce
> undeterministic behavior when there are no references to the observers
> other than observable.

Suppose you have one instance of A which refers one instance of B. In addition, suppose you have an Observable which has a WeakReference to B. Suppose that A was unreferenced. At this point B is elegible to be finalized and deallocated because there's no remaining strong reference to it. See:
http://java.sun.com/javase/6/docs/api/java/lang/ref/package-summary.html#reachability

> This would mean we have to dictate that the client has to hold onto
> the observer reference if they wish to get called.

I dont know if I understood what you mean... I'd say that the client shoud do something like this:

Date date = new Date(...);
date.addObserver(this);
date.addObserver(someOtherObject);
date.notifyObservers(); // as discussed above
someOtherObject = null; // release strong reference to the Observer
date.notifyObservers(); // someOtherObject will NOT be notified
> I think 
> by default we should use regular references and provide
> WeakRefernceObservable impl that some Observable impls can use.

It's very convenient to rely on JVM mechanisms to reclaim objects we eventually forget to explicitly un-reference. When we use WeakReferences, the objects can be reclaimed even when the reference count is greater than zero, given that the object is weakly referenced.

Thanks

-- Richard




Richard,

Here are my thoughts..

a) JDK Observer invocations can be controlled by setChanged/clearChanged on Observable and external entity can control when to be notified or not, so this works well when events are not self driven, but in Date case, events are self driven, so was the suggestion. (this is one of the patterns i noticed in Eclipse plugins)


b) I was trying to cover the case when there is no reference to Observer other than Observable. For example, if someone implemented Observer registration as shown below using the registerObserver method, only live reference to MyObserver instance after the method execution is Date.delegatedObservable.observers which is a weak reference and can get gc'd anytime and client code may never get called.

Class MyObserver implements Observer {
    private String id;

    private MyObserver (String id) {
       this.id = id
    }
          
    public void update(Observable o, Object arg) {
        // get the data from db using id and Date
    }
 
    public synchronized static void registerObserver(Date aDate, String id) {
        MyObserver a = new MyObserver (id);
        aDate.addObserver(a);
    }          
}

I am trying to avoid dictating how applications should register Observers with our implementation.

Keep the ball rolling :)

Thanks

-- Srinivas




Hi Srinivas,

a.1) setChanged/clearChanged are protected, so can only be driven from Observable implementations and derived classes. For instance, Date is a good candidate for using setChanged instead of calling notifyObservers directly. Notice that for self driven events, setChanged is preferred. We are lacking this implementation at the moment and, in fact, we should provide the same semantics as JDK, IMHO.

a.2) notifyObservers, on the other hand, is public and meant to be called when an Observable implementation or derived class (such as Date) is referenced by a client class which would like to unconditionally trigger Observers to be notified. A good example is a pricing engine which would like to refresh/force recalculations but the dates it holds were not touched at all.

b) I think you are correct about registerObserver: as soon registerObserver returns, the only strong reference to that Observer is lost and, doing so, the weak references can be reclaimed by GC at anytime and your handling code never called. :(

I'd say this behavior is correct because the Observer must be considered died as soon the scope of its declaration died. The programmer should keep a global accessible collection of Observers, in this specific situation. Something like this:

    static private Map<String, Observer> allObservers = 
                       new TreeMap<String, Observable>();

    public synchronized static void registerObserver(Date aDate, String id) {
        MyObserver a = new MyObserver(id);
        allObservers.add(id, a);
        aDate.addObserver(a);
    }

I think I understood your concern (tell if I'm wrong): you'd like to offer a strong and consistent framework for programmers which could prevent such 'mistake'. I understood that you'd like to provide something that frees the developer of have to remember details which potentially will lead him to bugs and waste of time. Am I correct? I'd say that there are 2 approaches to accomplish this aim:

One is providing registerObservable like I outlined above. Notice that we will have to provide unregisterObservable also and the programmer will have to 'remember' to call it. It does not seem to be very good. (:

Another is providing such life cycle control inside Observable and derived classes. (Wow! seems I finally got the point of your previous email :/ ) I see 2 scenarios:

  • High skilled programmer: We could have another flavor of DefaultObservable which keeps strong references instead of weak ones. The programmer will have to 'remember' to call deleteObservers() or even deleteObserver(aObserver) anyway... but we suppose he/she knows what a strong reference is and why it must be used in his specific situation.
  • Careless programmer: One could simply use DefaultObservable which relies on WeakReference and GC to manage life cycle of Observers.

Anyway, I think that JQuantLib should offer the more friendly API as possible for Java programmers, using well established naming conventions, style, etc,etc. In the situation we adapt something from JDK, as Observable/Observer is one case, we should try to keep the API and behavior as close as possible from the existing JDK API.

Your thoughts? Yeah! Keep the ball rolling :)

RichardGomes 14:43, 15 March 2008 (UTC)




Hi Richard,

I agree that we need to keep the API simple and consistent.

  • For WeakReferences usage, its a catch 22 :) i would do it other way, i.e default should be regular reference one and advanced users can use WeakReference one which is inline with what JDK says about Weak references.

Using our earlier example, with regular references

        Date myDate = new Date( );
        MyObserver.registerObserver(newDate,"ibm");
        MyObserver.registerObserver(newDate,"msft");
        ......
        myDate = null; //at this point, myDate and registered observers become eligible for GC
     

With the Weak references(using the code to keep track of Observers in Map)

        Date myDate = new Date( );
        MyObserver.registerObserver(newDate,"ibm");
        MyObserver.registerObserver(newDate,"msft");
        ......
        myDate = null;
        MyObserver.deRegisterObserver("ibm");
        MyObserver.deRegisterObserver("msft");        
     

Depending on how applications are coded, WeakReference usage can require additional code. One can argue both ways.

Usually with Observers( & listeners), it is quite common to assume Observable to have strong reference to registered Observers unless its unRegistered. I think we can look into using generics to support both with simpler programming model. We should give some more thought.

  • For Observer pattern, Have you considered Notification model in eclipse emf ? We may be able to borrow some ideas from there.

http://help.eclipse.org/help32/index.jsp?topic=/org.eclipse.emf.doc/references/javadoc/org/eclipse/emf/common/notify/Notification.html http://help.eclipse.org/help32/index.jsp?topic=/org.eclipse.emf.doc/references/javadoc/org/eclipse/emf/common/notify/Notifier.html http://help.eclipse.org/help32/index.jsp?topic=/org.eclipse.emf.doc/references/javadoc/org/eclipse/emf/common/notify/Adapter.html


--Shasti 16:37, 15 March 2008 (UTC)




Hi Srinivas,

I was looking at java/util/Observable.java from JDK1.6 sources. JDK uses strong references and I think we should mimic JDK as close as possible. Could you please create two flavors of DefaultObservable as discussed?

Could you also have a look on some usages of the Observable pattern in our current code base? Let me know if you find anything weird. I'd say that you should not invest much time on it because the core object model is still a work in progress. In particular, intruments and price engines are giving me a lot of headache to understand and translate properly. I'd say that we will have to revisit this subject again later.

Regarding notification in Eclipse... oh, well... I prefer the way JDK does. I mean: Observables and Observers work in pairs and we suppose that an Observer will handle properly an Object sent by an Observable. It's also prudent to throw an Exception when an Observer receives something unexpected. In Eclipse API Notification carries additional information about how a certain Object was changed. In spite it is useful, I dont think it is necessary or desirable in JQuantLib, because of our commitment to best performance as possible.

Kind Regards :)


RichardGomes 22:25, 16 March 2008 (UTC)