Unlock This Episode
Our Free plan includes 1 subscriber-only episode of your choice, plus weekly updates from our newsletter.
Introduction
Alright, we’ve now accomplished what we set out to do at the beginning of this series of episodes on modular state management. First, we defined what “modular” meant: we determined that modularity was the ability to move code into a literal Swift module so that it is completely isolated from the rest of your app. Then we showed just how modular our reducers already were by breaking each one off into a framework of its own. Finally, in order to modularize our views we discovered two forms of composition on the Store
type: one that allowed us to focus an existing store on some subset of state, and another that allowed us to focus an existing store on some subset of actions. These operations allowed us to separate all of our views from more global, app-level concerns and move them into isolated modules of their own.
Subscribe to Point-Free
Access this episode, plus all past and future episodes when you become a subscriber.
Already a subscriber? Log in
Exercises
So far it has been very easy to tap into SwiftUI’s button actions in order to send those actions to the store. However, not all SwiftUI actions are that easy. For instance,
TextField
s do not expose closures for us to implement that will be notified when text is changed in the field. Instead, they useBinding<String>
values, which are 2-way bindings that allow you to simulataneously change the text field’s value and observe text field changes.This model unfortauntely does not fit our architecture since we prefer all mutations of state go through our store and reducer. However, it’s easy to fix! Implement the following function on
Store
, which allows you to construct aBinding
by providing a way to construct anAction
from the binding value and a way to extract a binding value from our store’s value:extension Store { public func send<LocalValue>( _ event: @escaping (LocalValue) -> Action, binding keyPath: KeyPath<Value, LocalValue> ) -> Binding<LocalValue> { fatalError("Unimplemented") } }
We have decided to call this method
send
so that it mimics the standardsend
method onStore
. This means that you can simply search forstore.send
in your application to find all places where user actions feed into the architecture.Using the
send
implementation from the previous exercise, change theText
view that holds the counter into aTextField
, which would allow the user to enter any number they want. To accomplish this you will need to introduce a new counter actioncounterTextFieldChanged(String)
in order to be notified when the user types into the field.
References
Playground Driven Development
Brandon Williams & Stephen Celis • Monday Jul 9, 2018This week’s episode took “playground-driven development” to the next level by showing that a fully modularized app allows each of its screens to be run in isolation like a mini-app on its own. Previously we talked about playground-driven development for quickly iterating on screen designs, and showed what is necessary to embrace this style of development.
We use Swift playgrounds on this series as a tool to dive deep into functional programming concepts, but they can be so much more. Today we demonstrate a few tricks to allow you to use playgrounds for everyday development, allowing for a faster iteration cycle.
Playground Driven Development
Brandon Williams • Friday Oct 6, 2017Brandon gave an in-depth talk on playground driven development at FrenchKit 2017. In this talk he shows what it takes to get a codebase into shape for this style of development, and shows off some of the amazing things you can do once you have it.
Playground Driven Development at Kickstarter
Brandon Williams • Friday May 19, 2017We pioneered playground driven development while we were at Kickstarter, where we replaced the majority of our use for storyboards with playgrounds. It takes a little bit of work to get started, but once you do it really pays dividends. In this Swift Talk episode, Brandon sits down with Chris Eidhof to show the ins and outs of playground driven development.
Why Functional Programming Matters
John Hughes • Saturday Apr 1, 1989A classic paper exploring what makes functional programming special. It focuses on two positive aspects that set it apart from the rest: laziness and modularity.
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 • Tuesday Oct 10, 2017A 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”.