Hi guys, my name is Steve. Now I’m a mobile platform engineer at VinID which is one of largest super-app in Vietnam.
We’re serving millions of customer and always in the top of #LifeStyle category on the Appstore.
We’re a large business then we need to choose a suitable architect design to fit our requirements then RIBs is our final decision.
RIBs is a new mobile cross-platform architect design from Uber. If it is a first time you hear about that, it’s a recommendation to take a look at the homepage of RIBs.
Today I would like to share something about the reusable principle while applying the RIBs architect design.
In this article, I only mention about 2 components of RIBs: Interactor & Presenter.
Interactor is a component where we store all business logic. It seems like a Controller in MVC architect design or ViewModel in MVVM architect design.
Presenter is an abstraction of a View. Because View will be implemented by native platform then we use the Presenter while talking about higher level of architect design.
For higher level of design, RIBs abstracts the Interactor & Presenter by their abstractions: Interactable & Presentable. The relationship of them can be declared as below:
1. Interactable define an interface, the Interactor implements the detail.
2. Presentable define an interface, the Presenter implements the detail.
3. The Interactor contacts Presenter via Presentable by delegate pattern.
4. The Presenter contacts Interactor via Interactable by delegate pattern.
Let’s imagine we have a feature named Nearby Applied Places which has been implemented to suggest users about the nearby applied places base on their location.
In RIBs architect design, we define a feature like a RIB node. Again, if you’re unfamiliar with RIBs, it’s a recommendation to take a look at Uber RIBs homepage here: https://github.com/uber/RIBs
The Interactable & Presentable of our feature look like this:
Our Nearby Applied Places RIB has been implemented completely and working well.
Next, let’s imagine we get a new requirement need to implement a new sub-feature named Nearby Applied Places Widget. Widget is a smaller feature of a main feature will be displayed on the home page of the App where user can access informations quickly without opening the main feature.
Hmm… Let’s continue creating new RIB node for its widget, it’s a first thing I have considered.
After thinking again, I realized that the widget RIB & its main RIB share many logics, for example: The widget inherits all methods and properties from its main Interactor & Presenter excepts the loadMore() method. Only UI/ View is difference (tableView for main RIB & collectionView for widget RIB).
We should reuse the main RIB components instead of implementing from a new scratch for widget, it means we don’t need to create a new RIB for widget, just extend the main RIB only!
Now, our idea looks like this:
By this way we can reuse completely the Interactor & Presenter of the main RIB, just extending one more view for widget feature.
Now everything looks good but as we’ve mentioned before, the widget doesn’t use the loadMore() method because the requirement restricts the number of items will be displayed on the home screen. We should hide this method from widget then the main Interactor should be implemented by 2 sub-Interactable like this:
Our codes look beautiful thank to the awesome Protocol Composition feature of Swift.
Now, our relationships look like this:
Each view needs to contact Interactor by right Interactable to make sure they’re working under the right scope.
iOS system also provides widget feature where we can bring our widget from the main App to Home screen of iPhone/iPad:
If a nice day, our UI/UX team & Product Owner want to bring the Applied Places to the iOS widget, we’re ready to do it quickly, just implementing step-by-step like the widget on the home of the App.
The reusable principle should be applied not only for architect designs but also our daily coding. Uber RIBs is an awesome architect design which fits a super-app or platform ecosystem requirements but one of its downsides is mother of boilerplate codes. To avoid that & make our codes be clean & expandable later, it should be reusable first!