Open hastebrot opened 7 years ago
From my perspective there are two steps to mature the observer (aka listener) pattern.
The first step is to replace observable.addListener(observer)
and observable.removeListener(observer)
with an object-oriented Subscriber
(aka Consumer
) and Subscription
. This lets us keep references to observable
and observer
in a single subscription
object, thus simplifies removing the observer from the observable. Removing the observer is important, since memory leaks in the observer pattern are a common problem. Now instead of adding a callback/listener via observable.addListener()
we can simply pass the callback to subscription.subscribe()
(here: onChanged()
).
A possible second step to mature the pattern is to make use of (monadic) functional combinators (some of them were introduced in Java 8). Through functional composition with methods like orElse()
, map()
, flatMap()
and filter()
we can process/transform the observed values before passing them via subscribe()
to the effectful callback. This is important, since we need (side) effects but want to minimize them. This also adds reactive semantics.
Also note: we can switch between each step. We can use objects that implement the observer pattern and wrap them into objects that implement step one or step two. Probably the second step is out of scope.
Hi Benjamin :)
thanks for your feedback!
So, the goal of this TCK is to provide good'ol observer pattern without dependencies to JavaFX?
This is not right. The API should be a plain JavaSE API that could be used everywhere. If JavaFX properties would deepened on the interfaces of this API it would be real cool, because:
Since we only define interfaces here Implementations could easily be bound. Based on this it would be easy to bind a JavaFX property to any other property (maybe a WebSocket based property or so). Since this binding must handle threads etc. it's not part of the property interface. We will have a deeper look at binding functionality later.
When talking about listener / subscription I'm completely with you. Currently I do not know if functional combinators should be part of this API. I think it will be important to create reactive streams on top of the observer pattern. Since (reactive) streams provide exactly the functionally that you have mentioned I do not know if we need it here. But as you said, this will be a later step and maybe tan we all know more :)
I support Benjamins request for monadic combinators. Having map
, flatMap
and filter
would be a big benefit for developers.
This is one of the cool thinks that ReactFX adds to the JavaFX observers.
I think we should discuss this. From my point of view such methods do not belong in this low level library since Reactive / Functional programming should be created on top of this lib. Anyway I would love to discuss this point. Maybe we can do a twitter call in near future. @hastebrot @miho interested?
Sure, but we need some planning since I'm currently in the arabic desert. Sometimes I have good internet. But not always.
As far as I understand, reactive streams [1] are an extension of the observer pattern, with implementions of reactive
Observable
,ObservableList
,ObservableSet
andObservableMap
in [2].So, the goal of this TCK is to provide good'ol observer pattern without dependencies to JavaFX?
[1] https://github.com/reactive-streams/reactive-streams-jvm [2] https://github.com/ReactiveX/RxJava
I worked the last week extensively with the internals of JavaFX and RxJava observables, which made me interested in the pros/cons of each approach. The first difference was right in the
README.md
: RxJava handles the next value, errors and completed states, and optionally uses the genericChange<T>
as value.ObservablePattern
unifies this intoonChanged(ValueChangeEvent)
.There is an analysis of JDK 1.0
Observable
and its shortcomings in Erik Meijer's "Your Mouse is a Database" [3] in section "Crossing Futures and Callbacks".[3] http://queue.acm.org/detail.cfm?id=2169076