React 下,谈谈编程范式

大家经常听到 React 环境下,对 函数式面向对象 等 编程范式 的阐述

但却很少有文章结合 React 特殊语境,对这两个范式进行详细说明,因此,写这篇文章,帮助大家形成 共同语言


首先,编程范式除了实现方式不同以外,其区别的根源在于 ——

关注点不同

  • 函数的关注点在于 —— 变化
  • 面向对象的关注点在于 —— 结构

对于函数,因为结构方便于处理变化,即输入输出是天然关注点,所以 ——

管理状态副作用很重要

为何如此说:

var a = 1
function test(c){
   var b = 2
   a = 2
   var a = 3
   c = 1
   return {a,b,c}
}

这里故意用 var 来声明变量,让大家又更深的体会

在函数中变更函数外的变量 ——

破坏了函数的封装性

这种破坏极其危险,比如上例,如果其他函数修改了 a,在 重新 赋值之前,你知道 a 是多少么?如果函数很长,你如何确定本地变量 a 是否覆盖外部变量?

会有大量意外发生

无封装的函数,不可能有’可装配性‘和’可调试性

所以,使用函数封装逻辑,不能引入任何副作用!注意,这个是强制的,在任何多人协作,多模块多资源的项目中 ——

封装是第一要务,更是基本要求!

所以,你必须将数据(或者说状态)全部包裹在函数内部,不可以在函数内修改任何函数以外的数据!

所以,函数天然存在一个缺点 —— 封装性需要人为保证(即你需要自己要求自己,写出无副作用函数)

当然,还存在很多优点 —— 只需要针对输入输出测试,更加符合物体实际运行情况(变化是哲学基础)

这部分没有加重点符号,是因为它不重要 —— 对一个思想方法提优缺点,只有指导意义,因为思想方法可以综合运用,不受限制

再来看看面相对象,来看看类结构:

class Test{
  a = 1
  b = 2
  c = 3
  constructor(){
    this.changeA()
  }
  changeA(){
    this.a = 2
  }
}

这个结构一眼看去就具有 —— 自解释性自封装性

还有一个涉及应用领域的优势 —— 对观念系统的模拟 —— 这个词不打着重符,不需要太关心,翻译过来就是,可以直译人脑中的观念(动物,人,车等等)

但它也有非常严重的问题 —— 初始化,自解耦麻烦,组合麻烦

需要运用到大量的’构建’,’运行’设计模式!

对的,设计模式的那些名字就是怎么来的

其实,你仔细一想,就能明白为什么会这样 ——

  • 如果你关注变化,想要对真实世界直接模拟,你就需要处理静态数据,需要自己对一个领域进行人为解释
  • 如果你关注结构,想要对人的观念进行模拟,你就需要处理运行时问题,需要自己处理一个运行时对象的生成问题

鱼与熊掌,不可兼得,按住了这头,那头就会翘起来,你按住了那头,这头就会翘起来

想要只通过一个编程范式解决所有问题,就像用手去抓沙子,最后你什么都得不到


极限的函数式,面向对象

通过函数和对象(注意是对象,类是抽象的,观念中的对象)的分析,很容易发现他们的优势

函数 —— 测试简单,模拟真实(效率高)

对象 —— 自封装性,模拟观念(继承多态)

将两者发扬光大,更加极限地使用,你会得到以下衍生范式:

管道/流

既然函数只需要对输入输出进行测试,那么,我将无数函数用函数串联起来,就形成了只有统一输入输出的结构

听不懂?换个说法 ——

只需要 e2e 测试,不需要单元测试!

如果我加上类型校验,就可以构造出 ——

理想无bug系统

这是将函数这一结构推广到极致的产物,也是各个函数式开发语言的主打卖点: