Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Too many sharing operators? Should we cull the herd? #298

Closed
benlesh opened this issue Sep 11, 2015 · 10 comments
Closed

Too many sharing operators? Should we cull the herd? #298

benlesh opened this issue Sep 11, 2015 · 10 comments
Milestone

Comments

@benlesh
Copy link
Member

benlesh commented Sep 11, 2015

In a hallway discussion with @jhusain, we were talking about how most of the time people really just want share or shareReplay or shareBehavior (or the like), and rarely do they actually want to just publish something without that immediate refCount call.

Some of these operators are yet to implement, but the list is considerable when you realize they're all specializations of the same thing:

  • publish().refCount()
  • publishReplay().refCount()
  • publishBehavior().refCount()
  • publishValue().refCount()
  • share()
  • shareReplay()
  • shareBehavior()
  • multicast(subjectFactory).refCount()
  • publish() then connect()
  • publishReplay() then connect()
  • publishBehavior() then connect()
  • multicast(subjectFactory) then connect()
  • publish().connectionStrategyThing - (tbd @trxcllnt proposed operator for defining connection and disconnection strategy)

The problems

  1. It's bloat, there are just too many operators that do pretty much the same thing.
  2. Most of them aren't very straight forward to teach.
  3. Many of them aren't used enough to justify a specialization.
  4. The ones that are used frequently are always used in the same ways, but rarely used alone. (publish is almost always paired with refCount, etc)

My pitch

I think we should pare this back to being a refined set of operators that falls into two categories:

  1. The most common combined operators (share rather than publish().refCount() for example)
  2. The most basic operators that allow you to build any of the others multicast and refCount for example

To cull or simply exclude?

An alternative to cutting them completely from the library is to keep them in the library, but not include them in the global output. People could simply use them from their modules.

attn @staltz who was a big proponent of publishBehavior (which is honestly one I'd consider cutting in favor of shareBehavior)

@benlesh benlesh added this to the Initial Beta milestone Sep 11, 2015
@benlesh
Copy link
Member Author

benlesh commented Sep 11, 2015

I'd also appreciate the thoughts of @mattpodwysocki, who undoubtedly has faced more internal client needs (or dislikes) for the presence of these operators.

@staltz
Copy link
Member

staltz commented Sep 11, 2015

I agree with the sentiment there are too many of them (I know I added yet more, but that was in an attempt to standardize them).

I have also been teaching these operators to developers, and they mostly prefer share() because it's so intuitive and has a clear intent. I sometimes use publish().refCount() just to emphasize the refCount and teach how it works under the hood.

Agreed that share, shareBehavior, shareReplay should be the main ones to teach and advocate. (although shareReplay is getting less useful, and ReplaySubject in general).

The least useful of them all is multicast IMO. It's so low-level and I have never encountered a situation where I needed it.

I would consider this solved if we didn't have use cases for explicit connect() calls, which leads us to break share into two to get only the first part (publish).

Here are three different courses of action I have in mind:

(1) Only share

  • share
  • shareBehavior
  • shareReplay
  • multicast(subjectFactory).paulsConnectionStrategyThing for those cases where you need to solve your tricky use case

(2) publish + connect strategies

  • publish()
  • publishBehavior()
  • publishReplay()
  • connect on ConnectableObservable
  • refCount on ConnectableObservable
  • paulsConnectionStrategyThing on ConnectableObservable

(3) keep them in the library, but not include them in the global output

@jhusain
Copy link

jhusain commented Sep 11, 2015

+1

JH

On Sep 11, 2015, at 10:39 AM, André Staltz [email protected] wrote:

I agree with the sentiment there are too many of them (I know I added yet more, but that was in an attempt to standardize them).

I have also been teaching these operators to developers, and they mostly prefer share() because it's so intuitive and has a clear intent. I sometimes use publish().refCount() just to emphasize the refCount and teach how it works under the hood.

Agreed that share, shareBehavior, shareReplay () should be the main ones to teach and advocate. ( although shareReplay is getting less useful, and ReplaySubject in general).

The least useful of them all is multicast IMO. It's so low-level and I have never encountered a situation where I needed it.

I would consider this solved if we didn't have use cases for explicit connect() calls, which leads us to break share into two to get only the first part (publish).

Here are three different courses of action I have in mind:

Only share

share
shareBehavior
shareReplay
multicast(subjectFactory).paulsConnectionStrategyThing for those cases where you need to solve your tricky use case
publish + connect strategies

publishReplay()
publishBehavior()
publishValue()
connect on ConnectableObservable
refCount on ConnectableObservable
paulsConnectionStrategyThing on ConnectableObservable
keep them in the library, but not include them in the global output


Reply to this email directly or view it on GitHub.

@trxcllnt
Copy link
Member

@Blesh I almost never publish().refCount(), especially if we add something like control, so I will argue vehemently against removing the publish variants, or at least removing them but keeping the generic multicast.

Ironically, even though it's counter to our performance goals, I think the best way to reduce operator count is operator overloading/polymorphic functions.

@benlesh
Copy link
Member Author

benlesh commented Sep 11, 2015

I will argue vehemently against removing the publish variants, or at least removing them but keeping the generic multicast.

@trxcllnt That sentence confused me. Can you clarify? You want all of the publish variants? Are you saying you actually use connect all the time?

I am in favor of a combination of 1 and 3 in @staltz's comment above. including the share variants and basic building blocks in the exported global, but leaving all of the other ones in the repository.

@robwormald
Copy link
Contributor

The ones that have confused me the most (from a n00b perspective) are the ones that require double chaining like publish().refCount() - .share() is a much more intuitive operator for that case, so I like @staltz's idea #1.

I'm all for leaving the bulk of the operators out of the exported global, but one thing I'd like to see documented / discussed is what the preferred method is for adding your own operators (as a consumer of the library, or in a framework that leverages Rx internally) - i'll open another issue for this?

@trxcllnt
Copy link
Member

@Blesh yes, I almost always connect. refCount is almost never the behavior I want, so either I control manually with connect, or would use control in a world where that existed: publish().control(connectionStrategy).

@trxcllnt
Copy link
Member

To be clear I'm fine getting rid of all the specialization of multicast as long as we keep multicast. It's not that much more difficult to call source.multicast(_=> new ReplaySubject(10)) rather than source.replay(10).

@benlesh
Copy link
Member Author

benlesh commented Sep 12, 2015

I think we have a consensus, then. Your control (name to be bike shedded) method, multicast and the share variants would be the ideal.

staltz pushed a commit to staltz/RxJSNext that referenced this issue Oct 2, 2015
Add shareReplay() as a core operator. Vaguely relates to issue ReactiveX#439 and
issue ReactiveX#298.
staltz pushed a commit to staltz/RxJSNext that referenced this issue Oct 6, 2015
Add shareReplay() as a core operator. Vaguely relates to issue ReactiveX#439 and
issue ReactiveX#298.
@benlesh
Copy link
Member Author

benlesh commented Nov 5, 2015

I think for now, this has been addressed.

@benlesh benlesh closed this as completed Nov 5, 2015
@lock lock bot locked as resolved and limited conversation to collaborators Jun 7, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants