RxJS is great. So why have I moved on?
medium.com
RxJS is great. So why have I moved on?
1–10 of 40 posts
Re: RxJS is great. So why have I moved on?
#2In the meantime, the biggest issue I've had with bacon is figuring out what are the best practices in organizing the code. One does end up with a lot of streams or variations/combinations on streams used for different purposes. Eventually it does become hard to follow, as the author mentions, though because all state is self-contained you can change any one part with a high degree of confidence that it won't break other features.
Still there must be some ideas out there that don't involve incorporating a full blown framework/SPA architecture. The author of bacon has a blog post on the subject but it seemed to me that there could be better ways still. Anyone have any suggestions?
Re: RxJS is great. So why have I moved on?
#3Re: RxJS is great. So why have I moved on?
#4As a disclaimer I'm the author of an Rx-inspired library for Scala [1] and that also works for Scala.js in the browser. Shameless plug aside, Scala also has Future/Promise in its standard library and now due to macros support it got scala/async [2], a library that gives you the "await" keyword in Scala, so in Scala you also get this kind of M:N multithreading that looks like synchronous code. This in addition to Akka and other possibilities.
In other words I've worked with both approaches and Core.async is not comparable with Rx. I do understand the author's woes, as sometimes the Rx model is misapplied, plus it's hard to understand for the unfamiliar.
One of my colleagues was complaining once that "but I don't know what the debounce operator does and it's hard for me to read that". And I told him: yeah dude, but try implementing the logic in debounce by yourself and see how readable that is.
And that's exactly why Rx is problematic. On one hand because stream processing is fundamentally hard, no matter what model you choose. And on the other hand Rx comes with a lot of useful operators that do a lot for you, but then you have to learn about them.
For the naysayers, I'll just leave this piece of code with a challenge for implementing it with core.async and compare in terms of readability and note this is a copy paste from actual production code ...
commands
.groupBy(w => (w.assetID, w.commandID))
.mergeMap { gr =>
gr.timeout(30.seconds, Observable.empty)
.throttleLast(1.second)
.distinctUntilChanged
.echoRepeated(5.seconds)
.whileBusyBuffer(DropOld(30))
}
What it does is to split the signals for each asset and command, for each of these it's supposed to sample the signal by 1 second, but in case the same value is repeated over and over again or in case the channel goes silent, then the last value will end up signaled every 5 seconds (reducing the traffic to our OpenTSDB). Finally for each key we close the stream after 30 seconds of inactivity. And then for each such key it does buffering of at most 30 elements and in case the consumers are too slow, then these buffers start dropping older elements on overflow. And then we merge everything back.I would also show you how we are modeling state machines with the "scan" operator, state machines that are evolved from signals coming from multiple sources, but the sample would be too long. In any case "scan" allows you to use pure functions and data-structures, so you can test your business logic without interactions to third party services, mocks, stubs or whatever.
I have to deal with such code all the time. And I've seen such code implemented in a classic fashion as well. You basically end up with Maps storing stuff and with ifs and whiles and with manual timers in an unholy dance of mutation so hard to understand and debug that it would make grown men cry.
But then such solutions are not silver bullets. Rx, CSP, futures, actors are not silver bullets to be applied everywhere, with all of them having a sweet spot for which they excel. I'm actually using Rx, actors, futures, scala/sync in the same project and it's great.
Also, one last note: Rx is not FRP ;-)
Re: RxJS is great. So why have I moved on?
#5What do you think of something like http://mweststrate.github.io/mobservable/ ?
https://github.com/cjohansen/js-atom/blob/master/atom.js
https://github.com/dustingetz/react-cursor/blob/master/src/C...
Vastly less code than https://github.com/mweststrate/mobservable/tree/master/src. Cursor+Atom has nothing to do with Rx or core.async, of course, and is probably not the future. (I say this as the maintainer of react-cursor)
Re: RxJS is great. So why have I moved on?
#6Discovering and mastering bacon.js/FRP completely changed the way I think about programming. It hugely increased the quality and stability of my code in ways that continue to surprise and amaze me. I cannot recommend it enough, but this article definitely has me curious about ClojureScript. In the meantime, the biggest issue I've had with bacon is figuring out what are the best practices in organizing the code. One d…
[1] https://github.com/evancz/elm-architecture-tutorial/ [2] http://elm-lang.org/
Re: RxJS is great. So why have I moved on?
#7Re: RxJS is great. So why have I moved on?
#8Discovering and mastering bacon.js/FRP completely changed the way I think about programming. It hugely increased the quality and stability of my code in ways that continue to surprise and amaze me. I cannot recommend it enough, but this article definitely has me curious about ClojureScript. In the meantime, the biggest issue I've had with bacon is figuring out what are the best practices in organizing the code. One d…
I don't have non-architecture answers for how to organize code since that's pretty much the point of an architecture. Most of the application organization patterns around the React space are only ~200 lines of code and a description of how the pieces fit together. You don't have to adopt the whole thing immediately but you don't get the full benefits of a pattern until everything works the same way.
For my part, I got a job writing clojurescript full time and migrated the app to re-frame [1][2] this year in pieces over the course of a couple months and it's the first frontend architecture that's made me happy in over a decade of continuous searching. The js version is Redux but I think Redux is missing middleware as a concept.
[1] https://github.com/Day8/re-frame/ [2] https://github.com/binaryage/pure-frame What this provides is a complete event cycle of completely pure functions (the state swap happens in the framework) with all the data in an immutable map in a single atom. By namespacing my subscriptions and events I can see a problem, look at the component, and know immediately where my problem is within ~10 lines of code. It's not perfect but it's pretty good.
One thing that doesn't get mentioned often enough when talking about Clojurescript is the potential for doing server-side rendering of the app without having to run node. [3]
[3] http://yogthos.net/posts/2015-11-24-Serverside-Reagent.html
Re: RxJS is great. So why have I moved on?
#9Discovering and mastering bacon.js/FRP completely changed the way I think about programming. It hugely increased the quality and stability of my code in ways that continue to surprise and amaze me. I cannot recommend it enough, but this article definitely has me curious about ClojureScript. In the meantime, the biggest issue I've had with bacon is figuring out what are the best practices in organizing the code. One d…
I wrote a 20k LoC bacon app in 2014 and had the same issue with being able to understand all the pieces individually but having trouble comprehending the whole system. I don't have non-architecture answers for how to organize code since that's pretty much the point of an architecture. Most of the application organization patterns around the React space are only ~200 lines of code and a description of how the pieces f…
Redux totally has middleware (you actually need middleware for async actions).
Re: RxJS is great. So why have I moved on?
#10Discovering and mastering bacon.js/FRP completely changed the way I think about programming. It hugely increased the quality and stability of my code in ways that continue to surprise and amaze me. I cannot recommend it enough, but this article definitely has me curious about ClojureScript. In the meantime, the biggest issue I've had with bacon is figuring out what are the best practices in organizing the code. One d…