Confusing terminology in TCA

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.

1 Like

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.

Not quite like the reduce function but the combine argument you pass to it.

Yes, exactly like that. Their logic of how they evolved this is behind a paywall on their site: ( https://www.pointfree.co/episodes/ep68-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 https://talk.objc.io/episodes/S01E21-structs-and-mutation) to change the function to look like this:

func reducer(state: inout MyState, action: MyAction) -> Effect
3 Likes

The Elm Architecture (TEA) has different names for both of these concepts.

  • 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.

4 Likes

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.

Ah, I see. So the write up is a bit weird, but the name is still on point. Fair Enough.

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.

Feel free to comment:

1 Like
Terms of Service

Privacy Policy

Cookie Policy