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

Comparison to other reactive libraries #18

Closed
rodryquintero opened this issue Aug 20, 2015 · 9 comments
Closed

Comparison to other reactive libraries #18

rodryquintero opened this issue Aug 20, 2015 · 9 comments

Comments

@rodryquintero
Copy link

I would like to see a comparison between Mobservable and other reactive libraries.

@mweststrate
Copy link
Member

Hi,

That is a hard question since there are many libraries :). Let's first define "(functional) reactive programming":

The essence of functional reactive programming is to specify the dynamic behavior of a value completely at the time of declaration.

  • Heinrich Apfelmus

Generally speaking, I think there are two important flavors of reactive programming:

Event stream based FRP

Event stream based libraries, focus at manipulating streams and are very good at that. Joining, splitting, merging, mapping, sampling etc. These libs are useful if you want to reason about multiple event streams at the same time. Or when throttling plays an important role, like with network traffic. For solving simple problems though, these libraries are quite obtrusive (imho). They need a different mindset. Also, representing every variable in your state as stream might become quite unwieldy. Examples: RxJs and BaconJS.

Transparent FRP

Transparent Reactive programming on the other hand tries to hide reasoning about time. It just applies reactive programming in the background. Like with event based, TFRP updates views whenever needed. The difference is that in TFRP you don't define how and when stuff updates. While with streams you (have to) define that explicitly.

The tracker library of Meteor summarizes this nicely:

Tracker gives you much of the power of a full-blown Functional Reactive Programming (FRP) system without requiring you to rewrite your program as a FRP data flow graph.
https://www.meteor.com/tracker

Examples of frameworks that apply TFRP libs are knockoutJS, EmberJS and Meteor. Mobservable is stand-alone, although it ships with a small ReactJS binding.

These are things that makes mobservable distinctable from other TFRP libraries:

  1. Changes are always processed synchronously and atomically; You can never observe intermediate values. This makes reasoning simpler and avoids weird edge case behavior.
  2. Mobservable doesn't ship with its own reactive structures. Instead, all structures behave like normal javascript objects, classes and arrays (although array's will have some caveats until ES7).
  3. Its a stand-alone solution.

I'll hope that answers your question.

@rodryquintero
Copy link
Author

Thanks. This answer helps to understand Mobservable better.
El El jue, 20 ago 2015 a las 1:53 p.m., Michel Weststrate <
notifications@github.com> escribió:

Hi,

That is a hard question since there are many libraries :). Let's first
define "(functional) reactive programming":

The essence of functional reactive programming is to specify the dynamic
behavior of a value completely at the time of declaration.

  • Heinrich Apfelmus

Generally speaking, I think there are two important flavors of reactive
programming:
Event stream based FRP

Event stream based libraries, focus at manipulating streams and are
very good at that. Joining, splitting, merging, mapping, sampling etc.
These libs are useful if you want to reason about multiple event streams at
the same time. Or when throttling plays an important role, like with
network traffic. For solving simple problems though, these libraries are
quite obtrusive (imho). They need a different mindset. Also, representing
every variable in your state as stream might become quite unwieldy.
Examples: RxJs and BaconJS.
Transparent FRP

Transparent Reactive programming on the other hand tries to hide
reasoning about time. It just applies reactive programming in the
background. Like with event based, TFRP updates views whenever needed. The
difference is that in TFRP you don't define how and when stuff updates.
While with streams you (have to) define that explicitly.

The tracker library of Meteor summarizes this nicely:

Tracker gives you much of the power of a full-blown Functional Reactive
Programming (FRP) system without requiring you to rewrite your program as a
FRP data flow graph.
https://www.meteor.com/tracker

Examples of frameworks that apply TFRP libs are knockoutJS, EmberJS and
Meteor. Mobservable is stand-alone, although it ships with a small ReactJS
binding.

