Ribs: Use plugin point, how the child ribs communicate with parent rib?

Created on 22 Jul 2020  Β·  4Comments  Β·  Source: uber/RIBs

Without plugin point:

If communication is going up the RIB tree to a parent RIB’s Interactor, then the communication is done via a listener interface since the parent can outlive the child.

In the article Engineering Scalable, Isolated Mobile Features with Plugins at Uber, see the Figure below

image

Figure: Enforced separation between plugin and non-plugin code ensures that the Refinement Steps RIB can no longer reference Airport Door Selection directly and is now forced to handle each child RIB according to an interface returned from the plugin point

Non-plugin frameworks cannot directly reference plugin frameworks, so plugin point frameworks bridge this gap. Additionally, transitive framework dependencies are disabled

Does it means child ribs communicate with parent rib by using plugin point ?

Most helpful comment

With RIBs you have two mechanisms of communication:

  • Listener (mainly Child β†’ Parent) β€” this is similar to the delegate you should be familiar with; whichever system wants to use a RIB, it must implement the Listener protocol.
  • Stream (mainly Parent β†’ Children) β€” since the specifics of children, and more importantly, _subtrees_ are concealed from the parent, except for the Listener and (in case of a VC-less RIB) ViewControllable, the parent must not treat its children as direct subjects (they don't work for you, don't try to manipulate them directly). For example, assume any child can become more complex and turn into a subtree with many layers.
    To make a RIB, no matter how deep into the tree do something we use a _Stream_. In RIBs idiom, Stream is a RxSwift Observable wrapped by a protocol implementation (wrapping is important, for example you might choose to use Combine instead of RxSwift, which is slightly less easy, but won't change your RIBs dependencies). You pass values (messages) to the Stream and whichever RIBs subscribe to receive those values can decide what they want to do with them. As any parent would tell you:

Your children don't listen.

Why is this important for PluginPoint?

Plugins are a way to have many children, without being overwhelmed by them. In more technical terms, PluginPoint narrows down the available Listener / Dependency API. All Plugin RIBs have to deal with a single Listener interface, but the Parent RIB only has to implement a few methods; and all Plugins _should_ share the same dependency (usually that's how you can tell that something is a plugin, when it has things in common with a bunch of other components). Lastly, the PluginPoint is an additional barrier, which enforces the principle of "your children don't listen". In case of PluginPoint parent doesn't even know that Plugin children exist! β€” it only attaches the PluginPoint and implements it's Listener and Dependency protocols. This either means using a few methods on the Listener protocol shared by all Plugins, or as @kovpas has said, using Stream pattern in an inverted fashion, to facilitate communication _around_ the PluginPoint by passing the stream to the plugins themselves.

All 4 comments

It depends on the use case. Sometimes we do use plugin points to attach RIBs of the similar nature, but it's not the case all the time.

Child RIBs communicate to parents usually via Observables.

With RIBs you have two mechanisms of communication:

  • Listener (mainly Child β†’ Parent) β€” this is similar to the delegate you should be familiar with; whichever system wants to use a RIB, it must implement the Listener protocol.
  • Stream (mainly Parent β†’ Children) β€” since the specifics of children, and more importantly, _subtrees_ are concealed from the parent, except for the Listener and (in case of a VC-less RIB) ViewControllable, the parent must not treat its children as direct subjects (they don't work for you, don't try to manipulate them directly). For example, assume any child can become more complex and turn into a subtree with many layers.
    To make a RIB, no matter how deep into the tree do something we use a _Stream_. In RIBs idiom, Stream is a RxSwift Observable wrapped by a protocol implementation (wrapping is important, for example you might choose to use Combine instead of RxSwift, which is slightly less easy, but won't change your RIBs dependencies). You pass values (messages) to the Stream and whichever RIBs subscribe to receive those values can decide what they want to do with them. As any parent would tell you:

Your children don't listen.

Why is this important for PluginPoint?

Plugins are a way to have many children, without being overwhelmed by them. In more technical terms, PluginPoint narrows down the available Listener / Dependency API. All Plugin RIBs have to deal with a single Listener interface, but the Parent RIB only has to implement a few methods; and all Plugins _should_ share the same dependency (usually that's how you can tell that something is a plugin, when it has things in common with a bunch of other components). Lastly, the PluginPoint is an additional barrier, which enforces the principle of "your children don't listen". In case of PluginPoint parent doesn't even know that Plugin children exist! β€” it only attaches the PluginPoint and implements it's Listener and Dependency protocols. This either means using a few methods on the Listener protocol shared by all Plugins, or as @kovpas has said, using Stream pattern in an inverted fashion, to facilitate communication _around_ the PluginPoint by passing the stream to the plugins themselves.

Also, do the tutorials (if you haven't already).

hi guys, where can i find out about the PluginPoint demo? thanks.

Was this page helpful?
0 / 5 - 0 ratings