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

Rename usage of "observable" to not confuse with TC39 observable #470

Closed
jayphelps opened this issue Aug 10, 2016 · 21 comments
Closed

Rename usage of "observable" to not confuse with TC39 observable #470

jayphelps opened this issue Aug 10, 2016 · 21 comments

Comments

@jayphelps
Copy link

jayphelps commented Aug 10, 2016

As many of you are aware of, TC39 (the standards body around the JavaScript language) have a proposal for adding a new async primitive to the language called an "Observable". The current iteration of the spec has a ton of history outside of JavaScript, but tl;dr is most recently inspired by the RxJS library, which now is also updated as one unofficial reference implementation.

The usage of the term "observable" in regards to the TC39 proposal is incompatible with the usage by MobX, which means if TC39 does in fact ever include it in JavaScript it's probably highly confusing to use the term in this fashion.

Aside from future hypothetical awkwardness, historically I would argue a majority of people who have heard the term associate it with either RxJS/Bacon/Most/or one of the other Reactive Extensions (Rx) implementations in other languages like Rx.NET, RxJava, etc. I feel like this may produce unnecessary confusion for adopters, especially if they wish to continue also using a library that implements their known definition of Observables, like RxJS, together with MobX.

I'd like to discuss possible alternative names MobX could adopt, if the MobX community is willing. I realize for some this is a non-trivial name change requiring a major version bump, but I believe it's best for the longevity of MobX.

FWIW MobX has a ton of overlapping functionality with Ember, which does not use the term Observable. Instead, they too use the terms computed properties and observers, but their computed properties also support writing/setting in a similar fashion of what MobX's @observable does.

Thoughts?

(for reference: Mobx vs Reactive Stream Libraries (RxJS, Bacon, etc))
Cc/ @Blesh

@jayphelps
Copy link
Author

jayphelps commented Aug 10, 2016

Perhaps just @observe or @observed would be sufficiently different? I totally get why it was named observable.

@mweststrate
Copy link
Member

Yep good point, @state or @tracked might also work (@observed vs @observer might be a too subtle difference for the quick reader). Doesn't have to be a breaking change but could also be an idiomatic alias with a decent deprecation message. (note to self: add traces to deprecation messages)

@benlesh
Copy link

benlesh commented Aug 10, 2016

I like @tracked, because I feel like the words "observe" and "state" are already everywhere in my code. But that might just be me.

@jayphelps
Copy link
Author

I also think that @state is confusing given existing usage in the React community. @tracked sounds good. I'll defer to the existing MobX community to bikeshed further. 😄

@mweststrate
Copy link
Member

"trackables", trackable / extendTrackable / @tracked (or @trackable?) sounds like the best option to me so far. Any better ideas?

@mweststrate
Copy link
Member

Alternatively: derivable (from DerivableJS). Or @mutable lol :)

@benlesh
Copy link

benlesh commented Aug 12, 2016

I still like trackables

@winterbe
Copy link

Track, watch, listen, subscribe, spy, guard, audit, peek, glue, monitor, hunt, crib, hook, stick, chase.

@mweststrate
Copy link
Member

Hmm.. should observer be renamed to tracker or tracking in such cache? Or just reactive 🙈

@benlesh
Copy link

benlesh commented Aug 19, 2016

Tracker. Reactive is a higher level concept.

@winterbe
Copy link

I like @listen and @listener or @watch and @watcher. It's short and less verbose to type than @...able.

@rossipedia
Copy link
Contributor

+1 @watch and @watcher

@urugator
Copy link
Collaborator

All those words are so generic and used in so many different libraries and contexts. Use the words that best describe what's happening and introduce namespacing if neccessary.

I am not a fan of "track", I feel like there is a subtle difference in the meaning, which doesn't fit into MobX context as good as "observe".
To me, the word "track" has some continuity in itself (in terms of time or space), while MobX is more about detecting and reacting to discrete state changes, not about following changes over time.

"Listener" is in fact quite similar to "observer", but "listenable" doesn't sound right and listeners are already widely used in the context of event programming.

"Watcher" is quite fine, but "watchable" only if it's enjoybale for watcher :) ...so I don't know about that either.

@winterbe
Copy link

You've just accidentally introduced a new candidate: @Detect (for
observable) + @react (for observer). 😎

Am Montag, 22. August 2016 schrieb urugator :

All those words are so generic and used in so many different libraries and
contexts. Use the words that best describe what's happening and introduce
namespacing if neccessary.

I am not a fan of "track", I feel like there is a subtle difference in the
meaning, which doesn't fit into MobX context as good as "observe".
To me, the word "track" has some continuity in itself (in terms of time or
space), while MobX is more about detecting and reacting to discrete state
changes, not about following changes over time.

"Listener" is in fact quite similar to "observer", but "listenable"
doesn't sound right and listeners are already widely used in the context of
event programming.

"Watcher" is quite fine, but "watchable" only if it's enjoybale for
watcher :) ...so I don't know about that either.


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
#470 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAdmqSVwoenjQzr6ptag50p16OpI3McUks5qidyKgaJpZM4JgwVW
.

@urugator
Copy link
Collaborator

urugator commented Aug 22, 2016

@winterbe @Detect is confusing because it can be used for observer, observer detects the changes of observable...
@detectable is better, but what does it mean that object is detectable? It doesn't make much sense...

What about:
@stateful
@stateAware

