Proof of concept for fluent bindings for ObservableValue

John Hendrikx hjohn at xs4all.nl
Mon Oct 4 21:50:56 UTC 2021



On 04/10/2021 17:51, Nir Lisker wrote:
> I think that a PR can be created. The only point we need to decide is
> about the subscription models we talked about above. ReactFX uses
> something different for each, you use the same. That can determine if we
> need different classes for each binding type.

We can introduce classes for these in any case if that keeps things more 
clean; they're not public (after your change) so we can change our minds 
later.

I'm not sure I see the difference though, ReactFX does the same kind of 
observations to keep the bindings up to date. Here's a comparison:

OrElseConst (ReactFX) vs OrElseBinding
--------------------------------------

     protected Subscription connect() {
         return Val.observeInvalidations(src, obs -> invalidate());
     }

------

     protected Subscription observeInputs() {
         return Subscription.subscribeInvalidations(source, 
this::invalidate); // start observing source
     }

OrElseGetBinding (no equivalent in ReactFX)
-------------------------------------------

     @Override
     protected Subscription observeInputs() {
         return Subscription.subscribeInvalidations(source, 
this::invalidate); // start observing source
     }

FlatMapped (ReactFX) vs FlatMapBinding
--------------------------------------

     protected final Subscription connect() {
         return Val.observeInvalidations(src, obs -> srcInvalidated())
                 .and(this::stopObservingSelected);
     }

     private void stopObservingSelected() {
         if(selectedSubscription != null) {
             selectedSubscription.unsubscribe();
             selectedSubscription = null;
         }
     }

------

     protected Subscription observeInputs() {
         Subscription subscription = 
source.subscribeInvalidations(this::invalidate);

         return () -> {
             subscription.unsubscribe();
             mappedSubscription.unsubscribe();
             mappedSubscription = Subscription.EMPTY;
         };
     }

In both ReactFX and the PoC we see that FlatMapping requires a more 
complicated subscription. As a FlatMap observes the original observable 
and the result of the flat mapping, when unsubscribing two listeners 
need to be unsubscribed.

As for the OrElse and OrElseGet, I just noticed ReactFX does not have an 
#orElseGet equivalent. Closest thing is #getOrSupply but that doesn't 
create a binding and is just a convenience method to get the current 
value.

This does make me wonder how useful #orElseGet really would be -- I 
think we should leave it out for now, it is easy to introduce later if 
there is a real use case for it (I checked what I code I have, and I 
never used it so far, it was only used to delegate #orElse to #orElseGet 
which is pretty useless).

I think one more thing to decide is the naming of flatMap, there seems 
to be some support for using "select" as a name instead. I personally 
don't mind the name as for me flatMap just implies a map with the 
additional step of flattening the result (stripping the extra wrapper, 
be it Optional, Stream or in our case, ObservableValue).

I don't think that confusion with reactive programming is good argument 
to not use this name, as neither Optional nor Stream have resulted in 
such confusion.

> I can create the JBS issue for this one and a draft CSR if you want.

It would be great to move this forward.  If we can't borrow one of the 
existing JBS issues then it would be good to create a new one, I can do 
that, I can rewrite the text of the PoC MR a bit for this purpose. As 
for a CSR, I'm not quite sure what that entails so it might be best if 
you draft one.

The draft PR is mostly missing the JUnit test coverage now, which I can 
take care off. I can also take care of the other changes we discussed 
that may not be there yet. And I'll take another critical look at the 
documentation and see if it still matches with what was discussed.

I've tried pushing the JUnit 5 upgrade as well, but I don't think it 
will arrive in time (or perhaps it will).  What I can do is convert my 
JUnit 5 tests to JUnit 4, and once JUnit 5 is available I can revert that.

--John


More information about the openjfx-dev mailing list