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

feat(subjects): Rename BehaviorSubject to CurrentValueSubject, AsyncSubject to LastValueSubject #4838

Closed
wants to merge 1 commit into from

Conversation

benlesh
Copy link
Member

@benlesh benlesh commented Jun 6, 2019

This is a rename.

BehaviorSubject -> CurrentValueSubject
AsyncSubject -> LastValueSubject

Old names are deprecated, not removed.

Background

Given my extreme jealousy that Apple called their version of BehaviorSubject "CurrentValueSubject"... And given that I'm really, very tired of answering the question "Why is it called a BehaviorSubject?" and "What is AsyncSubject?", this is a rename. Because names that make sense are good.

…ubject to LastValueSubject

`BehaviorSubject` -> `CurrentValueSubject`
`AsyncSubject` -> `LastValueSubject`

Old names are deprecated, not removed.
@Fallenstedt
Copy link

Will these changes update ReactiveX's docs? http://reactivex.io/documentation/subject.html

@benlesh
Copy link
Member Author

benlesh commented Jun 6, 2019

@Fallenstedt We could update those separately. https://rxjs.dev is the source of truth for RxJS. I don't think reactivex.io has been accurate WRT RxJS for years.

@Fallenstedt
Copy link

Fallenstedt commented Jun 6, 2019

@benlesh, My only concern is inconsistency. I feel that rxjs.dev should be updated asap if this PR were to go through.

I'm torn on this PR. On one hand it describes a BehaviorSubject's intentions more accurately, but it will rip the rug from under all docs and guides that the community has created.

@benlesh
Copy link
Member Author

benlesh commented Jun 6, 2019

@Fallenstedt, you are right, it will make blogs, etc, that talk about BehaviorSubject inaccurate. However, it would be a while before BehaviorSubject is actually removed, and even then, we'll try to provide backwards compatibility through rxjs-compat.

@ducin
Copy link

ducin commented Jun 6, 2019

