本文是 状态管理框架 选型预研时看到油管上一个Talk的部份内容的总结和一些本身的思考。程序员
要引入一个框架,从上到下的过程包括数据库
状态管理框架 可追根溯源到函数式的本质特性上,因此有必要先搞清楚函数式为什么物。编程
而一个“新”事物的流行每每会产生泡沫,因此也会有人把函数式当成 银弹 ,如同对待 区块链 ,人工智能 和 大数据 同样。在这里但愿一方面把函数式的前因后果说清,另外一方面戳破这些浮夸的 泡沫效应 ,让它回归到原有的价值。swift
函数式的历史能够追述到1930年代的{lambda calculus},函数式编程本质上就是对 λ演算 的一种实现。基本思想就是只经过“变量”和“函数”两个元素来解决问题。这个思想给函数式编程带来诸如 匿名函数 、 一等公民 、 柯里化 等概念。数组
咱们所接触到的主流编程语言几乎都是 图灵机 的思想延续,可见这一分支一直是处于绝对统治地位。但随着现代语言愈来愈多的加入 λ演算 的特性,这两个思想最终产生了交集。安全
那么函数式思想为何从一个小众的事物慢慢变成了显学了呢?那么咱们看一下这个思想到底给软件工程注入了哪些新鲜血液。网络
有一种误解是学习函数式要忘记掉你所学过的编程方式,但与其说引入函数式就是要用它替代 面向对象 ,还不如说是对 面向对象 的程序进行重构,毕竟二者各有优劣。闭包
咱们一开始知足某个业务写的 面向对象 代码多是如下的样子,你能够把他看作一些页面,函数或是模块。并发
随时业务的变化,可能有些组件被删掉,或是新增了新的模块,也多是模块间的调用/依赖关系有了变化。因而复杂度开始增大。app
代码变成这个样子后,虽然表面上仍然可使用,可是源码却已经难以理解和维护 咱们会发现难以理解的一个缘由是:这个系统一件事的成立,须要大量的前提! ++由于依赖太多++
图灵系的语言也有同样的困境,随着语言的迭代更新,逐渐加入了更多的限制:
当一个概念愈来愈难以理解的时候,就到了一个改变的节点上。好比减小概念:Swift就没有protect关键字 why;但更有效的思路是引入更加简单的 函数式 。
数学家,和程序员同样,对概念的 封装 , 组合 有着巨大的需求。 例如英国数学家在一本著做中花了379页推导出1+1=2
他们是怎么管理好这么多封装,最终能串联起来解决问题的呢? 能否把他们的经验拿来借鉴?
答案就是 数学函数
数学函数 是输入集合到输出集合映射。
而函数式语言的函数特性就是 数学函数
这和 面向对象 的函数可不同,咱们通常而言的 函数/方法 ,都是一些statement的集合。也就是说,他能够对外界环境进行改造 (好比网络请求,数据库请求),也能够彻底没有输入和输出,更不用提说什么映射了。
但其实要想借鉴过来也很简单,好比大多现代语言都引入了 闭包 , 一等公民 ,在此基础上只须要给平常所写的函数加一个约束,就能够作到相似数学函数的效果。(加了这些约束的函数被称为 纯函数 ,或 引用透明 )这个约束就是:没有反作用(只能加工参数,输出结果,不能修改外界环境)
若是咱们平时多写纯函数,问题就已经获得了必定的简化。
纯函数 带来的一个好处就是 不可变 immutability ,由于 纯函数 只能处理输入,返回输出,那外界的状态就能够经过拷贝的方式传递进来,不用修改原来的值:
好比对于把x这个集合传入各类各样的函数内,x并不会改变。
这个好处不言而喻,不可变意味着线程安全,意味着没必要由于一些bug去查看每个可能产生的函数。
例如Swift就引入了这个特性,除了 class 都是 值类型 ,传递即拷贝,并经过 copy-on-write 实现按需拷贝,下降空间开销。
纯函数 不是一个褒义词,如同 反作用 不是一个贬义词同样。
有人肯花钱让咱们作程序的缘由就是编写程序经过写一些不纯函数来产生反作用(例如改变数据库里的数据)
用户不关心代码,只关心你能带给他们什么样的 反作用 (其实对于他们就是想要的做用) ,只有程序员才关心这个过程够不够优雅。
问题在于如何处理 反作用 ?
答案是 桥 ,换句话说就是一层封装,把真正要产生的 反作用 藏起来。调用 桥 只能经过一个如何修改该值的函数给它,由这层封装来帮你实现 反作用 。
若是是状态修改,有一种方式是:当有冲突发生的时候,会从新执行须要再次更新的函数。(相似数据库的transaction)
若是是修改外部环境,通常会把请求放到队列里,统一派发。
即便是函数式语言, 反作用 也是要作的,否则这个程序就毫无心义,只是咱们把 反作用 和 纯函数 隔离了起来,让他们的影响在一个可控的范围内。
这种隐藏状态,经过传递函数修改状态的管理 反作用 的方式,就是咱们下面要聊的状态管理思想。
那就是并发!
共享全局状态是维护的噩梦,单纯的乱代码还不足以形成没法理解,能够经过清理最终理清,但若是是并发问题的代码,须要釜底抽薪的改造才可能把各类线程间的协做交接清楚。
即便咱们不引入 状态管理框架 ,仅仅是让数组不可变,用Promise/RxSwift之类把异步的代码梳理好,也至少能让出现问题的线程拿到了不一样版本的数据,因为数据间的隔离就不会有这边遍历那边修改致使的闪退。
若是在应用了Promise/RxSwift以外,引入了 状态管理框架 ,就意味着有了一个方便的途径,能够直接声明一种安全的共享状态,全部的修改都是统一控制的,不只仅不会出错,还可让每次修改都能有序的生效。