Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overload for collectWhileInState with Builder #186

Closed
sockeqwe opened this issue Aug 6, 2021 · 4 comments · Fixed by #519
Closed

Overload for collectWhileInState with Builder #186

sockeqwe opened this issue Aug 6, 2021 · 4 comments · Fixed by #519
Labels
enhancement New feature or request
Milestone

Comments

@sockeqwe
Copy link
Collaborator

sockeqwe commented Aug 6, 2021

Currently we support collectWhileInState with flowBuilder as shown bellow:

 fun <T> collectWhileInState(
        flowBuilder: (Flow<InputState>) -> Flow<T>,  
        handler: InStateObserverHandler<T, InputState, S>
 )

I would like to add an overload with

 fun <T> collectWhileInState(
        flowBuilder: (InputState) -> Flow<T>, // just InputState , not Flow<InputState> as above
        handler: InStateObserverHandler<T, InputState, S>
 )

because I personally have more need for this variation of flowBuilder ( (InputState) -> Flow<T>) compare to the current one (Flow<InputState>) -> Flow<T>.

Obviously, that causes a clash on the JVM because both methods have same signature.

Thus we would need to rename one.

I would propose the following:

  • My assumption is that most people have use case for the version with (InputState) -> Flow<T> . Thus I would keep that one under the collectWhileInState name.
 fun <T> collectWhileInState(
        flowBuilder: (InputState) -> Flow<T>, // just InputState , not Flow<InputState> as above
        handler: InStateObserverHandler<T, InputState, S>
 )
  • I would rename the one with Flow<InputState>) -> Flow<T> to collectWhileInStateWithGenericBuilder():
fun <T> collectWhileInStateWithGenericBuilder(
       flowBuilder: (Flow<InputState>) -> Flow<T>,  
       handler: InStateObserverHandler<T, InputState, S>
)

Any thoughts?

cc @gabrielittner

@sockeqwe sockeqwe added the enhancement New feature or request label Aug 6, 2021
@gabrielittner
Copy link
Member

gabrielittner commented Aug 7, 2021

Couldn't this be a foot gun? You create a Flow based on a value in the state, but if it's in the state it means that the value can change through mutations. Even if you know that the value does not change without you leaving the state first I think it would still be safer to do { stateFlow -> stateFlow.flatMapLatest { inputState -> myFlow(inputState) } } opposed to just { inputState -> myFlow(inputState) }. Or would the flowBuilder in your proposal be called whenever InputState changes and we do the flatMapLatest internally?

@sockeqwe
Copy link
Collaborator Author

sockeqwe commented Aug 8, 2021

Yes, but that is in general also an issue for on<Action> and other friends because the passed (as parameter) state can already be mutated in the meantime. Example:

data class FooState(val value : Int)

inState<FooState> {
   onAction<FooAction> { stateSnapshot, action ->
      delay(2000)
       ... 
      // Some properties like stateSnapshot.value could be outdated because of mutations happened in parallel

   loadItem(stateSnapshot.value)

   ...
}

In that case we need to rely on using MutateState properly or set up inState(condition) properly to cancel if necessary for onAction to give some guarantees

@gabrielittner
Copy link
Member

After I've added the indentity block (#480) I will also tackle this one. The motivation for flowBuilder: (Flow<InputState>) -> Flow<T> was to enable collecting a flow that depends on a value of the state by chaining it through a flatMapLatest. The identity block together with this proposal achieves the same:

inState<Foo> {
    untilIdentityChanged({ it.bar }) {
        collectWhileInState({ createFlow(it.bar) }) { ... }
    }
}

This approach fits better to the descriptive nature of building a state machine and is less dangerous than the approach of transforming a flow. While refactoring some things in preparation of these changes I've also noticed that the (Flow<InputState>) -> Flow<T> introduces additional complexity to the library. The current builder would be deprecated.

One question would be the name since the initial renaming proposal won't work since we've reached 1.x.

@gabrielittner gabrielittner added this to the 1.2 milestone May 30, 2023
@sockeqwe
Copy link
Collaborator Author

sockeqwe commented May 31, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Development

Successfully merging a pull request may close this issue.

2 participants