Как обрабатывать приватное состояние в функциональном программировании? - PullRequest
0 голосов
/ 28 декабря 2018

В моем приложении есть функция, которая имеет некоторую частную информацию о состоянии и некоторую общедоступную информацию.Как я могу избавиться от изменяемой частной переменной состояния?Как получить приватное состояние в цепочку?

Я только недавно узнал о функциональном программировании и хотел преобразовать эту функцию в более 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 голосов
/ 28 декабря 2018

FP не имеет дело с частными государствами.Почему вы заботитесь о сохранении чего-то частного?Потому что кто-то еще, из внешнего мира, мог преднамеренно или нет мутировать этого и привести в негодность весь объект, верно?Но в FP нет мутаций.Так что вы в безопасности.

Таким образом, ваш квестон сводится к «как справиться с состоянием».Ну, дайте мне знать, если вы хотите, чтобы я ответил.

...