Redux 编程思想

导论

什么是 Redux

Redux 是 Flux 的一个变种, 是一种非常流行的单向数据流管理框架. 在 Flux 的基础上, Redux 将数据流进行统一的管理, 让数据流的变化, 变得可预测, 这也是 Redux 名字的由来.

我眼中的 Redux

Flux 早期的官方实现中, 并没有 Reducer 的概念, Store 是一种服务的聚合体, 包括一些数据和操作, 而 Redux 中的 Store 已经是另一种概念了, 如果说 Flux 的早期实现是一个 OOP 的版本, 那 Redux 其实算是 Flux 的 FP 实现, 所以当我们将 OOP 的各种设计工具应用到基于 Redux 构建的应用中去时, 你会发现如此的格格不入, 一切都是离散的, 一个对象被变成了三部分, Action, Reducer, Store 中的一部分, 由于 OOP 在软件开发领域的巨大影响, 为了能够融入 OOP 社区做出了很多努力和尝试, 其中典型的代表是基于 Duck-Module 的流派, 如阿里的 dva 等, 另外一些则属于原生派, 通过各种 Util 来减少 Redux 的样板代码. 不过本文不讨论这些实现, 本文将讨论的是如何在 Redux 上实现这两种风格的前端应用架构

基于 Redux 的 OOP 前端应用架构

OOP 的核心概念是类和对象, 我们开发类来封装数据和操作, 提供对象来输出它们, 通过组合和继承来描述复杂的对象体系. 用各种工具来确保操作的边界, 让对象高内聚, 同时隔离彼此之间的风险.

所以如果没有对象, 一切就都是徒劳的.

而 Redux 是基于 FP 的, 就像两种不同的世界观, 无论怎么拧巴, Reducer 也不可能成为 OOP 里的一员, Action 只是消息的传递者, 在 OOP 里我们通过给对象发送消息来实现方法的调用, 从这个角度看, Bind 了 Dispatch 的 ActionCreator 看起来更像是一个方法, 但是数据又都在 Store 里, 但仔细思考下, 结合以上这几点, 我们大致上应该能理出一条通向 OOP 的道路

  • 隐藏 Reducer
  • 隐藏 Dispatch, ActionCreator 默认绑定 Dispatch
  • 将对象挂载到 Store 上, 隐藏 getState() API

有了思路, 那就开始搞吧

搞吧....其实本文只讨论编程思想, 所以如何实现, 就得另起一篇了:-D

基于 Redux 的 FP 前端应用架构

讨论完了 OOP, 然我们来看看 FP, FP 的核心不用说自然是函数了, 一切皆函数, 但要开发一个应用, 仅仅光靠函数这一个概念, 我们的工作量未免过于巨大, 因此需要引入一些有效的工具帮助我们, 比如 "管道" 和 "高阶函数", 另外为了保持数据不可变, 我们还需要引入不可变的数据类型系统 "Immutable", 有了这些我们可以尝试开始着手去搭建一个前端应用架构了.

如果说 OOP 是用一堆对象描述世界, 对象彼此通过消息来传递数据, 那在 FP 的角度来看, 世界就像一条条管道, 数据在管道中流动, 管道和管道之间可以并行, 也可以串联, 甚至可以彼此包含. 在对象的世界里, 对象负责存储和处理数据, 数据是动态的, 可变的, 而在管道的世界里, 数据是不可变的, 因为管道不负责存储数据, 如果数据没有任何消费方, 那数据本身就没有意义了. 所以存储数据是不必要的. 因为数据处理本身并不绑定数据, 这也使得数据处理的过程变得非常灵活. 总结下, FP 的前端应用架构基于以下四点

  • 用函数定义操作, 并解决数据并行的问题
  • 用高阶函数来组合函数, 构建复杂的操作
  • 用管道解决数据的串行操作
  • 引入"Immutable" 保证数据不可变

基于这四点, 我们可以尝试对前端应用架构使用 FP 的方式来进行抽象和描述, 比如对于一个包含界面的 Web应用, 从用户输入数据到传递给服务端的过程, 可以想象成一条管道

用户输入 -> UI响应并处理 -> 数据层响应并处理 -> 发送数据的管道响应并处理 -> 数据源响应并处理 -> 持久化
//反过来
用户请求 -> UI响应并处理 -> 数据层响应并处理 -> 发送数据的管道请求并处理 -> 数据源响应并发送

在过去要保证这样的串行操作, 可能存在诸多问题, 比如异步的处理, 所幸 ES7的 async/await 给我们带来了便利, 异步和同步编程模型的统一使得降低了前端架构的复杂性. 整个前端应用架构看上去就像两条流水线, 组合在一起就是一个环, 我叫它"环形架构"或者"流水线架构"

以其中的数据管道为例, 我们可以想象请求数据的引擎就是一个并行节点, 因为对不同的数据源, 请求引擎可能不同, 但是我们会统一成一个概念, 比如 fetch, 在 node 和微信小程序下就是完全不同的, 但是通过概念统一, 我们可以利用高阶函数组合出一个能够并行处理多种数据源的引擎, 利用管道对传递的参数和数据源响应的数据分别处理.

事实上, 前端架构中的很多部分都无法用对象描述, 包括层次, 垂直的和纵向的, 流程图, 状态图, 时序图等等. 但这些东西却可以用数据管道来统一描述, 因为前端架构图都是平面图, 当我们描述前端架构的时候, 都是在同一平面上描述数据是如何流动和处理的, 无论我们如何划分, 数据在某一平面上一定是某一种串行或者并行操作.

当你习惯这种思维模式, 我想你会上瘾, 因为一切都是一个环上的某个操作, 无论多复杂的系统, 都可以被分解成一个简单的操作, 粒度的控制完全取决于你.

然后我们把 Redux 放到这个应用的环中, 你会发现, Redux 代表的并不是整个环, 而是其中的一部分, 更像是一个DB, Store 提供 Dispatch 和 来触发数据的写入, Action.Type 如果用来表示数据类型显然比用来描述操作更合理, 这样 Action 本身就是可枚举的了, 相对应的 Reducer 也变得可枚举了, 然后整个前端应用的架构应该是

UI 数据管道 -> Redux 管道 -> 数据源处理管道 -> 数据源

我们将 UI 上的 local 数据放在 UI 数据管道处理, 同时 Redux 管道负责接管外部数据源的读写, 而数据源处理管道则负责通信中前后的数据处理, 如果应用很庞大, 你可以加入更多的平面, 去切分整个系统, 例如加入数据模型的重组, 比如使用 Reselect 库重组数据模型

UI 数据管道 -> 数据模型重组管道 -> Redux 管道 -> 数据源处理管道 -> 数据源

只要你愿意, 你可以合理的切分更多的平面出来, 当然过多的管道会带来通信和数据校验的成本, 这些都是需要在架构设计中被考虑到的部分.

但当你在你的应用中使用这种架构基于 Redux 去开发, 你的应用应该会非常容易测试和维护, 但是在开发模式上, 采用 TDD 应该会更合适, 因为确保每个管道的可用性, 是将他们拼起来的唯一前提.

某野生前端架构师

写于2017年夏末

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容