@Fallenstedt this way you might drop pretty much all renames ever. Same argument goes for the other side: all the people who will come to learn RxJS (and it's getting more and more traction each year) will learn a thing with a precise name, making it more clear for them. Eventually, the ones who learnt the new name first would outstand us, who knew BehaviorSubject first.

@Fallenstedt
Copy link

Fallenstedt commented Jun 6, 2019

That is valid perspective @ducin. I can see how this change could help many.

I guess it will be up to other Reactive libraries (RxDart for example) to catch up.

@cartant
Copy link
Collaborator

cartant commented Jun 7, 2019

However, it would be a while before BehaviorSubject is actually removed.

I would suggest that it never be removed. It could remain as an alias - even if deprecated. We still have flatMap as an alias for mergeMap, after all.

@benlesh
Copy link
Member Author

benlesh commented Jun 7, 2019

Honestly, I'd like to get rid of flatMap too. I think aliases are confusing for people. LOL... But I do see the compromise you're proposing.

@cartant
Copy link
Collaborator

cartant commented Jun 7, 2019

Given that deprecations can be accompanied by a message/explanation, I'd be in favour of deprecating flatMap with a deprecation message that mentions that it is an alias for mergeMap. The subject deprecation messages could mention their aliasing the new names, too.

@obenjiro
Copy link

obenjiro commented Jun 7, 2019

No, plz don't. We still struggling with tons of documentation and tutorials that uses method chaining (talking about introduction of pipe-able operators). But this change won't bring as big of a value.

@benlesh
Copy link
Member Author

benlesh commented Jun 7, 2019

Books/articles on technology getting outdated isn't a valid reason to stop progress. We're committed to backwards compatibility. Even the very argument presented by @obenjiro above is a bit of FUD, because even as recent as v6.5.2 "method chaining" still just works, you just install rxjs-compat and that's it. Here's a stackblitz that proves it.

This works in RxJS 6.5.2 if you just npm install rxjs-compat. No other work needed.

import { Observable } from 'rxjs/Rx';

const source = Observable.of(1, 2, 3)
  .filter(x => x % 2 === 1)
  .map(x => x + x)
  .delay(1000)

source.subscribe(x => console.log(x));

So here we are... more than a year and a half after pipeable operators are introduced, and dot-chaining still "just works" in v6.5.2.

It's just not a good argument.

@benlesh
Copy link
Member Author

benlesh commented Jun 7, 2019

Hell, I'm okay with leaving it deprecated for the next 3 major versions, if we must. But I think the name should change.

@psmyrdek
Copy link

psmyrdek commented Jun 7, 2019

I’m totally for the first one, but don’t you think that terms last and current are dangerously close to each other?

@rart
Copy link

rart commented Jun 11, 2019

With intention of helping in name usability testing, I’ll mention that: As a user of rxjs who hasn’t yet come across AsyncSubject and don’t know what it does, I struggle to imagine what LastValueSubject does different from CurrentValueSubject. Thinking for a minute it occurs to me that when you subscribe you get, not the value that was just nexted, but the previous(?). It also made me consider whether subscribers get notified until the second next into their subscription.

@thorn0
Copy link
Contributor

thorn0 commented Jun 12, 2019

@benlesh Please excuse the dumb question, but... why is it called a BehaviorSubject? 😆 I'm having trouble googling the answer.

@Odonno
Copy link

Odonno commented Jun 16, 2019

CurrentValueSubject seems like a right name but I would suggest SkipUntilCompletionSubject instead of LastValueSubject.

@BioPhoton
Copy link
Contributor

I consider LatestValueSubject (but this still can be confused with replay logic) more accurate than CurrentValueSubject

@rart
Copy link

rart commented Jun 18, 2019

After learning what the subject does, LastValueSubject makes a lot of sense. I think the issue with all the variants of Last - i.e last, lastest, lastEmitted is that without any knowledge of what the subject does, last can be easily interpreted as “previous”.

Though a mouthful, I’d vote for Odonno’s SkipUntilCompletionSubject. That one I got straight away what it really does and made me say “aah, that’s what the ‘last’ referred to”

@thorn0
Copy link
Contributor

thorn0 commented Jun 18, 2019

last can be easily interpreted as “previous”

How about "ultimate" or "final" then? UltimateValueSubject, FinalValueSubject

upd: I'm proposing these as new names for AsyncSubject, not for BehaviorSubject.

@Odonno
Copy link

Odonno commented Jun 18, 2019

@BioPhoton So, it seems it is still ambiguous. And so I have one more question : why not adding the firstValue argument to the Subject constructor?

@BioPhoton
Copy link
Contributor

@Odonno
Subjects are here for multicasting.
There are different subjects for different problems.
The most primitive subjects is Subject.
It should not be changed in any order also no new parameters for initial values...

For specific cases we have specific subjects. I. E. BehaviorSubject to privide an initial value as well as caching the lastest and forwarding all future values

@Odonno
Copy link

Odonno commented Jun 18, 2019

@BioPhoton Oh right. Thanks for the explanation. But now I don't see the difference between BehaviorSubject and ReplaySubject(1).

@ducin
Copy link

ducin commented Jun 18, 2019

@BioPhoton Oh right. Thanks for the explanation. But now I don't see the difference between BehaviorSubject and ReplaySubject(1).

@Odonno Behavior guarantees the initial value (or, to be more precise, the current state's initial value). That's different from Replay e.g. when there was no event emitted on the upstream - behavior requires an initial event to be passed to new subscribers, Replay has no such guarantee. Think of Replay as replaying all/some of the goals of a soccer match - and Behavior as the result. Replay might not emit anything if upstream doesn't provide any events. No goals - no replay. Behavior is the match result so there has to be initial 0:0, moreover, if you come late, you see the current score even if you didn't see the goals - you get the current state.

Another difference is handling late subscription, in particular, when the subject is already completed. Behavior doesn't emit, Replay does.

There's a lot more to subjects than one might think ;)

@Odonno
Copy link

Odonno commented Jun 19, 2019

Thanks for the explanation @ducin. I knew this but not the part about the subscription when the Observable is completed. That's really tricky.

IMO, it is really ambiguous and would suggest to provide two different subjects : AlwaysReplaySubject and ReplaySubject but then the ReplaySubject would not be retro-compatible because we would've to change its behavior. Not an option obviously... :(

But on another subject, I suppose that CurrentValueSubject is not the perfect name but the most consistent name for the BehaviorSubject.

@BioPhoton
Copy link
Contributor

If we rename these subjects then we should also be consistent and rename the other operators related to them:

  • publishBehavior => publishCurrentValue
  • publishLast => publishLastValue

@benlesh
Copy link
Member Author

benlesh commented Oct 15, 2019

This PR is terribly out of date, and overall, while the reception here has been positive, the greater community doesn't have much appetite for the change at the moment. I do think we should revisit this at some point, though, as the names still really don't make sense to most people.

@benlesh benlesh closed this Oct 15, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Nov 14, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.