These are things that makes mobservable distinctable from other TFRP
libraries:

  1. Changes are always processed synchronously and atomically; You can
    never observe intermediate values. This makes reasoning simpler and avoids
    weird edge case behavior.
  2. Mobservable doesn't ship with its own reactive structures. Instead, all
    structures behave like normal javascript objects, classes and arrays
    (although array's will have some caveats until ES7).
  3. Its a stand-alone solution.

I'll hope that answers your question.


Reply to this email directly or view it on GitHub
#18 (comment)
.

@mehdi-cit
Copy link

Would it be possible to give some insight on the benefit of using Mobservable over Tracker?
I'm new to both Mobservable and Tracker but from what I gathered around the internet Tracker usage may lead to 'infinite reactive loop'. Is such problem automatically avoidable by Mobservable? (I hope I am not saying something stupid but going through the 5 minutes tutorial, it seems the 'syncing' would only be 'evaluated' if there's a real change in the underlying data)

@mweststrate
Copy link
Member

Hi @mehdi-cit ,

The pure basics of libraries are very similar; the dependency of functions will be tracked automatically, so that the can be re-run when one of their dependencies changes. Tracker.autorun(func) is very similar to mobservable.makeReactive(func).

These are the interesting differences however:

  • Tracker will re-run function asynchronously, while mobservable re-runs them synchronously. Synchronous re-runs make reasoning about your computations easier, you cannot get a stale function from a computation. Async runs are often used to achieve atomic updates, but in mobservable this is guaranteed in the algorithm itself.
  • In Tracker you have to explicitly create dependency objects to accompany your values, or you have to use the meteor collections. Mobservable is less opiniated on the kind of structures you have to store your data in. You can just use plain arrays, objects and classes after passing them through makeReactive.
  • Mobservable does not allow you to write impure reactive functions; state should not be changed inside computations (think about it: if you need to change state during a computation, you are actually looking at data that can be derived from other data, so it shouldn't be stored state at all). This avoids issues like the infinite reactive loops

Oh it is true indeed that changes are only propagated if a computation really resulted in a new value indeed. But I'm not sure whether the same holds for tracker or not.

P.s.: an atomic update is this:

var thing = makeReactive({
  value: 2,
  squared: () => this.value * this.value,
  cubic: () => this.value * this.squared
});

now suppose you are observing cubic, and altering thing.value from 2 to 3. That change will both update squared and cubic. But squared itself will also trigger an update of cubic. Mobservable makes sure that the update of cubic is atomic; it will transition from 8 directly to 27, and not yield intermediate values like 12 (square 2 * 3) or 18 (square 3 * 2).

@mweststrate
Copy link
Member

Oh, another notable difference is that there is hardly any cleanup to do in mobservable, only sideEffects need to be disposed explicitly by the programmer.

@mehdi-cit
Copy link

Thank you Sir.
The more I read and test the more I like mobservable! I cannot help but imagine how I could use it many different ways (not just UI stuff).
I do not want to get ahead of myself but we might have here what could possibly be the greatest js library ever.

@rodryquintero
Copy link
Author

Along this lines i would also like to point out that i wish i knew about
this library before i started coding for a project i am working on.

Good job!

El El vie, 21 ago 2015 a las 9:47 a.m., mehdi-cit notifications@github.com
escribió:

Thank you Sir.
The more I read and test the more I like mobservable! I cannot help but
imagine how I could use it many different ways (not just UI stuff).
I do not want to get ahead of myself but we might have here what could
possibly be the greatest js library ever.


Reply to this email directly or view it on GitHub
#18 (comment)
.

@aleclarson
Copy link

aleclarson commented Aug 31, 2016

You can just use plain arrays, objects and classes after passing them through makeReactive.

I assume Object.defineProperty is used to make objects/classes reactive.
But how are "plain arrays" made reactive? Via some proxy?

Oh it is true indeed that changes are only propagated if a computation really resulted in a new value indeed. But I'm not sure whether the same holds for tracker or not.

Here's an excerpt from the Meteor docs about their ReactiveVar class:

"An important property of ReactiveVars — which is sometimes a reason for using one — is that setting the value to the same value as before has no effect;"

So if you're using a ReactiveVar, changes are not propagated for duplicate values. But when using Tracker.Dependency, all change events are propagated regardless.

@mweststrate
Copy link
Member

@aleclarson observable arrays are basically objects with numeric keys and all the other array methods

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

4 participants