I’m in state management hell right now with my growing Angular application. (The backend is an Elixir/Posgres JSON API server.) So, I’ve started looking at NgRx, a Redux implementation for Angular. What immediately struck me is the parallel between Elixir/Erlang gen server concepts and Redux concepts. Has anyone else noticed this?
Because they both use the functional way…
State => Action => new State
Absolutely. You will see the same pattern again if you look at the Elm architecture (which IIRC influenced React/Redux).
Indeed, redux does list Elm and other very functionally oriented ideas in the prior art sections of their documentation (https://redux.js.org/introduction/prior-art) along with less direct references to other functional languages specific implementations. On a personal note: at the time I learned it, it was one of the things that drew me towards it as a compromise between things I needed to get done and where Elm was at which made it seem like a balance between the great ideas Elm had and reality. It also feels like the same basic idea can be seen in so many other things (sometimes predating or sometimes not) once it clicks.
So, I’ve started looking at NgRx, a Redux implementation for Angular.
Both are used for application state management but they accomplish that in very different ways (in fact there is
redux-observable.js to combine both for React - if so desired). In RxJS your code is essentially “wiring up” observables for directing and transforming input streams of values (from sources) to subscribers typically resulting in a change in local state (LearnRx, Learning Observable by Building Observable).
What immediately struck me is the parallel between Elixir/Erlang gen server concepts and Redux concepts.
Redux/Elm uses a monolithic store (reducer composition notwithstanding) while BEAM processes distribute state which evolves as a result of adhering to some application specific protocol communicated via inter-process messages - so really the actual approach is very different.
GenServer itself is simply a battle hardened version of the recursive-receive-loop, providing the generic behaviour module, leaving the specific callback module to you - in order to implement a full-blown BEAM process.
@ngrx/store: Store is RxJS powered state management for Angular applications, inspired by Redux.
Looking at that page I was immediately reminded of this:
As far as I’m concerned implementing a state container with RxJS is manifesting that same complexity fetish.
This is a very detailed comment! Thanks for taking the time!
I’m relatively new to the world of functional design patterns, so please forgive any ignorance implied by the question I’m about to ask. I also want to add the caveat that I’m also coming from the Angular world, and I think that front-end frameworks tend to have a similar level of complexity fetishizing these days, so I may be looking at things through complexity-colored glasses.
Coming from AngularJS and the promise API for async data access, the Observable API (RxJS) felt like a dream come true - the main benefit being that it made it easy to pipe HTTP access and DOM events together to compose user interactions with one consistent API, rather than using one API for HTTP and another for DOM.
We’re just starting to use NgRx too, and it feels like a similar step up, because it provides one consistent place to store and process state, rather than having local state scattered across a bunch of different services and (maybe) components. On top of that, the fact that it has strong observable support makes it easy to integrate with the reset of our Angular app, which may indicate some framework bias on my part.
I guess my question is, what’s a better API for writing a redux-like library with lazy state emission? Right off the top of my head, it seems like JS generators could be a good candidate, and then if someone wanted to integrate them with RxJS they could use the
from operator with the returned generator, or something similar. I also recognize that this is a JS question on an EX forum, so don’t feel any pressure to respond. I was just thinking about it.
Anyway, thanks again for the thoughtful comment!
Welcome to the forum!
so please forgive any ignorance implied by the question I’m about to ask.
As long as we are clear that anything that I write is just my opinion and not the gospel truth.
I’m also coming from the Angular world
I’ve spent significant time with AngularJS but I’ve never looked at Angular because despite the changes it didn’t look like it was getting away from being some sort of OO leviathan (and I was an OO devotee back then). I came to that conclusion when I found myself spending a significant amount of time learning AngularJS but ultimately didn’t feel like I understood web development in general any better.
There is likely nothing wrong with Angular in an enterprise environment for web applications targeting workstations that have direct access to the corporate backbone. But if the target demographic includes mobile users the issue of a JS Budget is a real one.
Angular is just a bit too heavy if you are on a JS budget. And predictions are that average mobile performance will at best stagnate if not decrease due to the continued influx of more inexpensive (and less performant) smart devices into the general market.
promise API for async data access, the Observable API (RxJS) felt like a dream come true.
While I realize that promises are eager, observables are lazy I think it would have made some sense if observables would have been adopted into ECMAScript instead of promises.
As it is, RxJS is a bit heavy for the value it brings when you are on a JS budget. Unfortunately the TC39 Observable proposal seems to have stalled. The current thinking seems to be that it doesn’t belong in the language spec. So short of observables becoming a W3C standard (not likely) observables will require a downloadable library within the browser. Maybe a WebAssembly version will be lighter weight (not holding my breath).
The size issue with RxJS pushed one contributor, André Staltz, to create an entirely new library xstream for his own framework Cycle.js (he only needed hot observables; Unidirectional User Interface Architectures). More recently he devised a specification for “callbags” that enables observable-like behaviour without the presence of an observable library.
the main benefit being that it made it easy to pipe HTTP access and DOM events together to compose user interactions with one consistent API, rather than using one API for HTTP and another for DOM.
I think the general idea is to turn any change that “the system” might be interested in into an event value that can then just be dropped into the network of “wired up” observables that will then route and transform that value to all the essential subscribers.
rather than having local state scattered across a bunch of different services and (maybe) components.
In my view the primary use case for observables is decentralization - when a significant change happens somewhere, the observables are responsible for propagating and transforming these change events to where they need to go - that way each subscriber has complete autonomy over its own local state while only having to deal with change events they are actually interested in.
I feel the main reason RxJS is often bolted onto monolithic stores is because the monolithic store was already in place. Reactivex solved a problem that the unistore couldn’t by itself.
I believe that if you start from scratch and are committed to using observables that you should design your solution around them - and if you do, the need for a unistore will never come up.