函数编程之道

大师和他的徒弟盘坐着进行图灵冥想,沉思Lambda. 徒弟看着大师问:“老师,你能告诉我什么是简单吗?编程是复杂的,框架通过去除选择使得编程入手变得简单,那么类和框架哪个更好呢?”

大师看着徒弟问:“你读过智者大师Carmack微博吗?有时,优雅的实现只需要一个函数,不是一个方法,也不是一个类,不是一个框架,只是一个函数即可。”

“但是,老师”学生开始要发问,但是老师打断它,问:“难道表示not functional(非函数性、非功能性)的词语不是dysfunction(功能性障碍、不举)的意思吗?”

徒弟忽然明白了。

1. 不变性:真正的不变是变化,可变性隐藏了变化,隐藏了变化就会带来混乱,智者会积极拥抱历史。
如果你有一块钱,我再给你一块钱,这并不能改变之前你仅有一块钱的情况,现在你有了两块钱,而可变性试图抹掉历史,但是历史又不能真正被删除,当过去事实无法追溯,它就如同鬼魂缠绕你,表现为程序中的Bug。


2.分离:逻辑是思想,效果是行动,智者总是在行动前思考,只有当思考完成后才行动。
如果你试图同时执行动作和逻辑,你会制造副作用,它会引起你逻辑中的bug,保持函数最小化,一次只做一件事,做好它即可。


3.组合:自然的一切都是和谐的,一棵树没有水不能生长,一只鸟而没有空气不能飞翔,智者总是通过配料把汤的味道做得更好。
为组合进行计划,自然地将函数输出作为其他函数的输入,保持函数签名尽可能简单。

4.保护:时间是宝贵的,努力会花费时间,智者总是尽可能重用它们的工具,愚者子女故事为每次新情况创造特殊工具。
类型特定的函数不能被不同类型的数据重用,智者会让函数处理许多数据类型,或者包装起数据,让其看上去和函数预期的一样,列表List和其中条目item是最伟大的通用抽象。


5.流水不腐:死水无法饮用,食品丢在一边会腐烂,智者总是让事情流动起来。
基于时间的列表集合是一个流。共享对象和数据固定会使得函数彼此相互干扰,同一个资源的线程竞争能够绊倒对方死锁,只有当数据通过纯函数自由地流动起来,程序才是有条理,可预期的。

6.智慧:智者迈出第一步之前首先找到路,智者是函数思维,而不智者会在丛林中迷失方向。


The Dao of Immutability — JavaScript Scene — Mediu

[该贴被banq于2015-04-10 14:14修改过]

我觉得列的几条都很好,但是和函数式编程没有任何实质关系,任何方式,比如古老的面向过程,前些年的面向对象,都应该努力做到这几条,做不到的,是架构师偷懒,设计师能力不足的表现。

复杂度的问题,我更赞成的是“系统复杂,实现复杂;系统简单,实现简单”,复杂系统设计和实现非常简单,是不切实际的幻想;简单系统,做的无比复杂,设计师难辞其咎。

真正的复杂度降低,应该是靠系统分解来做到的,完整系统切分为一系列相互依赖和通信的子系统组成,合理切分,合理定义依赖和通信是关键;子系统如果还复杂,要切分为模块,模块间一样存在依赖和通信,也需要合理定义;如果模块还是非常复杂,要定义其中的子模块,再往后,定义其中的程序单元(例如包、类、函数等等)。

说整个系统是复杂的,这个是常见的现象,甚至说,一个子系统复杂,也很正常,但是你要是经过多次切分,到了一个程序单元那里,还复杂无比,那说明架构师不称职。

就像做一把椅子,设计师定义好椅子面、腿、靠背的样式、尺寸以及它们相互对接的部分的明确要求,每个部分实现都不复杂,每个部分只要按照架构师给它的“部件需求规格说明”来设计自己的部分即可。而且,架构师也不用管部件的设计细节,定义先用锯子还是先用刨子。在一个“椅子产品”的设计和实现中,架构师和部件设计实现者各司其职就可以了。

实际的软件系统当然比作一把椅子复杂得多,但是这个例子中的方法,是解决复杂度问题的正道。没有工具能够解决你特定业务的的复杂度,因此,应该把一个称职的、优秀的架构师,作为系统设计和开发的核心,这样,才能做到《道德经》说说“挫其锐,解其纷”,做出好的产品。

代码中的变量是立体空间图形,调用、赋值等是运动,问题大都出在我们如何良好的管理这些空间和空间的运动。程序世界中有管线、有管道,有流体……,代码文件中的代码对应的世界跟现实世界是完全一样的。程序员的编程工作就是搬弄一些砖砖瓦瓦、瓶瓶罐罐、管管道道、土土木木、花花草草,筑路架桥、开山凿洞、凿渠引水……

但是我们的计算机比自然计算机中的模型更抽象,更高效,去除了可以去除的干扰,得到一个理想的数学模型。如果我们的计算机计算球拍击球后球的落地点的话,它是根据动量守恒和抛物线自由落体计算的,当球拍击球的当时甚至击之前我们就能计算或预测球的落点。可是自然计算机不这样,它无法排除任何信息,球拍击球的时候球和球拍凹陷,撞击发生了震动,震动波在空气中传播,球飞了出去,球飞行中遇到的每一个空气份子,每一个微小颗粒,甚至重力在1毫米距离的差异……这些东西那个自然计算机都没有办法绕开。

当一些人还在努力制造着一系列积木,其中的积木还不一定做得出来的时候,我们就直接用语言表达出来了,就像我们这样,对,就像现在。要判断是否说错了,读一下就知道了,要改变逻辑意思,有比改变我们现在对话更简单的吗?绕一个大圈,用积木把自己想说的话表达出来,程序员啊,你们还累不累?

语言的判断难道不是逻辑体系的判断吗?当谈论逻辑以外的东西的时候,那不过是语言以外的东西罢了。