EDIT: when I think about it, @observer is only used on react components and in fact it's just autorun for component's render method, so... maybe @autorender or @autoupdate (react also uses the term "update")?
EDIT2: Yep, I really like @stateful and @autoupdate

@urugator
Copy link
Collaborator

urugator commented Aug 23, 2016

I just found out this issue #169 and I am a little bit confused.
Aren't we saying "let's be compatible with TC39" and "let's change the nomenclature, because we are not compatible with TC39" at the same time?

@mweststrate
Copy link
Member

@urugator there is a difference between having interoperability with TC39 observables and being TC39 observables.

For example suppose you create the following var x = mobx.observable({ y: 5 }). In principle there are two things that can be observed (with MobX.observe) here: x itself, and x.y. However introducing a subscribe method on either of them is trouble some, on x because it might collide with an actual property called subscribe, and you cannot introduce it on x.y either because it is a primitive and "cannot" have methods in the first place.

So the only thing that could safely be implemented is [Symbol.observable]() : Observable;, but that is only applicable to non-primitives: observable objects, arrays and maps. So the point of #169 is to do the latter, but also to provide a utility like asObservable(x, "y"): Observable. The bottom line being: not all mobx observables can be TC39 observables, although can all be converted to TC39 observables. It is a bit like the distinction between an iterable and an iterator.

@urugator
Copy link
Collaborator

@mweststrate I got the point, but I don't think that arguments are entirely valid:

Handling primitives:
let a = mobx.observable(5); boxed
let a = Observable.from(5); boxed

Handling structures:
let a = mobx.observable([1]); converted into observable
let a = Observable.from([1]); converted into observable

Handling object properties:
mobx.observe(x.y, onChange) not possible unless x.y is observable
x.y.subscribe(onChange) not possible unless x.y is observable

Only difference is the ability to observe specific property of observable object, which is something I would call a "parametrized subscription":
mobx.observe(x, "y", onChange)
x.subscribe("y", onChange) fictional alternative in the context of TC39

Even though we could call property y observable, we in fact still subscribe for observable x, the y can't be observed without being a property of observable x.
So the fact that y can't be subscribed does not go against the compatibility with TC39 observables, because y is not observable by itself.

What's more mobx.observe(x, "y", onChange) can still be done via mobx.observe(x, onChange), only the observed property must be filtered in onChange listener.
So the only real difference from x.subscribe(onChange) (aside from being static function) is that MobX provides a shorter and probably better optimized version for one special scenario.

If there is a concern that subscribe method might collide with actual property, shoudn't we be concerned the same way about overwriting [Symbol.observable]?
What if my object extending mobx.observable actually also implements TC39 observable?

I don't say that mobx.observable should implement Observable API, I just don't see incompatibilities, which would make it impossible.

@mweststrate
Copy link
Member

@urugator hmm these are very interesting points indeed. Would it be confusing if an mobx.observable always contains a value, but if you subscribe to it, you won't get that values directly in your subscriber, but events? (like an array splice, just like observer). Probably that is ok.

@urugator
Copy link
Collaborator

urugator commented Aug 25, 2016

@mweststrate Yea, the question is, what should be produced by observable for it's subscriber... the changed value (which is actually observable itself) or change event?
I would go for events, because they're more descriptive and versatile.
The mobx.observe basically produces events even now, because it never produces just a single value (even though the "event" is flattened into arguments).
However I don't know how practical it is. I think we need to ask why and in which way mobx should be compatible with TC39 Observables?
How we would like to use mobx in the context of RxJS or similar framework.
Is it even the same thing (TC39 compatibility and intended usage as observable)?
What are the benefits and real use case scenarios?
I haven't use any of these "reactive" frameworks yet, so I really don't have that kind of thinking "It would be cool if I could do this..."

My additional thoughts/opinions:

@mobx.observable shouldn't implement Observable API by itself, let the client do it when needed
@mobx.observable shouldn't implement [Symbol.Observable], let the client do it when needed

Provide:

mobx.subscribe(
  observable: mobx.Observable
  onNext : Function, // accepting single arg mobx.ChangeEvent
  onError? : Function,
  onComplete? : Function) : Subscription;

Provide:

@mobx.tc39.observable and mobx.tc39.observable(object) adding mobx.observable behavior alongside with:

subscribe(onNext, onError, onComplete) {
  return mobx.subscribe(this, onNext, onError, onComplete);
}
[Symbol.Observable]() {
  return this;
}

(Similary, anyone can easily implement decorator passing just changed value instead of ChangeEvent)

Provide:
mobx.Symbol.Observable available on any mobx.observable object as

[mobx.Symbol.Observable]() {
  return this;
}

Refactor:
mobx.observable(object) so that it first checks for a presence of [mobx.Symbol.Observable] property on a passed object and if present, returns the result of [mobx.Symbol.Observable]() mimicking Obervable.from(object) behavior.
(maybe we could also provide mobx.from(object) and mobx.tc39.from(object) mimicking TC39 even better)
solves #492

@mweststrate
Copy link
Member

Although I understand that some confusion might arise from using a similar term to the tc39 proposal, I think will cause to much confusion to rename the whole concept at this point. Especially since in practice this doesn't seem to lead to trouble very frequently. I usually explain it as: there are observable streams which emit events to which one can subscribe, like RxJs, and there are observable values from which we can observe the updates (MobX).

For the interoperability question, see #677

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants