I’ve Made a Redux Architecture Library for iOS and Called It Puredux
Not long ago, I started to roll out Puredux v1.0.
Basically, Puredux is a UDF architecture framework for app state management with Redux ideas in mind. Store, Reducers, Actions dispatching, and so on. BTW, if you are not familiar with UDF and Redux, here is a post for you.
First of all, I got inspired by SwiftUI's data-driven UI and decided to build a framework that could bring the data-driven approach to UIKit. I wanted a framework to be seamlessly used both with UIKit and SwiftUI.
Another goal was to remove the borderline between UIKit and SwiftUI so that the project could be easily migrated from UIKit to SwiftUI with fewer problems.
Story behind Puredux
It all started with my goal to increase my performance as an iOS dev.
I didn't like that making an iOS app either takes a ton of time, or it can be made fast but in a dirty way that eventually blows up with bugs, lack of reusability and testability, and all those developers' problems.
Another goal was to eliminate the borderline in the development of "small and simple apps made by a single dev" and "big and complicated apps made by a large team". In my opinion, there should be an opportunity for seamless scaling up of the project instead of throwing away and rewriting when the team becomes big.
In other words, the architecture of the app should be flexible enough for that. Flexible enough to be simple and resource-efficient, when needed allowing to safely get into the tech debt. Flexible enough to get out of the tech debt and scale up when things become very complicated.
To achieve this it should be very testable and extendable and scalable and tightly coupled and so and so on, but preferably without dozens of boilerplate classes/structs for every small simple screen.
One of the tasks on the way to my goals was to find a cheap and simple CoreData alternative for reliable entity state management. Proper app entities' state management eliminates a good half of the app's bugs.
The second part of all bugs usually relates to the management of the rest of the app's state. That's why I also wanted a reliable way to manage the entire app state, not only entity models.
Another task on my way to 10x engineer was to unify codebases and development approaches across several projects: personal, work, and freelance, so I could share code and typical solutions.
Using Redux in iOS Development
Back in 2020, I started to get interested in aspects of using Flux/Redux-like architectures in iOS.
SwiftUI was out. Its data-driven UI implementation approach looked like it was designed with Flux/Redux in mind.
I got heavily inspired by AlexeyDemedetskiy and Thomas Ricouard's stuff and started experimenting with Redux in my pet project.
After experimenting with my pet project, I used it in a small prod project and then in another one. Eventually, redux-related code moved to a separate module, that finally became Puredux.
It's easy to use and understand what's inside because it's small and simple.
Puredux consists of small bricks: PureduxStore, UIKit bindings, SwiftUI bindings, and a few more things that are on their way.
Puredux + UIKit + SwiftUI Compatibility
If you are having a UIKit-only legacy project with an old minimum deployment target, Puredux can be still used with it. For a brand new feature, for example.
Strict but Fair
On the one hand, Puredux is restrictive in the sense of the data flow and UI updates as a UDF framework.
On another hand, it has no limitation on how the reducer should look like or how side effects are performed, allowing you to use your imagination at full throttle, depending on your needs. Environment injection, feature toggles, A/B testing, or whatever is possible.
Async Work Under Control
Puredux allows not to care about async work, threading, race conditions, and inconsistent app states by simply doing things where they should be done.
The state is reduced in the background. Props are prepared in the background. UI is updated/rendered on the main thread. As simple as that.
One of the "classic" Redux problems of the global state exposed to every app's feature is finally solved in Puredux.
PureduxStore is capable of creating proxy stores with local state mapping allowing us to isolate features from the entire app state.
Puredux allows us to deduplicate state changes and to avoid unwanted UI updates both for UIKit and SwiftUI.
Clean App Layers
Puredux does not penetrate all the layers of the app.
It acts as an infrastructure, allowing to glue the layers together, without creating a lot of dependencies.
It means that your UIKit or SwiftUI code will know almost nothing about Puredux, won't get tightly coupled to it, and might be reused in other places.
You can implement your app with UIKit or SwiftUI and connect it to PureduxStore.
Got fed up with Puredux? No problem, it's VERY easy to clean up UI from Puredux-related code.
Show Me the Code
There is already a good number of examples and Q&A in the documentation that could be found on Github.
You are welcome to add GitHub stars, follow, share with friends, and ring the bell.
I also have some examples of apps to show more detailed use cases, but they are pretty old and need to be revisited and updated. And I also plan to make a few "how-to" posts. So feel free to subscribe and stay tuned.