I realize that the RIBs framework is flexible enough to allow multiple approaches, but I'd like to collect some thoughts on design philosophy here.
Imagine a scenario in which we have a menu of options, the MainMenu RIB, which links to a child, ProfileMenu. ProfileMenu then links to each of three possible screens: ProfilePhotos, ProfileSummary, and ProfileHistory. The hierarchy looks like this:
|
|__ProfileMenu
|
|__ProfilePhotos
|
|__ProfileSummary
|
|__ProfileHistory
Would it be best practice to combine the Photos, Summary, and History RIBs into one and call it Profile which can display multiple Views, or should these indeed be separate RIBs?
Essentially, ProfileMenu performs no business/data logic aside from routing to the chosen menu selection. And each of its child RIBs are relatively minimal themselves. This is what leads me to prefer the approach of combining all four Profile RIBs into one, and just having the ProfileInteractor decide which new View to display, given the user's selection.
Is there any precedent for this in the sample code? I didn't see any examples in the tutorials of RIBs displaying multiple ViewControllers.
Given the best practices established at Uber, I'm curious about whether it's smart to create more granular RIBs like in the diagram above, or whether it's appropriate sometimes to have multiple ViewControllers per RIB. The answer is likely going to be "RIBs makes no requirement, do what's best for your app"; though I'd still like to hear some thoughts on the matter.
Thanks!
The answer is likely going to be "RIBs makes no requirement, do what's best for your app"; though I'd still like to hear some thoughts on the matter.
You're right. That is the answer :)
Some things to consider are:
Hey @AttwellBrian, thanks a lot for the response.
If each of these screens does highly distinct things, may get complex, may have different owners, may have child RIBs or store intermediate state it may make sense to separate the screens into different RIBs.
That's a good suggestion to apply this rubric. Often I find myself looking at a screen with subcomponents and deciding which components should be broken up into RIBs vs. simply Views; this question can be answered by the question:
Does this component represent a distinct, discrete logic logical substate of the application, and if so, might it spawn children with their own substates?
Another question we find ourselves asking to help answer the question of RIB vs. View is this:
If our designer were to make this look different, like by combining these screens into one, or splitting this screen into many, would that have a big impact on our RIB hierarchy?
We're trying to stay as close to "No, the RIB hierarchy is rather decoupled from how the screens look" as we can. That said, you have great points regarding decoupling, testing, and lazy-performance that support more RIB granularity.
I think it's important to stay focused on the business-logic components, and not let the RIB hierarchy be dictated by what the app looks like. This is oftentimes difficult because you can't _see_ the business logic hierarchy of an application.
Anyway, great work so far on the RIBs framework, documentation, and outreach. I'm super excited to have this tool and to be able to have a much smarter, cleaner, app architecture because of it.
Glad you're finding this useful. I'm curious: what apps are you using this in Jake?
At Life360 (http://engineering.life360.com/), we're building some pretty major upcoming features using RIBs for our iOS and Android apps. We actually had developed our own implementation of RIBs since May which we based on the Uber Mobility talks and your blog post.
Luckily the implementation we've been working with has a lot of similarities with the "official" version here, so the RIB components can interoperate pretty seamlessly. And you guys added a LOT of features that we didn't have, so that's pretty exciting.
Here is some guidance that we landed on:
A good rule of thumb that I use when deciding whether some UI should be a rib are these questions:
“Does this UI ever attach a child to itself, or does it just inform its parent that it was clicked?“
If it attaches children, then creating the Router makes sense.
“Furthermore, does this component consist of several files and components that need to be hooked up together?“
If so, then creating a Builder for it makes sense.
“Finally, does this component talk to the network or database, or have some business logic that needs to be unit tested?“
If so, then creating the Interactor makes sense.
There are several cases I’ve seen in which we create a RIB structure for what is essentially just a small control / button. Typically a button would never attach a child to itself, nor would it have multiple components that need to be attached together, nor would it have lots of built-in business logic. Creating a Router, Interactor, and Builder just for a button may cause challenges in the future, making it more difficult to move this button around or change the UI, because it’s now a whole RIB.
It’s okay for a View to have subviews—especially if these subviews are pretty minimal in that they just report single events back to their Interactor.
Most helpful comment
At Life360 (http://engineering.life360.com/), we're building some pretty major upcoming features using RIBs for our iOS and Android apps. We actually had developed our own implementation of RIBs since May which we based on the Uber Mobility talks and your blog post.
Luckily the implementation we've been working with has a lot of similarities with the "official" version here, so the RIB components can interoperate pretty seamlessly. And you guys added a LOT of features that we didn't have, so that's pretty exciting.