I am officially the primary maintainer of Uber’s RIBs iOS GitHub Repository
I’m excited to help maintain and support this wonderful architecture!
RIBs is a cross-platform architecture Uber came up with to power their mobile apps back in 2016.
I had the pleasure of learning about and working with this architecture during my time at Uber. I was sold on its modular and composable nature, clear separation of layers, and deep Clean Architecture roots.
Since then, it’s been my favorite architecture for mobile apps and I’ve used it for many years in personal and work projects applying it to codebases big and small.
Lately, I volunteered to help with maintaining the repo and I am now the official primary maintainer!
What is RIBs?
RIBs is an acronym that gives the name to the smallest logical piece of this architecture, a RIB, a group of 3 classes: Router, Interactor, Builder.
In RIBs architecture, your entire app consists of a tree structure of RIBs where each RIB represents a business scope of your app and can have zero or many children.
As the user interacts with the app and business logic demands, some RIBs will be instantiated and routed to and added to the RIBs tree, and some will be routed away from, deallocated, and detached from the RIBs tree.
This approach makes it very easy to break down your app into business scopes with single responsibility and logic completely isolated from each other. This way, a team can work on a subset of RIBs within a larger application and have their own “sandbox” in them and change whatever it wants without risking breaking other RIBs across the app.
The uniqueness of this architecture is two-fold:
it’s a complete end-to-end solution that not only has an architecture and a set of guidelines but also a framework to enforce structure (unlike other architectures such as MVVM, MV*, VIPER, etc. which are all essentially just sets of loose guidelines).
RIBs is business logic driven, not view/UI-driven. Pretty much every other mobile architecture is view-driven where the architecture itself and the application cannot exist without a view and the view is the very first and smallest component of the architecture. In RIBs, each RIB can exist by itself (aka be headless) without a view or can optionally have a view. UI updates and anything else in the view layer is driven by the business logic in the RIB rather than the other way around. It is a very subtle but profound difference that makes this architecture much more flexible and superior to any other client side architecture out there.
That said, of course, most of the RIBs will have an associated view that they will manipulate:
There is much more that I can say about this wonderful architecture but I’ll do it in followup posts in the future. If you want to learn more about it, here’s a list of other resources that might help:
https://insideiosdev.com/episodes/alex-on-ubers-rib-architecture-2d362fd3
RIBs - Uber's new mobile architecture that scales to hundreds of engineers by Tuomas Artman
A few years back, I started to make a video course about it, so if you’re interested you can check it out here, it’s free!
What are the plans for RIBs?
Since RIBs is a cross platform architecture at its core, it originally was implemented and published with Android and iOS combined together, all in one repo. Since there have been more developments happening in the Android implementation version iOS lately, Uber decided to split them out and give the iOS implementation its own github repo.
There are lots of outstanding issues and questions about the iOS framework in the original repo. I’ll start slowly moving those to the new repo and will try to help resolve them and answer questions as best as I can.
There is some modernization that needs to happen to the framework:
Add SwiftUI support
Add Swift Concurrency (async/await) support
While RIBs technically can support both out of the box, SwiftUI with UIHostingController, and async/await by wrapping it into a RxSwift Single or Observable, it would be nice to have helpers and convenience methods around it built-into the framework itself to make the integration smoother.
For anyone who’s transitioning and migrating existing codebases to RIBs, it would be nice to have some convenient APIs to provide that functionality for legacy code integration. I have encountered these issues myself in integrating RIBs into existing codebases - there needs to be some sort of support of attaching RIBs outside of RIBs tree hierarchy, to something like a legacy UIViewController. However, it’s not applicable to anyone, who, like Uber, starts from scratch and builds their entire application with RIBs from the getgo. For anyone who’s transitioning and migrating existing codebase to RIBs it is much more practical to start with leaf RIBs rather than the root and work your way up the tree. It is also technically achievable today with the current framework but you’d need to know the internal mechanics of how a RIB is attached to a RIBs tree and then replicate the same actions adding one to a view controller.
As I have other commitments like my ongoing work on my book, there is no timeline on these improvements, but I’ll try to add them as soon as I can and will post on substack about the progress.
Conclusion
I encourage everyone to try this fantastic architecture. It truly has been the biggest unlock for me for scalable application development!