Observable - next generation

305 views
Skip to first unread message

Alik Elzin

unread,
Oct 16, 2015, 4:20:46 AM10/16/15
to guava-discuss, Alik Elzin
Hey, for a long time now, I'm not using Java's the Observable mechanism but rather using my own implementation.
The reason is that Java's Observable mechanism has some pitfalls:
1. Lack of generalization (Observer can receive any object).
2. It's not concurrent, meaning behaves slowly when notifying of an event (especially if many observers are registered).
3. It's cumbersome with the changed state (It needs to be set manually even if a notification is requested).
4. It has a cyclic dependency between Observable and Observer.

I'd like to provide another implementation for the observable mechanism and thought that guava would be a nice place for it, as guava provides some very core complementary functionality and a better observation mechanism is down that alley.
Thoughts?

Cheers.

Martin Buchholz

unread,
Oct 16, 2015, 1:07:18 PM10/16/15
to Alik Elzin, guava-discuss
Sounds like you might be interest in Flow and SubmissionPublisher coming in jdk9

--
guava-...@googlegroups.com
Project site: https://github.com/google/guava
This group: http://groups.google.com/group/guava-discuss
 
This list is for general discussion.
To report an issue: https://github.com/google/guava/issues/new
To get help: http://stackoverflow.com/questions/ask?tags=guava
---
You received this message because you are subscribed to the Google Groups "guava-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to guava-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/guava-discuss/bb473b93-17de-42d8-9764-51b0662d3a4d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Olivier Grégoire

unread,
Oct 16, 2015, 2:08:37 PM10/16/15
to Martin Buchholz, Alik Elzin, guava-discuss

Alik Elzin

unread,
Oct 17, 2015, 3:34:30 AM10/17/15
to guava-discuss, mart...@google.com, kil...@gmail.com
Thanks for pointer.
I think eventbus is a different pattern than observer. I agree that they try to solve a similar problem in a different way.
I looked at the implementation of the Guava's EvenBus. I'm not sure this is the place to discuss pros or cons. Just trying to say that there are cases where I want to use a [1]simple observer mechanism than a full blown generic eventbus.

Also, some of the disadvantages I wrote above aren't fixed by EventBus or even worse:
Lack of generalization - EventBus still receives Objects and not using generic.
cumbersome - Well, it's even more cumbersome than the current Java's observer mechanism.
not concurrent - subscribers are copied when firing events - instead of using some concurrent implementation.

Anyhow, EventBus and Observer are different patterns and I think both have a place in the world. I'd like to specifically concentrate on Observer. Sounds OK?

[1] By simple, I mean the following code:

public interface Observer<T> {
public void update(T args);
}

public class Observable<T> {

private ConcurrentLinkedQueue<Observer<T>> observers = new ConcurrentLinkedQueue<Observer<T>>();
public void addObserver(Observer<T> observer) {
observers.add(observer);
}
public boolean removeObserver(Observer<T> observer) {
return observers.remove(observer);
}
public void notifyObservers(T arg) {
for (Observer<T> observer : observers) {
observer.update(arg);
}
}
public Collection<Observer<T>> getObservers() {
return Collections.unmodifiableCollection(observers);
}
public void clearObservers() {
observers.clear();
}
}

Alik Elzin

unread,
Oct 17, 2015, 3:43:53 AM10/17/15
to guava-discuss, kil...@gmail.com
I don't understand the connection to the Java's observer.
I see a connection in relation to SubmissionPublisher, but SubmissionPublisher is targeted to solve a specific problem - solving stream control (if I understand correctly).

Joachim Durchholz

unread,
Oct 17, 2015, 5:15:16 AM10/17/15
to guava-...@googlegroups.com
Am 16.10.2015 um 10:20 schrieb Alik Elzin:
> Hey, for a long time now, I'm not using Java's the *Observable *mechanism
> but rather using my own implementation.
> The reason is that Java's *Observable *mechanism has some pitfalls:
> 1. *Lack of generalization* (*Observer *can receive any object).

Not having generics decouples Observables from the requirements of the
Observers. I.e. it's useful in scenarios where you don't care about
breaking Observers when evolving the Observable (yes such scenarios do
exist).
Of course, today, one could make it Observer<H super G> and
Observable<G> and code the don't-care-about-Observers Observables as
Observable<Object>.

> 2. It's *not concurrent*, meaning behaves slowly when notifying of an event
> (especially if many observers are registered).

Well, *somewhere* you need a list of recipients for the update() call.
If you need to parallelize the update() execution, simply use Observers
that start a separate thread - it's an extra call, but that's likely
negligible compared to the overhead of inter-thread communication. (I
may be wrong; you can still make your point by demonstrating that a
"more concurrent" notification mechanism is faster. Beware that
benchmarking individual elements is really, really hard.)

