У меня есть хорошее представление о преимуществах использования неизменяемых данных в моих приложениях, и я довольно доволен идеей использования этих неизменяемых структур в простой синхронной среде программирования.
Вот хороший пример где-то в Stack Overflow, который описывает состояние управления игрой, передавая состояние в последовательности рекурсивных вызовов, примерно так:
function update(state) {
sleep(100)
return update({
ticks: state.ticks + 1,
player: player
})
}
Мы можем сделать какую-то произвольную, свободную от побочных действий работу в теле функции, тогда мы возвращаем новое состояние, а не мутируем старый.
Кажется довольно легко перевести это на простую асинхронную модель, например на Javascript.
function update(state) {
const newState = {
player,
ticks: state.ticks + 1
};
setTimeout(update.bind(this, newState), 100);
}
Однако, как только у нас будет больше источников асинхронных событий, кажется, что намного сложнее сохранить состояние неизменным и функции чистыми.
Если мы добавим событие click в пример, мы получим код, который выглядит следующим образом.
window.addEventListener('click', function() {
// I have no idea what the state is
// because only our update loop knows about it
});
Теперь, очевидно, я не хочу мутировать состояние в этом методе, но мне нужно получить доступ к состоянию, чтобы создать новое состояние, что-то вроде этого.
window.addEventListener('click', function() {
const state = getState();
createState({
player,
clicks: clicks + 1
});
});
Но, похоже, для этого требуется какой-то изменчивый менеджер состояний?
В качестве альтернативы, я полагаю, я мог бы добавить событие click в очередь действий, которые будут обрабатываться в цикле обновления, например:
window.addEventListener('click', function() {
createAction('click', e);
});
function update(state, actions) {
const newState = {
player,
ticks: state.ticks + 1,
clicks: state.clicks + actions.clicks.length
};
setTimeout(update.bind(this, newState, []), 100);
}
Опять же, это не особенно функционально и полагается, по крайней мере, на какое-то изменчивое состояние где-то на этом пути. Вероятно, это наивные подходы, исходящие от человека, который в основном работал с изменчивым состоянием и императивным объектно-ориентированным программированием.
Как выглядит дизайн системы, когда есть несколько асинхронных источников событий, и мы хотим, чтобы все было неизменным? Или, по крайней мере, какой хороший шаблон для управления изменчивостью в такой системе?