Why are pure reducers so important in redux?

2019-06-24 04:55发布

问题:

Pure reducers have no side effects and enable things like time-travelling. They make reasoning about application behavior easier.

This is intuitive to me. But I cannot articulate WHY pure reducers lead to these positive non-functional attributes.

Can someone help me articulate why making reducers side-effect free makes reasoning about application behavior easier?

Is it because you are guaranteed to have the exact same state after running the reducers?

If so, surely even side-effectful (ie. non-pure) reducers could have this property?

回答1:

Is it because you are guaranteed to have the exact same state after running the reducers?

Yes, pure reducers are deterministic, meaning that if they are given the same input, they will always produce the same result output. This property helps with situations like unit testing, because you know if a test passes once, it will always pass.

If so, surely even side-effectful (ie. non-pure) reducers could have this property?

No, impure reducers would rely on both the inputs and on the state of the application. They could behave a given way 1000 times while you're testing, but break when your application happens to be in a particular state that you never thought to test.

Of course, it's perfectly possible to have a gap in your unit testing that misses a corner case. But if the test's results are 100% based on the inputs then you're far more likely to notice those corner cases just by looking at the stated inputs expected by the reducer.

If a function changes the application's state, then running the same function twice, or the same few functions in different orders, may cause completely different behavior. This makes it hard to reason about the correctness of the application because in order to know whether a given line of code is correct, you have to know what happened prior to calling it, possibly in a completely different part of the application.



回答2:

Is it because you are guaranteed to have the exact same state after running the reducers?

Yes, this is what makes pure-reducers the "gold standard". If the output depends only on the input, then it is very easy to test, replay, keep history, etc...

If so, surely even side-effectful (ie. non-pure) reducers could have this property?

(not the popular answer). This is also correct. non-pure reducers could also have these same properties, if you are careful. However, it is much more error prone, and (conceptually) doesn't make much sense to do. The idea that (I think) you are getting at is that everything is just input and output. You could change the line of thinking a bit and consider the internal state of your "non-pure" reducer as one more input into your reducer.

In that sense, you could imagine tracking your application state, your actions, and the internal state of your reducers, and end up with the same playback, etc, properties of your pure reducers (although you'd need a lot more code to handle that).

However, here's the rub: now you have your actual application state and your reducer's internal (and hidden) state. Who wants to keep track of two sets of state? That is what really makes the testing, reasoning, and implementation more difficult. There are more "kinds" of things to keep track of, and it is easier to miss/forget key details. In essence, if you already have a large portion of your application dedicated to keeping track of state, why would you want to keep more state hidden in your reducers?

So even ignoring doing things right for the sake of "rightness", it is conceptually simpler for your overall system architecture to keep all of your state in just one place.