因为新冠肺炎疫情,很多同学都宅在家中,所以有大把的时间进行学习和充电。作为程序员或工程师的你,想要在代码方面更精进一步的话,应该看哪些书?我们特地邀请 支付宝研究员王益来分享他的书单。顺带说一下,王益是 SQLFlow项目和ElasticDL项目的发起者和负责人,其中机器学习工具SQLFlow在GitHub上短时间内就获得了很多Star数,是一个人气很高的开源项目。
下面我们一起来看看,这位资深程序员最喜欢的编程书籍是什么?
前几天,同事问我如果用平时通勤的时间来充电,应该看什么书。我回忆了一下对我影响最大的三本编程书。
《Structure and Interpretation of Computer Programs》
第一本是《 Structure and Interpertation of Computer Programs》,简称为 SICP,这本书有在线版本:https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book.html 。这是曾经 MIT 计算机系本科生的教材,用 Lisp 的一种极简的方言 Scheme 语言作为初学者编程语言 —— 而不是常用的 Java、Python、C —— 是不是很反智?实际上,这正是这本书的精髓。
大部分程序员如果被问到一个问题:如何把一串整数顺序颠倒过来,大家会考虑用一个数组存储这些整数,用两根指针分别从数组两段向对面扫描,依次交换两根指针指向的整数,直到两根指针相遇。其实类似的问题,这样的解决思路,在美国公司的面试里也经常碰到。它让程序员充分利用内存是 randomly accessible 的特点,来选择高效率的数据结构,设计高效的算法。
SICP 不管效率。SICP 不管效率。Scheme 语言本身也不提供数组(有些 packages 提供),只有 list(链表)。用链表存储的一串数字如何倒序?其实也有效率很高的解法 —— 比如可以递归。递归是一种程序的写法,一种表达方式 —— SICP 训练的是大家如何表达 —— 这更像语文课,而不是编程课。可是换一个角度思考,编程不就是用编程语言表达的一种语文吗!
SICP 通篇介绍两种表达的艺术—— 抽象(abstraction)和构造(composition)。定义一个递归函数是一种抽象,递归过程解构(decompose)链表,回溯过程重构链表(compose)—— 这是设计大型软件的核心思维方式。MIT 本科课程中,在用 SICP 启蒙之后,还是要学习数据结构和算法的。只是这个顺序 —— 先识大体,再纠缠细节 —— 很重要。
SICP 是我读博士的时候,我的同学王垠推荐我看的。其实至今没有通篇读下来。但是读了的部分,已经在我的职业生涯里给了我很大的帮助。我记得第一次读的时候我感叹“为什么我不是由这本书启蒙的!”
《The Art of Unix Programming》
第二本书是 《The Art of Unix Programming》,也有在线版本:http://www.catb.org/~esr/writings/taoup/html/。Unix 有很多设计的智慧。其中我印象最深刻松耦合(loss coupling)—— 是 SICP 中强调的抽象(abstraction)和构造(composition)的具体做法 —— (de)compose 时 components 之间的耦合要送,abstraction是要保证界面(interface)窄(简洁)。
Windows 用户用 Word 的时候,可以在文档里嵌入 Excel 点子表格,用的 OLE、COM 这类插件技术。如果 Excel 的 COM 组件有 bug,运行的时候出错,那么 Word 也会 crash。这是一个紧耦合导致系统稳定性下降的例子。人非圣贤,总会写bug,系统设计要限制 bug 导致的糟糕结果的扩散。
在 Unix 的世界里,每个程序都只专注做一件很小很具体的事情,比如 ls、sed、awk;同时提供很多机制(shell、shell script、pipes、environment variables),把这些程序组织起来 —— 组织方式灵活又宽松。用这些简单的基础单元,大家很容易组合(compose)出很复杂的系统。
我在做 code review 的时候,经常看到的一个问题是一大段程序同时解决好几件事情。或者发一个修改了很多文件的修改(pull request),修复好几个问题。其实都是属于没有认真解构(decompose)得到基本单元,然后以松耦合的方式组合(compose)的例子。
《Paul Graham's Essays》
Paul Graham 是硅谷著名的工程师、创业者、和投资人,创办了 Y Combinator —— 是的,就是陆奇老师加入,并且在中国独立融资和运营的那个。在他的主页上有一系列著名的文章:http://www.paulgraham.com/articles.html,其中最有名的可能是 Hackers and Painters(黑客和画家)。其实这些文章解答了大部分程序员常问的问题,每一篇都值得认真阅读和思考,甚至和同事朋友们讨论。
比如,创业公司应该雇佣 Java 程序员(因为人多,所以容易找到员工)还是Go 程序员(小众,人少)?Paul 写这些文章的时候,Go 还没有被发明出来。不过在多篇文章里,他提到他用 Lisp 语言创业获得第一桶金的经历 —— 创业公司不可能靠大众水平反超巨头,要找高手出奇制胜,应该用小众语言、人才、技术和商业模式。
这也间接解释了为什么 MIT 一度用 Scheme 语言和 SICP 来启蒙程序员 —— 因为能考上 MIT 的都是高手,要训练他们掌握 abstraction 和 composition 这样思考能力,从而能设计和组织一般人主持不了的大规模系统的研发。
再比如很多人问编程语言重要吗?我甚至听过一种论调:所有语言都是实现的图灵机的能力,都一样。那为什么大家不用汇编写程序呢?也有人改称:高级语言都是提供顺序执行、选择分支、循环、函数调用这些控制结构(control flows),没有区别。可是 Lisp 还有 coroutine、Go 还有 goroutine 哦。而正是 coroutine 和 goroutine 使得这两种语言在开发后台应用的时候,可以用比 C++ 和 Java 少的多的代码,高效率地描述复杂的逻辑。在 https://zhuanlan.zhihu.com/p/48181202 这里,我转述了 Paul 的观点。
2月19日—2月26日 ,蚂蚁金服将开展“共战‘疫情‘,技术破局”数字课堂线上直播。想要了解更多蚂蚁金服技术,欢迎扫描下方二维码,进入直播间观看。