Keep your Reducers dumb¶
The idea is that Reducer should contain only resolution to how an Effect modifies the State directly.
class ReducerImpl : Reducer<State, Effect> {
override fun invoke(state: State, effect: Effect): State = when (effect) {
// This is fine:
is Effect1 -> state.copy(someFlag = true)
is Effect2 -> state.copy(someData = effect.data)
is Effect3 -> state.copy(counter = state.counter + 1)
// Don't do this:
is Effect4 -> if (someCondition) (someFlag = true) else state.copy(counter = state.counter + 1)
}
}
If you find yourself adding conditionals, it's a smell that probably business logic is creeping from your Actor to your Reducer.
Resolution: Actor is the intended place for business logic:
- Create
Effectswith meaningful names to describe what can happen to yourState - Decide what happens inside your
Actor, based on any conditional logic or async execution, and emit the correspondingEffects - Use your
Reduceronly to implement how it modifies theState