My take on The Composable Architecture

iOS app architecture with composability and testability in mind

The Composable Architecture or TCA for short is a library to build application in a consistent and understandable manner, with composition, testing, and ergonomics in mind. This library is made by Point-Free to apply the concepts of functional programming in a practical way.

Context: Typical iOS Architecture

In the world of iOS development, there’s a few 4 most commonly used patterns in architecting an iOS application. Most notably MVC, MVP, MVVM, and VIPER. The details of these architecture is beyond the scope of this article. All these architecture has their own advantages and drawbacks. For example, MVC is simple but misusing it will cause a Massive View Controller. VIPER provides a good testability but it’ll generate much boilerplate code. At the end of the day, architectural decisions are based on the combination of use case, complexity, and many other variables. So there’s no such thing as the silver bullet of iOS architecture.

The claim

As the new guy in the iOS architecture neighborhood, TCA claims to provide:

  • Consistency: degree of firmness, density, viscosity, or resistance to movement or separation of constituent particles
  • Composition: a product of mixing or combining various elements or ingredients
  • Testing
  • Ergonomics: a product of mixing or combining various elements or ingredients

In this blog, we’ll test whether TCA fulfills what it claims to do or not.

Experiments!!!

We’ll create a song reader app that have the capability to add songs to favorites and see all the favorites we have. All the code snippet in this blog is taken from my Lagu Sion implementation. For more details, please go here.

Setting up

To install this library, generate a new iOS application in your Xcode and add TCA to your Swift Package Dependency. More info, head here.

Building the app

In this blog, I’ll build the app from the smallest component possible and work ourselves up and wire everything up.

Modeling Song: Simple, we can make a struct that contains all the fields needed. In this case we need to generate the id and song

Modeling Action to be made at on Song View: Simple, just use Swift’s enum to enumerate all the possible action.

Modeling what will happen when action appears: Here, we start to use TCA’s first feature: Reducer. TCA will receive all the action that the views will trigger and after that, the action will be processed through the reducer. In TCA, reducer is the place where logic happens. State mutations, logical operation, and action handling is happening in the reducer.

Implement how the Song View will look like: Simple, we create a view just like other SwiftUI views, but at the end, we’ll wire up the view with the state through a concept called Store

Previews: Since we haven’t wire up the view to any entry point, we can use SwiftUI previews to see how our view implementation is going.

Finally, testing the implementation

For now, let’s take a break from coding and look back what we have made here. First, we have modeled the state of the Song View and actions. Next the reducer and the view. TCA provides us with a framework to pass triggers from view to the reducer through Store . With store, developer can make SwiftUI previews easily. This checks the first claim that TCA is ergonomic.

Second, testing. Store concept also has it’s corresponding ergonomic component in testing named TestStore . This component enable us to intercept the actions triggered, sequence of actions, or even checks the state after every action sent or received. This checks the second claim that TCA is designed with testing in mind.

Cool, so far we have covered how TCA is ergonomic and designed with testing in mind. Let’s go to the next part of the implementation to prove the rest TCA claims.

Modeling Main List View: In the list view state, we store two lists. The list of songs, and favorite songs.

Modeling the Main List View Actions: Here, we’re going to use our previously made songReducer for each song we have in the main list.

Let’s take a break and see what we did. First, we model the MainState just as we did on SongViewState . After that, we create the model of MainAction and mainReducer . This shows that building component in TCA is consistent. Every layer of the implementation follows the same consistent pattern. This checks the consistency claim.

Next, TCA also gave us the tools we need to reuse and compose the songReducer in the mainReducer . As we know, the main state, composes song state directly or indirectly. If this happens, we can always compose any state with many other smaller states and we can still have the visibility of anything that happens in the child component. This checks the composability claim.

Last experiment I’d like to show is to fast forward on how we’re going to wire multiple sibling states to the root state.

Assume we have implemented the Settings and Favorites section.

Model App State: To wire up all the sibling states to single state, we have to define how are the AppState behave when there’s a change in AppState or if there’s any changes in the child states.

Model Action and Reducer:

Let’s stop and review again. In this section, we made the state, actions, and reducer. But if we look closely, appReducer is doing nothing but composing all the child reducers and passing its respective states and actions using pullback. This ultimately checks again the composability claim of TCA.

What I love

As we can see from the experiment, TCA delivers what it promised. Consistency, Composability, Testing, and Ergonomic. Personally, my favorite thing in TCA is how we can build mini components and wire it up to the chain until it has reaches the root/single source of truth. This ensures data consistency throughout screen and states.

What I don’t love

Right now, there’s no valid proof that this architecture is used in a huge app with high complexity. So we still have no idea on the extent of this architecture.

Where should I go next?

If you’re interested in how this library is designed, go to Composable Architecture series. If you’re into functional programming, especially in Swift, check out Point-Free’s site. They cover a lot of interesting ideas of functional programming specifically in Swift. If need more example of a working app using TCA, visit TCA’s GitHub examples.

References