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

时间:2018-12-28 10:24:36

标签: 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 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)
}

实际上,状态变量比a,b和x多得多。但是,如果我希望它们出现在链中,则我有一个巨大的State变量,并且所有变量都暴露出来。使用可变变量会更容易。 您对如何解决这个有什么建议吗?如果您认为这是错误的方法,那么我也愿意接受其他模式。 我的目标是保留一些私有状态,仅公开PublicState。

1 个答案:

答案 0 :(得分:0)

FP不处理私有国家。您为什么要关心将某些内容保密?因为来自外部世界的其他人可能有意或无意变异那个那个并使整个物体失修了,对吧?但是FP中没有突变。所以你很安全。

因此,您的问题变成了“如何处理状态”。好吧,让我知道是否要我回答。