As we're gearing up for our new Angular project, we are evaluating various architectural concepts to employ within our system--especially state management. In the past, there were natural complexities with client components being proactively notified. Today, enter reactive programming and central stores.
I understand the nature of maintaining a 'large' central store with corresponding actions (inside various services), reducers, and subscribers that contains state for the entire app. I also see the benefit of stratifying unit tests with these pure function reducers. The question I have is how does this stack up to the classic notions of 'separation of concerns' and 'single responsibility' where state is maintained for those components via their dedicated services (dependency injected) while a semblance of decoupling is provided as well?
Why use large central stores instead of singleton services that maintain 'contained' state who emit changes to subscribers AND maintain that separation of concerns (eg: customer data is separate from inventory data). Although, there are allusions to this in other parts of SO and the web, I don't see references directly tackling this question. Thoughts comparing these 2 notions (central store state vs dependency injected service/singleton state) and/or references that do is greatly appreciated.
It's definitely a good start in your Angular journey to ask yourself that kind of questions about project architecture.
With AngularJs (v1.x) I didn't really know what was the best pattern to work in a reactive way and make sure every components could subscribe to a data somewhere in a service and if another component called the service to update some data, others components would update.
Back then, I tried multiple solutions and ended up by adding RxJs
to my project. It was probably overkill as I wasn't aware of RxJs
super power and I basically didn't use any operator, I was just subscribing.
6~8 months ago, I discovered Redux
and found this approach very interesting. I decided to dig more into that idea of centralized store, with pure functions and immutable data. It was one of the best choice as a web dev I've done. You can use Redux
outside any framework. So even if I do have to make an example with JQuery
and maintain quite an amount of data, I use Redux
.
One thing I really like with Redux
is to normalize my data and manipulate them like a database where a reducer manipulate a table for example. "Computed view" with selectors
is also a powerful way of composing your data as you wish from raw "tables".
The question I have is how does this stack up to the classic notions of 'separation of concerns' and 'single responsibility' where state is maintained for those components via their dedicated services (dependency injected) while a semblance of decoupling is provided as well?
Well, as you tagged ngrx
I can image that you plan to use it with Angular (v2 or +) and the separation of concern is great. You split your logic by Reducer for manipulating the tables, but how about making ajax calls for example ? For that kind of side effects, you should use ngrx/effects. So you'll still have your services + reducers. Effects
will allow you to react to a dispatch for a given action.
For example, if you dispatch an action
with the type FETCH_USER
, in your reducer you simply toggle a boolean isFetchingUser
to true (so you can display a spinner in your view maybe). Then from a user.effect.ts
(which is a service), you can catch the FETCH_USER
action and call your backend. Once the response has arrived, dispatch from the effect an action FETCH_USER_SUCCESS
and pass the data from ajax call into the action payload
.
If you want to take a look to some code, I've created a demo on Github called Pizza-Sync. It uses @ngrx/store
and @ngrx/effects
with normalized data.
If you've got the Chrome or Firefox Redux devtools extension, you can take a look into the store and the actions.
Hope it helps, let me know if you have further questions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With