Closed jroper closed 6 years ago
I thought it was interesting that a SubscriberBuilder:build did not return a (Rs)Subscriber but actually returned a SubscriberWithResult. All the other builders are more true to their names :-) I would not push for new names - I am all for one name for one thing and a descriptive name but I have not written as much functional style code as would be needed to have a solid opinion.
I was curious if there was some advantage to Mono and Flux both being subtypes of their Publisher whereas CompletionStage is an interface that has no 'isa' relationship with Flow.Publisher at all - as a discussion point for having 'new' types.
There is certainly an advantage to Mono
and Flux
both being subtypes of their Publisher
, however I'm not sure that in practice it's as big as one might think.
In my experience writing reactive apps, generally there's a hard boundary as to when you want/need an asynchronously provided single value, vs want/need a stream. I don't think I've ever come across a place where being able to treat something as either, or being able to return either from an API, is necessary. I think the primary advantage is that it just makes interoperability between the two a little easier, there's no need to have two variants of flatMap
on the publisher for example, and there's no need to provide a mechanism to flatten CompletionStage<Publisher<T>>
either.
Another advantage is cross cutting concerns, particularly context passing, can be easily handled consistently across them.
At the same time, there can be advantages between having them separate, since it makes it absolutely clear in an API which one is expected.
All that said, I think the decision has already been made for us. CompletionStage
exists as a standard, and has wide adoption in other Java standards such as JAX-RS, the new HTTP client and is also being adopted in ADBA. I'm not sure that it makes sense to introduce a new abstraction for exactly one asynchronous value to be adopted by Java standards. Unfortunately we don't quite have the luxury that Spring has to do our own thing.
I have finally checked out the code and took a look.
As for CompletionStage, I think most of the specs will try to return a CompletionStage for any async operations.
As for the builder naming,
PublisherBuilder
has buildRs
. Why not just build
. The builder does not always build a Publisher. Should this be called PublisherFactory
as it can create CompletionBuilder
as well.
ReactiveStreamBuilder
is not a builder and should not be called a builder. I think this class should be called ReactiveStream
while the current ReactiveStream
should be called ReactiveStreamManager
.
SubscriberBuilder
should be called SubscriptionBuilder
and return a Subscription on its build method.
ProcessorBuilder
should be called ProcessorFactory
as it creates multiple builders.
buildRs()
naming comes from the approach to reactive doc recommendation for dealing with the transition from org.reactivestreams
to java.util.concurrent.Flow
. Because this returns an org.reactivestreams.Publisher
, at some point in future we will migrate to java.util.concurrent.Flow.Publisher
. When that happens, we can introduce a new build()
method that returns java.util.concurrent.Flow.Publisher
, and keep the buildRs()
method for backwards compatibility - that way we don't break backwards compatibility, and we ensure that the final API when juc.Flow is adopted is the nice looking one.ReactiveStreamBuilder
is the parent class of all the builders. It's an implementation detail, we could remove it altogether, it would only save a very small amount of boilerplate in our implementation to keep it.SubscriptionBuilder
is problematic due to there being a Subscription
interface in reactive streams itself, and this is not building that.ProcessorBuilder
is a builder for Processor
, if you invoke build()
(or for now, buildRs()
) on it, you get back a Processor
. It can become a builder of a different type when you connect a SubscriberBuilder
to it, but that's just a changing of shape of the current thing being built, it's not really creating a new builder.Is this issue still valid?
I think it's been adequately addressed.
The current names for the primary classes being used are
PublisherBuilder
,SubscriberBuilder
,ProcessorBuilder
andCompletionBuilder
. These accurately reflect what they are doing, they are used to build publishers, subscribers, processors and complete graphs. When working with them fluently the names don't even come into play:However, one of the use cases for this library is for APIs to use the interfaces directly, eg, here's how a developer might use the messaging spec:
In this case, the
Builder
name features very prominently in a place that might not be so intuitive.This issue is to discuss this naming and whether the above is acceptable, or if we should try to come up with different names. The names
Publisher
,Subscriber
andProcessor
are out due to the confusion it might introduce with Reactive Streams itself, and the fact that imports for the Reactive Streams libraries are already on the classpath.One option is to go for a completely different set of names, as some other Reactive Streams libraries do. For example, RxJava uses
Observable
forPublisher
and doesn't really have an equivalent forProcessor
andSubscriber
. Reactor usesFlux
andMono
forPublisher
, and also doesn't have an equivalent forProcessor
andSubscriber
. Akka Streams usesSource
,Flow
andSink
forPublisher
,Processor
andSubscriber
respectively, thoughFlow
is problematic due to a name class with the JDK9java.concurrent.util.Flow
outer class that holds all the reactive streams interfaces.