Hello Quick question about `molecule` since I see ...
# squarelibraries
p
Hello Quick question about
molecule
since I see the @Composable Presenter pattern being used more and more So there must be a reason / advantage but I'm not seeing it. I understand that it normally helps with synchronizing the evaluation of events/actions and emitting a new state With the device framerate. But why is this needed versus just observing a flow of events/actions and updating an observable state (Basically everything shown as advantages in the documentation, just without @Composable - the need of which is not explained)
A potential advantage is that inside of the @Composable Presenter then you have access to the Activity's context, which can be used to request permissions for example. But this is a big can of worms.
j
If you observe multiple flows in the UI layer you are forced to encode business rules on how those combine at that layer. It is then difficult to test those rules because they require running the whole UI. Combining them at the presentation layer means you get a single flow of models out that is easier to test.
1
It also means you can use it to target non-Compose UI toolkits, such as Android views, HTML DOM, UIKit, etc.
I think we cover all this in the readme...
Unfortunately, we are mixing business logic with display logic which makes testing harder than if it were separated. The display layer is also interacting directly with the storage layer which creates undesirable coupling. Additionally, if we want to power a different display with the same logic (potentially on another platform) we cannot.
Maybe it's not emphasied enough?
p
Thanks for the quick response! I agree with the advantages of moving that evaluation/logic to the Presenter But I still don't see why the Presenter has to be a @Composable.
j
It doesn't. You can use whatever you want.
👍 1
We built our presenters with RxJava and it scaled so poorly
Also in the readme > In Cash App our presenter objects traditionally expose a single stream of display models through Kotlin coroutine's Flow or RxJava Observable. > This code is okay, but the ceremony of combining reactive streams will scale non-linearly. This means the more sources of data which are used and the more complex the logic the harder to understand the reactive code becomes. > Despite emitting the Loading state synchronously, Compose UI requires an initial value be specified for all Flow or Observable usage. This is a layering violation as the view layer is not in the position to dictate a reasonable default since the presenter layer controls the model object.
👍 2
💯 1
We have since migrated all of them away from RxJava and Flow. We're now Compose-only at the presentation layer. Our view layer is like 80% views still. Someday we'll get to 100% Compose UI, but since it's an entirely different layer we don't need to couple that migration with the presenter migration.
K 1
🚀 1
p
Thanks! Really nice that you've transformed that need to decouple (and simplify) all logic from the UI and got clearer/cleaner logic in the presenters + the ability to fully test it! Documentation is great in showing how to organise the event/data flow Is just that it also shows an
@Composable Presenter
without saying that you don't need it on Android and then (because of this?) this pattern gets presented in tutorials targeted to Android (like https://medium.com/@ruby.lich/molecule-build-powerful-stateflows-with-jetpack-compose-fe0e40c2c740 or https://apiumhub.com/tech-blog-barcelona/from-viewmodel-to-compose/)
Think I'll go bug Zac now about why the Circuit Presenters https://slackhq.github.io/circuit/ are composables 😅
j
It basically the same reasoning. Circuit is strongly influenced by Cash's internal framework but has the advantage of starting from zero users. They get to dictate that everything is Compose UI based, and thus they don't need Molecule because the UI layer and host the presenter layer as a simple function. You only then need Molecule if you want to test your presenter function.
🙇 1
a
I understand the layering issue of the initial value. But why can’t the Presenter class not just expose a state flow instead of a flow?
j
You could, but since StateFlow lacks combination operators you have to do that at the very end, separate from the actual business logic and more as a weird standalone value. In the example in the repo, the Flow actually emits synchronously so such a value would never actually be used.
The Compose programming paradigm means your defaults, if needed, are built up as part of the normal logic on how your data is composed together
a
Awesome, great explanation