Nubank 收购 Clojure 语言背后的公司 Cognitect 时发表的一篇文章引用了《走出焦油坑》这篇论文,看完还是有点收获的,记录点笔记。

程序的复杂度在于 state 和 control,control指命令式的分支、循环,一步步执行代码。OOP 在这两方面都很差,封装和修改导致状态难以跟踪,Functional Programming 因强调 immutability 减少了 state 方面的复杂度,Logical Programming 因强调做什么(logic)而非怎么做(control)减少了 control 方面的复杂度,由此受启发,应对复杂度有两条路:

  • avoid,避免不必要的复杂度

  • separate,避不开的话就分而治之,策略与机制分离,逻辑与控制分离,模块切分都是 separate 的体现

根据这个思路,程序可以分成四块:

  • essential state,必不可少的状态

  • essential logic,必不可少的业务逻辑

  • accidental state/control,中间状态以及具体的优化、执行细节

  • other,与外界的交互

作者提出 FRP 编程风格:functional relational programming(不是前端届说的 functional reactive programming),FP 改善 state, relation 重视 essential state 和 essential logic(参考 SQL),这里 relation 指平铺的 tuple,不嵌套,没有 ORM 里 object 的 has 关系。 通俗的说,Spark dataframe / SparkSQL 就是 FRP 风格:对着 tuple 一遍遍应用 projection, filter, join 等,操作中支持 UDF,UDF 本身是纯函数,尤其在 SparkSQL 里,表达逻辑的 SQL 语言和实现 control 的 Java 以及 SQL hint 结合,兼顾了代码实现的简单和性能,性能优化属于 accidental logic,中间过程产生的 tuple 是 accidental state,对于 state 没有 OOP 封装,就是简单的 tuple / struct / case class。

这篇论文还强调 SQL 虽然起源于 relational model,但两者并不等价,在 Cod90 Serious flaws in SQL 中历数了 SQL 的三大缺陷。关系模型的鼻祖 Edgar Frank Codd 在其著作 《The relational model for database management: version 2》中还提到关系数据库应该实现四值逻辑:True, False, Applicable Maybe, Inapplicable Maybe,现实中的 RDBMS 实际上连三值逻辑 True/False/Maybe 都没实现好,而且用 NULL 混着代表 Applicable Maybe 和 Inapplicable Maybe 增加了 SQL 使用的难度。另外 Codd 还批判 Entity-Relationship 模型是不对的,应该只需要考虑 Relation 就行,可怜 ER diagram 概念广泛传播😄