Composable State Management: Reducers

Episode #68 • Aug 5, 2019 • Subscriber-Only

Now that we understand some of the fundamental problems that we will encounter when building a complex application, let’s start solving some of them! We will begin by demonstrating a technique for describing the state and actions in your application, as well as a consistent way to apply mutations to your application’s state.

Collection
Reducers and Stores
Composable State Management: Reducers
Locked

Unlock This Episode

Our Free plan includes 1 subscriber-only episode of your choice, plus weekly updates from our newsletter.

Sign in with GitHub

Introduction

The past few weeks we have explored the problem space of application architecture, and tried to uncover the root of what makes it so complicated. We ended up building a moderately complex application in the process, and although it was a bit of a toy example, it accented all of the pain points we encounter when building applications. In particular, we saw:

  • We want to be able to have complex app state that can be shared across many screens so that a mutation to one part of the state is reflected in the other screens instantaneously.

  • We want to be able to mutate the state in a consistent manner so that it’s obvious to newcomers to our code base how the data flows through the application.

  • We want to be able to build large, complex applications out of simple, composable units. Ideally we’d be able to build a component in full isolation, possibly even in its own module, and then later plug that component into a much bigger application.

  • We would like a well defined mechanism for executing side effects and feeding their results back into the application.

  • And finally we would like our architecture to be testable. Ideally we should be able to write tests with very little setup that allow us to describe a series of actions a user does in the app and then assert on the state of the app after those actions have been performed.

These are very important problems to solve because they allow us to scale our code base to handle many features and many developers working on the same app. Unfortunately, SwiftUI doesn’t solve these problems for us completely. It gives us many of the tools to solve it for ourselves, but it is up to us to take things the extra mile.

And so today we begin doing just that. We will introduce an application architecture that solves these problems. It’s opinionated in much the same way that SwiftUI is. It tells us exactly how we are supposed to model application state, tells us how mutations are applied to that state, tells us how to execute side effects and more. If we follow these prescriptions some really amazing benefits will start to pop up. And of course, the most important part, this architecture is entirely inspired by functional programming! We will draw inspiration from simple functions and function composition in order to understand how we can solve all of these problems.

We of course don’t claim that this architecture is a panacea and will solve all of your problems, and there will definitely be times where it seems that the problem you are working on simply does not fit this framework. However, we still feel that it’s worth exploring these ideas, and it can also be surprising how many problems can be solved with this architecture if you look at the problem from the right angle.

Recap: our app so far


References

  • Reduce with inout
    Chris Eidhof • Jan 16, 2017

    The Swift standard library comes with two versions of reduce: one that takes accumulation functions of the form (Result, Value) -> Result, and another that accumulates with functions of the form (inout Result, Value) -> Void. Both versions are equivalent, but the latter can be more efficient when reducing into large data structures.

  • Elm: A delightful language for reliable webapps

    Elm is both a pure functional language and framework for creating web applications in a declarative fashion. It was instrumental in pushing functional programming ideas into the mainstream, and demonstrating how an application could be represented by a simple pure function from state and actions to state.

  • Redux: A predictable state container for JavaScript apps.

    The idea of modeling an application’s architecture on simple reducer functions was popularized by Redux, a state management library for React, which in turn took a lot of inspiration from Elm.

  • Composable Reducers
    Brandon Williams • Oct 10, 2017

    A talk that Brandon gave at the 2017 Functional Swift conference in Berlin. The talk contains a brief account of many of the ideas covered in our series of episodes on “Composable State Management”.

  • Side Effects
    Brandon Williams & Stephen Celis • Feb 5, 2018

    We first discussed the idea of equivalence between functions of the form (A) -> A and functions (inout A) -> Void in our episode on side effects. Since then we have used this equivalence many times in order to transform our code into an equivalent form while improving its performance.

    Side effects

    can’t live with ’em; can’t write a program without ’em. Let’s explore a few kinds of side effects we encounter every day, why they make code difficult to reason about and test, and how we can control them without losing composition.

Downloads

Get started with our free plan

Our free plan includes 1 subscriber-only episode of your choice, access to 64 free episodes with transcripts and code samples, and weekly updates from our newsletter.

View plans and pricing