> 3. It's *cumbersome *with the changed state (It needs to be set manually
> even if a notification is requested).

I did not understand the scenario description.
I.e. what code do you mean how it looks today, how could it be made to
look better?

> 4. It has a *cyclic dependency* between *Observable *and *Observer*.

What cycle do you mean?
Type interdependence? That's normal in Java, and usually not a problem.

You can answer this by explaining what kinds of problems you encounter
from that cyclic dependency. It could be easier to understand, even.

> I'd like to provide another implementation for the observable mechanism and
> thought that guava would be a nice place for it, as guava provides some
> very core complementary functionality and a better observation mechanism is
> down that alley.

Do you have an implementation, or do you plan to build one?

Regards,
Jo

Alik Elzin

unread,
Oct 18, 2015, 1:21:44 AM10/18/15
to guava-discuss
4. Regarding the cyclic dependency, In Java's Observer, Observer knows Observable and vice versa. I think that the Observer is better not knowing the Observer. This helps decouple the actor from theater :)

An example implementation could something in the lines of:

public interface Observer<T> {
public void update(T args);
}

public class Observable<T> {

private ConcurrentLinkedQueue<Observer<T>> observers = new ConcurrentLinkedQueue<Observer<T>>();
public void addObserver(Observer<T> observer) {
observers.add(observer);
}
public boolean removeObserver(Observer<T> observer) {
return observers.remove(observer);
}
public void notifyObservers(T arg) {
for (Observer<T> observer : observers) {
observer.update(arg);
}
}
public Collection<Observer<T>> getObservers() {
return Collections.unmodifiableCollection(observers);
}
public void clearObservers() {
observers.clear();
}
}

Joachim Durchholz

unread,
Oct 18, 2015, 5:09:51 AM10/18/15
to guava-...@googlegroups.com
Am 18.10.2015 um 07:21 schrieb Alik Elzin:
> 4. Regarding the cyclic dependency, In Java's Observer
> <https://docs.oracle.com/javase/7/docs/api/java/util/Observer.html>,
> Observer knows Observable and vice versa. I think that the Observer is
> better not knowing the Observer.

I'm pretty sure that the Observer will always know the Observer ;-P

But there's not real cycle involved. The Observable has a list of
Observers, but the Observers know the Observable only while the update()
function is running (unless they store the value somewhere, but people
don't do this usually).

> This helps decouple the actor from theater
> :)
>
> An example implementation could something in the lines of:

That's not what I meant. My question was what's becoming worse for the
client code that calls this interface.

> public interface *Observer*<T> {

> public class *Observable*<T> {

With that, Observers can never observe a superclass of what the
observable offers. IOW client code would need a separate Observer for
each subclass.

> public void clearObservers() {
> observers.clear();
> }
> }

Leave clearObservers out, it's moving the decision who might be
observing what from the Observers back to the Observable.

Hm... I'm getting answers to two out of five questions, four of which
were about your claims.
You definitely need to have a good answer to any and all questions about
a proposal if you wish to add it to Guava. It need not be ready before
the question is even asked, but you need to arrive at that.

Regards,
Jo

Ron Shapiro

unread,
Oct 18, 2015, 10:08:38 AM10/18/15
to Joachim Durchholz, guava-...@googlegroups.com
Before looking to reimplement something, you probably want to consider RxJava: https://github.com/ReactiveX/RxJava

--
guava-...@googlegroups.com
Project site: https://github.com/google/guava
This group: http://groups.google.com/group/guava-discuss

This list is for general discussion.
To report an issue: https://github.com/google/guava/issues/new
To get help: http://stackoverflow.com/questions/ask?tags=guava
---
You received this message because you are subscribed to the Google Groups "guava-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to guava-discus...@googlegroups.com.

Alik Elzin

unread,
Oct 19, 2015, 10:49:53 AM10/19/15
to guava-discuss, j...@durchholz.org, Alik Elzin
Ha. Their Observer looks similar to mine ;-)
RxJava solves most problems I mentioned above - if not all of them.
The implementation is well documented but hard to follow. I have a problem understanding if there are any locks.
It looks easy from user perspective when you want to be notified on a predefined set of values - especially if you read this and this. See example below. This kind of misses the point.
It seems hard to understand how to notify the observable on new events/items. (a loss in simplicity when trying to have it all?) I probably missed something.
Anyhow, looks like a great package. Thanks for the pointer.

public static void hello(String... names) {
    Observable.from(names).subscribe(new Action1<String>() {
        @Override
        public void call(String s) {
            System.out.println("Hello " + s + "!");
        }
    });
}
hello("Ben", "George");
Hello Ben!
Hello George!

Reply all
Reply to author
Forward
0 new messages