engineers • Deep nested states (scopes) • Shared vocabulary and common patterns across iOS & Android • Testability & Isolation • Tooling for developer productivity RIBs help with all of these
architecture, but a framework • Business logic drives the app, not the view tree • Strong opinion on hierarchical state communication • Hierarchical DI scoping (with Dagger/Motif)
into an app • This activity provides lifecycle event hooks • Under the hood, UI is manipulated by directly manipulating the root ViewGroup (addView, removeView) • App functionality and features are split into separate hierarchical components called RIBs (with or without UI)
Each RIB can be made up 5 elements (independent, single responsibility) • Router, Interactor and Builder are mandatory • Presenter and View are optional • Viewless RIBs can handle non-UI business logic in hierarchical way
of the UI and set its properties Presenter Optional interface between interactor and view Router Contains routing logic to attach/detach child RIBs and other view components Interactor Contains all business logic (Rx subscriptions, where to store data, state management, what other RIBs should be attached as children, etc.) Builder Instantiates the RIB’s constituent classes and the builders for all of its children. Usually coupled with DI component for dependency management RIB Internals
Responsibility). This includes Rx Subscriptions, complex state management, business logic, when to attach or detach child RIBs, etc. Lifecycle Receives callback for lifecycle events and appropriately handles business logic and invokes router to perform routing tasks accordingly.
so as to keep interactor small Router Abstraction Decouples interactors and child RIBs Testability Abstraction and decoupling makes it easy to test complex interactor logic by simply mocking the router
the builders of all child RIBs Builder & Component DI Component Only part of a RIB that should be aware of DI and satisfy dependencies. Each Builder has a component which builds some dependencies for the RIB and receives remaining dependencies from its parent RIB’s Builder. Seperation Builder adds a separation between the DI mechanism and rest of the RIB architecture - we can reuse the rest of the RIB code with a different DI mechanism by replacing the builder
- stateless class that transforms business models into view-related models. Generally only used for complex views View Contains actual view logic to build and update the UI. These are designed to be as “dumb” as possible, and generally should just display information
can share a single, co-designed architecture along with a shared vocabulary across features that they are building. Shared vocabulary helps in writing common technical documents as well. Minimize global state RIBs encourage encapsulating states with deep hierarchy of well isolated individual RIBs, thus avoiding global state. This minimizes side-effects and unintended consequences. Single responsibility, Testability, Isolation Hierarchical decoupling and isolation improves testability and helps to ensure that classes follow single-responsibility wherever possible.
apps business logic to mirror its UI. For example, the view hierarchy may be shallower than RIB hierarchy to improve performance, or a single RIB may control the appearance of three different views at different places on the screen. Deep scope nested states Having deeply hierarchical RIBs helps to isolate and reason about changes within the required scope, while minimizing changes outside and eliminating side-effects. In practice, scoped dependency management also becomes easier Open-Closed Principle Developers can add new code without affecting existing code - for example, you can add a complex child RIB to a parent RIB with almost no changes to the parent RIB