Closed aaronshaf closed 9 years ago
@aaronshaf I'll try to describe some of the motivations that led to most.js and some of the things we think are interesting about it.
I'll be up front by saying that I don't really think of most.js, bacon, rxjs, kefir, etc. as a competition that most.js needs to "win". They are all useful tools in the reactive programming space. All of them have likely learned from and borrowed ideas from each other. The community will benefit from friendly competition and cooperation.
I'll be honest about my criticism of those libs here, but I have a ton of respect for them and their authors & contributors. I'm sure they have criticisms of most.js they could share.
In terms of personal motivation wrt reactive programming, I think it's an important concept that provides a lot of advantages: it naturally handles asynchrony and provides a model for dealing with complex data and time flow while also removing (or at least lessening) the need to resort to shared mutable state. It has many applications: interactive UIs and animation, client-server communication, IoT and sensor networks, etc.
In terms of motivation for most.js, I looked at existing implementations and felt there were several areas that could be improved upon. Here are a few of them:
Performance
Looking at the architecture and implementation of other libs, I felt it should be possible to get at least 1 to 2 orders of magnitude better performance. Kefir had done some good work in this area, but I felt that there were still plenty of perf gains to be had.
The perf test results indicates that most.js is achieving its goal in this area. My hope is that by publishing those numbers, and showing what is possible, other libs will improve as well.
I've only measured memory informally, so I don't want to comment on it in detail. However, it is also favorable compared to other libs.
Modularity
Other libs seemed not to have truly modular architectures. Bacon is implemented in a single file. RxJS is only "modular" in the sense that it's files must be concatenated in the correct order. I feel Kefir is a bit more modular, but as far as I could tell, also did not embrace a real module system such as CommonJS.
Most.js it highly modular CommonJS (I wanted to go ES6, but felt it still required a bit too much tooling, and that generated code would likely impact performance goals). It's internal Stream/Source/Sink architecture and APIs are simple, concise, and well defined (although not yet documented, which is an obvious problem!). Combinators can be implemented entirely in terms of that API. They don't need to use any private details. This makes it easy to implement new combinators externally (ie in contrib repos, for example) while also guaranteeing they can still be high performance.
If you wanted to, you could write a file similar to the root most.js module, and make your own customized reactive streams library, without worrying about concatenation order, or internal details. Standard tools such as browserify, webpack, and the like would be able to build it easily, with no additional tools required and without having to rely on manual concatenation ordering, etc.
Implementation simplicity
I felt the code in other libs was overly complex. Aside from making combinators less "obviously correct", I also felt that their complexity was likely causing performance issues. I felt a simpler implementation must be possible, and that it would lead to a more performant lib overall.
Promise integration
In my mind, promises and async reactive streams are naturally complimentary, but also should not be conflated. The relationship between sync "sequence" and "value" is clear, and the async analogue needs to be, too. By taking the notion of a sequence and a value and lifting them into the async world, it makes perfect sense to me, for example, that reducing an async sequence should produce a promise. Hence, most.js uses promises when a single value is the natural sync analogue.
Thank you!
@aaronshaf You're welcome. We're now looking at ways to integrate some of this information into the README, so I'm very glad you asked the question!
That README change is very nice, but I just found my way back to this old closed issue because the README doesn't mention any of the similar libraries. That made me first wonder if Most might be "yet another library implemented by someone who hadn't heard five similar libraries yet", but in fact it is a library implemented by someone who understands the direct competitors and had some specific differences in mind. The latter is of course a strong positive signal that it is a library to take seriously. I think making that more clear on the README could make the project more appealing to first-time visitors.
@kylecordes Thanks for the suggestion. Perhaps we could add an initial paragraph under Why most.js for Reactive Programming? mentioning other libs, and providing slightly more background and motivation. Do you think that would help?
Yes, that would definitely help. The idea is to give a sense of why someone would consider Most, and perhaps in the process make it clear what sort of developer should consider it. (Although, that last bit is already well accommodated by the bold headline at the top with "monadic" in it. People who know what that means will be drawn to it, people who don't will be pushed away.)
Speaking of advantages, the readme discusses how this reactive implementation is performance centric; it would be great to include a sentence about its relative size to other implementations also. (Some of my work is over in the Angular 2 space, where there is generally excitement about RxJS, but less excitement about its code size, but this is only important in applications aimed at smaller hardware.)
Thanks for those suggestions @kylecordes. I've opened https://github.com/cujojs/most/issues/228 to discuss adding a bit more to the README. Please feel free to add more thoughts there!
Brian, why cujo? What makes it special over, say, bacon.js and others?
Thanks :-)