For the past 4 weeks we have been exploring an application architecture that heavily takes inspiration from functional programming. It’s primary, atomic unit is just a function, known as a reducer, and we discovered many different ways these functions can be composed together, which is a story that has played out many times on Point-Free.
We started this exploration because we saw that although SwiftUI solves many problems that we face in building an application, and does so in a beautiful and powerful way, there are still some things it doesn’t solve. In particular, we need to know how to do things like:
Create complex app state models, ideally using simple value types.
Have a consistent way to mutate the app state instead of just littering our views with mutation code.
Have a way to break a large application down into small pieces that can be glued back together to form the whole.
Have a well-defined mechanism for executing side effects and feeding the results back into our application.
Have a story for testing our application with minimal setup and effort.
So far we have solved about two and half of these problems:
We now model state as a simple value type.
We now mutate our state in a consistent way.
And finally, we were able to break down a very large application-wide reducer into small, screen-specific reducers by using a variety of compositions.
However, we consider the last point to only be solving half of the modularity story when it comes to this architecture. Although our reducers can be split up and moduralized, the views that render the state and send actions to the store cannot. They still operate on the full universe of app state and app actions.
If we were able to focus the store on just the state and actions a particular view cares about, then we increase our chances that the view could be extracted out into its own module. This would be a huge win. The inability to isolate components of an application is perhaps one of the biggest sources of complexity we see in other people’s code bases. Components start to become unnecessarily entangled with each other, and it can be difficult to understand all the ways in which a component can change over time.
So today we are going to complete the story of modularizing our architecture by first directly showing what it means to moduralize and why it’s beneficial, and then by showing how our Store
type supports two types of transformations that allow us to focus its intentions onto only the things the view truly cares about.
Let’s start with a quick tour of the code we’ve written so far.