Kotlin 如何在函数式编程中处理私有状态?

Kotlin 如何在函数式编程中处理私有状态?,kotlin,functional-programming,rx-java,state,Kotlin,Functional Programming,Rx Java,State,我的应用程序中有一个特性,它有一些私有状态信息和一些公共状态信息可供共享。如何摆脱可变的私有状态变量?我如何让私人国家进入这个链条 我最近刚刚学习了函数式编程,并希望将此功能转换为更类似于fp的方法 这是我迄今为止的一个简单例子 sealed class PublicState { data class Data(val a:Int, val b:Int):PublicState() object Pending : PublicState() } data class Pri

我的应用程序中有一个特性,它有一些私有状态信息和一些公共状态信息可供共享。如何摆脱可变的私有状态变量?我如何让私人国家进入这个链条

我最近刚刚学习了函数式编程,并希望将此功能转换为更类似于fp的方法

这是我迄今为止的一个简单例子

sealed class PublicState {
    data class Data(val a:Int, val b:Int):PublicState()
    object Pending : PublicState()
}

data class PrivateState(val a:Int, val b:Int, val x:Int)

sealed class Action {
    data class InputC(val c:Int):Action()
    data class InputD(val d:Int):Action()
}

sealed class Update {
    data class A(val a:Int):Update()
    data class B(val b:Int):Update()
    object Working : Update()
}

class Feature {

    val actions = PublishSubject.create<Action>()
    val state = BehaviorSubject.create<PublicState>()

    private var privateState = PrivateState(0,0,1)

    init {
        val startState = privateState.toPublicState()
        actions.flatMap {action ->
            when (action) {
                is Action.InputC -> handleC(action)
                is Action.InputD -> handleD(action)
            }
        }.scan(startState, ::reduce)
            .subscribe(state)
    }

    fun reduce(previousState:PublicState, update: Update):PublicState {

        // can't use previousState because Pending has not all information
        // I don't want to add the information to pending because state is undefined while pending
        return when (update) {

            is Update.A -> privateState.copy(a = update.a).toPublicState()
            is Update.B -> privateState.copy(b = update.b).toPublicState()
            Update.Working -> PublicState.Pending
        }
    }

    fun doAction(action: Action) {
        actions.onNext(action)
    }

    private fun handleC(action:Action.InputC):Observable<Update> {
        return Observable.fromCallable {
            // time consuming work which uses x
            val result = privateState.x + privateState.a + action.c
            Update.A(result) as Update
        }.startWith(Update.Working)
    }

    private fun handleD(action:Action.InputD):Observable<Update> {
        return Observable.fromCallable {
            // time consuming work which uses x
            val result = privateState.x + privateState.b + action.d
            Update.B(result) as Update
        }.startWith(Update.Working)
    }

}

private fun PrivateState.toPublicState(): PublicState {
    return PublicState.Data(a, b)
}
密封类PublicState{
数据类数据(val a:Int,val b:Int):PublicState()
对象挂起:PublicState()
}
数据类PrivateState(val a:Int,val b:Int,val x:Int)
封闭式集体诉讼{
数据类InputC(val c:Int):Action()
数据类InputD(val d:Int):Action()
}
密封类更新{
数据类A(val A:Int):更新()
数据类B(val B:Int):更新()
对象工作:更新()
}
类特征{
val actions=PublishSubject.create()
val state=BehaviorSubject.create()
private var privateState=privateState(0,0,1)
初始化{
val startState=privateState.toPublicState()
actions.flatMap{action->
何时(行动){
is Action.InputC->handleC(操作)
是否已处理Action.InputD->Action(操作)
}
}.scan(开始状态::减少)
.订阅(州)
}
乐趣减少(先前状态:PublicState,更新:update):PublicState{
//无法使用previousState,因为挂起未包含所有信息
//我不想将信息添加到挂起,因为挂起时状态未定义
更新时返回{
是Update.A->privateState.copy(A=Update.A).toPublicState()
是Update.B->privateState.copy(B=Update.B).toPublicState()
Update.Working->PublicState.Pending
}
}
乐趣行动(行动:行动){
actions.onNext(action)
}
私人娱乐手册(action:action.InputC):可观察{
返回Observable.fromCallable{
//使用x的耗时工作
val结果=privateState.x+privateState.a+action.c
Update.A(结果)作为更新
}.startWith(Update.Working)
}
处理的私人乐趣(操作:action.InputD):可观察{
返回Observable.fromCallable{
//使用x的耗时工作
val结果=privateState.x+privateState.b+action.d
将.B(结果)更新为更新
}.startWith(Update.Working)
}
}
private fun PrivateState.toPublicState():PublicState{
返回PublicState.Data(a,b)
}
实际上,状态变量比a、b和x多得多。但是如果我想让它们在链中,我有一个巨大的状态变量,所有这些都会暴露出来。使用可变变量感觉更容易。 你对如何解决这个问题有什么建议吗?如果你认为这是一个错误的方法,我也对其他模式持开放态度。
我的目标是保留一些私有状态,只公开公共状态。

FP不处理私有状态。你为什么要关心保密?因为来自外部世界的其他人可能会有意或无意地对其进行变异,使整个物体年久失修,对吗?但FP中没有突变。所以你很安全


因此,你的问题归结为“如何处理状态”。好的,如果您想让我回答,请告诉我。

我想您是在尝试模型视图意图模式?在您的示例中(使用rx扫描功能),您应该使用
previousState
并返回一个新的不可变状态,作为渐进步骤,而不是总是在
中使用
privateState
::reduce
。这就是
scan
操作符对该用例的吸引力(将在
可观察的
中存储最后发出的项目)。在我看来,MVI模式有一些在示例中没有提到的主要缺陷——只有一个视图入口点会导致状态和事件的混合,对我来说,这两者可能是相互排斥的。私有状态与函数式编程并不真正兼容。如果您使用不可变的数据结构和导出镜头进行访问,则私有状态可以解决您实际上没有的问题。但话说回来,如果这个特定的代码正常工作,为什么您觉得有必要修改它?@MarkKeen是的,这是对MVI模式的修改。如果在
中使用
previousState
::reduce
我无法访问处于
挂起状态的状态。你有MVI中主要缺陷的例子吗?目前我非常喜欢MVI,但我对其他模式持开放态度,你会推荐哪种模式?@JaredSmith我想尝试不同的模式,我喜欢函数式编程的想法,所以我想尝试一下。我不需要改变它。我只想找到Android平台提供的“我的风格”,它适合MVVM架构——你可以使用任何架构或设计模式,我没有任何MVI的坏例子,但我想说的是任何“模式”如果将自身与库紧密耦合,那么灵活性可能会降低。如果您有一个嵌套的数据结构,那么将其公开会给您的用户一个隐含的契约,即该结构永远不会改变,并创建脆弱的API,这又如何呢?不变性是不够的。镜头的存在是有原因的。@JaredSmith,你当然是对的,但这类问题远远超出了基础。文章作者“最近才了解到FP”,所以我认为深入研究高级内容是没有用的。另一个要考虑的事实是,这个问题正是关于私立国家的,它来自于OOP观点;镜头与心理变化没有什么关系,这是这里的一个关键。@Serejabogolobov我的想法是只暴露这个阶层的消费者正在使用的这些东西。理想情况下,只为每个状态公开所需的信息<代码>挂起
没有其他信息,
数据
中有