I see things you want to encapsulate here, and that looks sane to me, but there's a couple usages that I find misleading.
From the README:
Reducer : A function that describes how to evolve the current state of the app to the next state given an action. The reducer is also responsible for returning any effects that should be run, such as API requests.
Store : The runtime that actually drives your feature. You send all user actions to the store so that the store can run the reducer and effects, and you can observe state changes in the store so that you can update UI.
Reducer, like the reduce function? Well, obviously not, if the effect is change the state. This doesn't seem like repeatedly applying a function to a collection of data to accumulate a single value.
Likewise, a store isn't typically a runtime. Most of the time it's where the data created or wanted by the user is stored, as distinct from the UI State.
I'd suggest these two concepts be called something like evolver and, well, controller.
Not the library author but I‘d like to point out that Reducer and Store are widely used in similar architectures, such as Redux, and are thus more likely to be understood by more people.
I’ve never heard the term Evolver before and I think Controller has so many connotations that it might lead people to misunderstand what a store is and how they should use it.
I agree that calling it “runtime” might be a bit confusing.
Yes, exactly like that. Their logic of how they evolved this is behind a paywall on their site: ( Episode #68: Composable State Management: Reducers ). But in general a reducer takes an accumulator and a value, combines them and returns to return an updated accumulator.
func reducer(accumulator: [String: Int], value: Int) -> [String: Int] {
//update the accumulator (or state in TCA terminology) to create a new state
var acc = accumulator
let key = String(value)
acc[key] = (acc[key] ?? 0) + value
return acc
}
The TCA reducer has the same shape as above, with the addition of Effects being thrown off as part of the state updates:
func reducer(state: MyState, action: MyAction) -> (MyState, Effect) {
//Do some work to accumulate state updates
}
They take advantage of the fact that returning a value is the same as using an inout param (see Structs and Mutation - Swift Talk - objc.io) to change the function to look like this:
Reducer: In TEA, the function that takes a state and an action and returns a new state is usually called update.
Store: In TEA, the runtime system is called the kernel. There is only one kernel and there's no single object or type that represents it. In the Composable Architecture, you have to call a Store to access your model or to send an action. In Soviet Russia Elm, kernel calls you.
Just my 2c as someone who came from ObjC and then Swift for a few Years and then went to JS land and just recently refreshed on Redux...
As said, reducer is a common term. Store as used here is not intuitive and imho misleading because it does more than a Store if it manages all side-effects of all actions. If TEA calls that kernel that feels more reasonable to me.
FYI: I just started a more scoped discussion for renaming Reducer to ActionHandler since I agree with the confusing terminology feedback here and I wanted to start with what feels like the most confusing term to me and my team. I agree that Store could also be improved, but at least it is partly intuitive, unlike Reducer IMO.