你真的了解重构吗?

今天(3月15日),Martin Fowler 《重构》第二版的中文版正式发布。

前不久,人邮的杨海灵老师找到我,让我帮忙给这本书写推荐语,我毫不犹豫地就答应了,有机会为经典之作写推荐语,实属个人荣幸。

不过,我随即想到,在专栏里,我只是在谈 TDD 的时候提到了重构,并没有把它作为一个专门的话题来讲,于是,我决定给我的专栏读者加餐,专门谈谈重构,毕竟重构是几乎每个程序员都会用到的词汇。

但你真的了解重构吗?

每个程序员都要做的事

作为程序员,我们都希望自己的代码是完美的。

但没有代码是完美的,因为只要你的代码还有生命力,一定会有新的需求进来,而新的需求常常是你在编写这段代码之初始料未及的。

很多人直觉的选择是,顺着既有的代码结构继续写下去,这里添一个 if,那里加一个标记位,长此以往,代码便随时间腐坏了。

如果用一个物理学术语描述这种现象,那就是“熵增”,这也就是大名鼎鼎的热力学第二定律。

如果没有外部干预,系统会朝着越来越混乱的方向发展。

对抗熵增的一个办法就是引入负熵,让系统变得更加有序

而在代码中引入负熵的过程就是“重构”。

调整代码这件事是程序员都会有的习惯,但把这件事做到比较系统,上升为“重构”这个值得推广的实践是从一个小圈子开始的,这个小圈子的核心就是我们在专栏里前面提到过的两位大师级程序员:Ward Cunningham 和 Kent Beck。

而真正让这个概念走出小圈子,来到大众面前的,则是 Martin Fowler 在1999年写下那本软件行业的名著《重构:改善既有代码的设计》(Refactoring: Improving the Design of Existing Code)。

Martin Fowler 的本事就在于他极强的阐述能力,很多名词经过他的定义就会成为行业的流行语(Buzzword),重构就是其中之一。

重构这个说法可比“调整代码”听上去高级多了。

时至今日,很多人都会把重构这个词挂在嘴边:“这个系统太乱了,需要重构一下。”

但遗憾的是,很多程序员对重构的理解是错的。

重构是一种微操作

你理解的重构是什么呢?

就以前面那句话为例:这个系统太乱了,需要重构一下。如果我们接着问,你打算怎么重构呢?一些人就会告诉你,他们打算另立门户,重新实现这套系统。

对不起,你打算做的事叫重写(rewrite),而不是重构(refactoring)。

《重构》是一本畅销书,但以我的了解,很少有人真正读完它,因为 Martin Fowler 是按照两本书(Duplex Book)来写的,这是他常用写书的风格,前半部分是内容讲解,后半部分是手册。

让这本书真正声名鹊起的就是前半部分,这部分写出了重构这件事的意义,而后半部分的重构手册很少有人会看完。很多人以为看了前半部分就懂了重构,所以,在他们看来,重构就是调整代码。调整代码的方法我有很多啊,重写也是其中之一。

如果真的花时间去看这本书的后半部分,你多半会觉得很无聊,因为每个重构手法都是非常细微的,比如,变量改名,提取方法等等。尤其是在今天,这些手法已经成了 IDE 中的菜单。

估计这也是很多人就此把书放下,觉得重构不过如此的原因。

所以,行业里流传着各种关于重构的误解,多半是没有理解这些重构手法的含义。

重构,本质上就是一个“微操作”的实践。如果你不能理解“微操作”的含义,自然是无法理解重构的真正含义,也就不能理解为什么说“大开大合”的重写并不在重构的范畴之内。

我在《大师级程序员的工作秘笈》这篇文章中曾经给你介绍过“微操作”,每一步都很小,小到甚至在很多人眼里它都是微不足道的。

重构,也属于微操作的行列,与我们介绍的任务分解结合起来,你就能很好地理解那些重构手法的含义了:你需要把做的代码调整分解成若干可以单独进行的“重构”小动作,然后,一步一步完成它。

比如,服务类中有一个通用的方法,它并不适合在这个有业务含义的类里面,所以,我们打算把它挪到一个通用的类里面。你会怎么做呢?

大刀阔斧的做法一定是创建一个新的通用类,然后把这个方法复制过去,修复各种编译错误。而重构的手法就会把它做一个分解:

  • 添加一个新的通用类,用以放置这个方法;

  • 在业务类中,添加一个字段,其类型是新添加的通用类;

  • 搬移实例方法,将这个方法移动到新的类里面。

得益于现在的 IDE 能力的增强,最后一步,按下快捷键,它就可以帮我们完成搬移和修改各处调用的工作。

在这个分解出来的步骤里,每一步都可以很快完成,而且,每做完一步都是可以停下来的,这才是微操作真正的含义。

这是大刀阔斧做法做不到的,你修改编译错误的时候,你不知道自己需要修改多少地方,什么时候是一个头。

当然,这是一个很简单的例子,大刀阔斧的改过去也无伤大雅。

但事实上,很多稍有规模的修改,如果不能以重构的方式进行,常常很快就不知道自己改到哪了,这也是很多所谓“重写”项目面临的最大风险,一旦开始,不能停止。

你现在理解了,重构不仅仅是一堆重构手法,更重要的是,你需要有的是“把调整代码的动作分解成一个个重构小动作”的能力

重构地图

下面我准备给你提供一张关于重构的知识地图,帮你了解它与周边诸多知识之间的关系,辅助你更好地理解重构。

学习重构,先要知道重构的定义。

关于这点,Martin Fowler 给出了两个定义,一个名词和一个动词。

重构(名词):对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。

重构(动词):使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。

之所以要了解重构的定义,因为重构的知识地图就是围绕着这个定义展开的。

首先,我们要对软件的内部结构进行调整,第一个要回答的问题是,我们为什么要调整。Martin Fowler 对于这个问题的回答是:代码的坏味道。

代码的坏味道,在我看来,是这本书给行业最重要的启发。很多人常常是无法嗅到代码坏味道的,因此,他们会任由代码腐坏,那种随便添加 if 或标记的做法就是嗅不出坏味道的表现。

我经常给人推荐《重构》这本书,但我也常常会补上一句,如果你实在没有时间,就去看它的第三章《代码的坏味道》。

顺便说一下,对比两版的《重构》,你会发现它们在坏味道的定义上有所差异,在新版的《重构》中,可变数据(Mutable Data)、循环语句(Loops)都定义成了坏味道,如果你不曾关注近些年的编程发展趋势,这样的定义着实会让人为之震惊。

但只要了解了函数式编程的趋势,就不难理解它们的由来了。

换句话说,函数式编程已然成为时代的主流。如果你还不了解,赶紧去了解。

我们接着回到重构的定义上,重构是要不改变软件的可观察行为。我们怎么知道是不是改变了可观察行为,最常见的方式就是测试

关于测试,我在“任务分解”模块已经讲了很多,你现在已经可以更好地理解重构、TDD 这些概念是怎样相互配合一起的了吧!

再来,重构是要提高可理解性,那重构到什么程度算是一个头呢?

当年重构讨论最火热的时候,有人给出了一个答案:重构成模式(Refactoring to Patterns)。

当然,这也是一本书的名字,有兴趣的话,可以找来读一读。

我个人有个猜想,如果这个讨论可以延续到2008年,等到 Robert Martin 的《Clean Code》出版,也许有人会提“重构成 Clean Code”也未可知。所以,无论是设计模式,亦或是 Clean Code,都是推荐你去学习的。

至此,我把重构的周边知识整理了一番,让你在学习重构时,可以做到不仅仅是只见树木,也可看见森林。

当然,重构的具体知识,还是去看 Martin Fowler 的书吧!

总结时刻

总结一下今天的内容。今天我介绍了一个大家耳熟能详的概念:重构。不过,这实在是一个让人误解太多的概念,大家经常认为调整代码就是在做重构。

重构,本质上就是一堆微操作。重构这个实践的核心,就是将调整代码的动作分解成一个一个的小动作,如果不能理解这一点,你就很难理解重构本身的价值。

不过,对于我们专栏的读者而言,因为大家已经学过了“任务分解”模块,理解起这个概念,难度应该降低了很多。

既然重构的核心也是分解,它就需要大量的锤炼。就像之前提到任务分解原则一样,我在重构上也下了很大的功夫做了专门的练习,才能让自己一小步一小步地去做。但一个有追求的软件工匠不就应该这样锤炼自己的基本功吗?

如果今天的内容你只记住一件事,那请记住:锤炼你的重构技能

最后,我想请你分享一下,你对重构的理解。欢迎在留言区写下你的想法。

重新审视“最佳实践”

我承诺的正文内容已经全部交付给你,恭喜你完成了整个专栏的学习!

希望通过对这些内容的学习,你已经对“如何做好软件”有了一个全新的认识。

在这个专栏中,我给你讲了很多行业中的最佳实践,比如:测试、持续集成等等,但因为这个专栏叙述方式的关系,一些有关联的实践被放到了不同的模块下讲解。

所以在这一讲中,我们将按照最佳实践的维度重新审视这些内容。我会将这些知识重新串联起来,帮你做一个对专栏的整体复习。

产品

做产品,很多时候是面向不确定性解决问题。目前这方面最好的实践是“精益创业”。

对于精益创业的最简单的理解就是“试”。

试也有试的方法,精益创业提出了一个“开发(build)- 测量(measure)- 认知(learning)”这样的反馈循环,通过这个循环得到经过验证的认知(Validated Learning)。

既然是对不确定产品特性的尝试,最好的办法就是低成本地试。

在精益创业中,最小可行产品(MVP)就是低成本的试法。最小可行产品,就是“刚刚好”满足用户需求的产品。理解这个说法的关键在于用最小的代价,尝试可行的路径

在产品的打磨过程中,可以采用用户测试的方式,直接观察用户对产品的使用。

作为程序员,我们要尽可能吃自家的狗粮,即便你做的产品不是给自己使用的产品,也可以努力走近用户

精益创业- 相关阅读:《06 精益创业:产品经理不靠谱,你该怎么办?》
最小可行产品(MVP)- 相关阅读:《19 如何用最小的代价做产品?》
用户测试、验证产品特性、吃自家狗粮- 相关阅读:《26 作为程序员,你也应该聆听用户声音 》

需求

当我们确定做一个产品功能时,怎么描述需求也是很重要的。产品列表式的需求描述方式最容易出现问题的地方在于,看不清需求的全貌。

用户故事是一个好的需求描述方式:作为一个什么角色,要做什么样的事,以便达成一种怎样的效果

在用户故事中,验收标准是非常重要的一环。即便不是采用用户故事描述需求,也依然建议先将验收标准定义清楚。

开发团队对需求的理解普遍偏大,基本上都是一个主题。

在开发之前,先将需求拆分成小粒度的。衡量一个用户故事拆分是否恰当,一个标准是 INVEST 原则。有了拆分出来的用户故事,就可以进行估算了,估算的过程也是对需求加深理解的过程,过大的用户故事应该再次拆分。

当我们有了拆分之后的需求,就可以对需求进行优先级讨论了。

先做重要性高的事,而不是一股脑地去做所有的需求。只有分清了需求的优先级,才能方便地对需求进行管理

持续集成

在开发中,写出代码并不是终点,我们要把代码集成起来。

集成要经常做,改动量越小,集成就可以做得越频繁,频繁到每次提交都去集成,这就是持续集成。

持续集成发展到今天已经是一套完整的开发实践。想要做好持续集成,你需要记住持续集成的关键是“快速反馈”。

  • 怎样快速得到反馈。

  • 怎样反馈是有效的。

持续集成,可以继续延展,将生产部署也纳入其中,这就是持续交付。如果持续交付,再向前一步,就可以同产品验证结合起来。

持续交付的关键点,是在不同的环境验证发布包和自动化部署。

不同的环境组成了持续交付的构建流水线,而自动化部署主要是 DevOps 发挥能力的地方。持续交付的发展,让交付物从一个简单的发布包变成了一个拥有完整环境的 Docker 镜像。

持续集成和持续交付可以将诸多的实践贯穿起来:单元测试、软件设计、任务分解、主分支开发、DevOps 等等。

所以,如果一个公司希望做过程改进,持续集成是一个好的出发点。

测试

测试是一个典型的程序员误区,很多程序员误以为测试只是测试人员的事。

理解了软件变更成本,知道了内建质量之后,我们就应该清楚,测试应该体现在全部的开发环节中。这一思想在开发中的体现就是自动化测试。

想要写好自动化测试,需要先理解测试金字塔,不同的测试运行成本不同。为了让软件拥有更多的、覆盖面更广的测试,需要多写单元测试。

编写测试的方式有很多,一种实践是测试驱动开发(TDD)。

先写测试,然后写代码,最后重构,这就是 TDD 的节奏:红——绿——重构。测试驱动开发的本质是测试驱动设计,所以,编写可测试的代码是前提。

要想做好 TDD,一个重要的前提是任务分解,分解到非常小的微操作。学会任务分解,是成为优秀程序员的前提条件。

想写好测试,需要懂得好测试是什么样子的,避免测试的坏味道。好测试有一个衡量标准:A-TRIP。

我们不只要写好单元测试,还要站在应用的角度写测试,这就是验收测试。验收测试现在比较成体系的做法是行为驱动开发(BDD),它让你可以用业务的语言描述测试。

编码与设计

编码和设计,是软件开发中最重要的一环。

在我看来,编码和设计是一体,想清楚才能写出好代码。很多程序员追求写好代码,却没有一个很好的标准去衡量代码的好坏。结合着软件设计的一些理念,我给你一个编写好代码的进步阶梯,希望你能达到用业务语言编写代码的程度。

用业务语言编写代码,需要对软件设计有着良好的理解。提到设计,人们的初步印象是“高内聚低耦合”,但这是一个太过高度抽象的描述。SOLID 原则是一个更具实践性的指导原则,有了原则做指导,就可以更好地理解设计模式了。

有了基础原则,我们会知道将不同的代码划分开,这样就产生了分层。

好的分层可以构建出抽象,而其他人就可以在这个抽象上继续发展。对于程序员来说,构建自己的核心抽象是最关键的一步。

目前构建核心抽象最好的方式是领域驱动设计(DDD),它将我们思考的起点拉到了业务层面,通过战略设计将系统按照不同的上下文划分开来,再通过战术设计,指导我们有效地设计一个个的领域模型。

但无论怎样做设计,前提是使用适当的技术解决适当的问题,不要把技术用复杂,把团队带入泥潭

项目准备

从头开始一个项目时,一个好的实践就是把一切都准备好。

迭代0就是这样一个把迭代准备好的实践,从需求到技术,做好充分的准备工作再开启项目,你会显得从容不迫。

在技术方面,迭代0最重要的准备工作就是构建脚本,它是后续很多工作的基础,比如,持续集成。

迭代0,做基础的准备- 相关阅读:《10 迭代0: 启动开发之前,你应该准备什么?》
构建脚本,让项目一开始就自动化- 相关阅读:《30 一个好的项目自动化应该是什么样子的? 》

其余的最佳实践

除了几个花大篇幅介绍的最佳实践,我们还提到了很多不同的最佳实践。

DoD

完成的定义(DoD),是一个确保合作各方理解一致的实践。它是一个清单,由一个个检查项组成,每个检查项都是实际可检查的。

有了 DoD,做事就只有两种状态:完成和未完成。

完成的定义,DOD- 相关阅读:《03 DoD价值:你完成了工作,为什么他们还不满意?》

站会

站会,一种轻量级的会议形式,用来同步每天发生的事情。一般来说,只说三件事:昨天做了什么,今天打算做什么,遇到了什么问题。

站会- 相关阅读:《22 轻量级沟通:你总是在开会吗? 》

看板

看板,一种项目管理工具, 将正在进行的工作可视化。通过看板,可以发现团队正在进行工作的很多问题。看板有实体和电子之分,可以根据自己的项目特点进行选择。

看板- 相关阅读:《23 可视化:一种更为直观的沟通方式 》

回顾会议

回顾会议,是一种复盘实践,让团队成员对一个周期内发生的事情进行回顾。回顾会议一般分为讲事实、找重点和制定行动项三个部分。

但在开始回顾之前,会先进行安全检查,确保每个人都能放心大胆地说真话。

回顾会议- 相关阅读:《25 开发中的问题一再出现,应该怎么办? 》
回顾会议中的安全检查- 相关阅读:《答疑解惑 持续集成,一条贯穿诸多实践的主线 》

重构

重构,是程序员的基本功,把调整代码的动作分解成若干可以单独进行的“重构”小动作,一步步完成。

重构的前提是识别代码的坏味道。保证代码行为不变,需要有测试配合,而重构的方向是,重构成模式(Refactoring to Patterns)。重构的过程和编写代码的过程最好结伴而行,最佳实践就是测试驱动开发。

重构- 相关阅读:《加餐 你真的了解重构吗?》
在测试驱动开发中重构- 相关阅读:《13 先写测试,就是测试驱动开发吗?》

分支开发

分支开发模型,是每个团队都要面临的问题。行业中有两种常见的分支模型,一种是基于主干的开发模型,一种是分支开发模型。

分支开发符合直觉,却不是最佳实践。主分支开发模型是与其他实践配合最好的模式,但也需要开发者有着良好的开发习惯。

如果并行开发多个功能,可以考虑 Feature Toggle 和 Branch by Abstraction。

分支开发- 相关阅读:《14 | 大师级程序员的工作秘笈 》

Feature Toggle 和 Branch by Abstraction- 相关阅读:《答疑解惑 如何分解一个你不了解的技术任务? 》

Fail Fast

Fail Fast 是一个重要的编程原则:遇到问题,尽早报错。不要以构建健壮系统为由,兼容很多奇怪的问题,使得 Bug 得以藏身。

Fail Fast- 相关阅读:《27 尽早暴露问题: 为什么被指责的总是你? 》

感谢阅读,如果你觉得这篇文章对你有帮助的话,也欢迎把它分享给你的朋友。

重新来“看书”

豆瓣书单

我们继续复习,在上一讲中,我从最佳实践的角度带领大家回顾了专栏里的一些内容。

这一讲,我们换个复习的角度。在专栏进行的过程中,有一些同学注意到我引用了大量的书籍,提出让我把这些书做一个整理。

Wei 同学提到:

有一个小建议: 在每一个主题模块的小结中,把文章中提到的书籍做一个书单方便读者。

刘晓林 同学提到:

郑老师在专栏中推荐了很多非常好的书籍作为参考,可否考虑在某一期中,将这些参考书籍整理成一个书单,按照专栏的主题做个小分类,然后每本书简单点评两句作为领读内容。希望在专栏的结束语之前可以看到这个书单。

Y024 同学甚至在留言中帮我总结了一个小清单,而有人也在豆瓣上做出了一个豆列,罗列了专栏中提到的一些书。

在今天这一讲中,我就站在“看书”的视角,带着你进行一次复习。这些书大多是在我个人成长过程中,给我留下深刻印象的。

我希望你在结束这个专栏学习之后,开启的是另外一段学习历程,用这些书提升自己的水平,夯实自己的基础知识。

学习了这个专栏之后,你拥有了一个新的知识结构,再来看这些书就会有一种全新的体验。

此外,在这次的内容中,我会提到几本专栏中没有提到的书,算是给你在学习路上的一个补充。

我还制作了一个豆列,方便你去找到这些书。

编码实践

如果你想详细学习如何写好代码,我推荐你去读 Robert Martin 的《代码整洁之道》(Clean Code),这本书几乎覆盖了如何把代码写好的方方面面。

《实现模式》是一本关于如何写好代码的书,更具体一点是,编写别人能够理解的代码。

它的作者 Kent Beck 是许多软件开发实践的开创者。但 Kent Beck 的写作能力一般,他的很多作品被埋没了。只有细细品味,才能体会到 Kent Beck 深厚的功力。

我提升自己编码水平的理解是从《程序设计实践》(The Practice of Programming)这本书开始的,这本书的作者是 Brian Kernighan 和 Rob Pike,这两个人都出身于大名鼎鼎的贝尔实验室,参与过 Unix 的开发。

如果你想从日常开发中提升自己的效率,可以读一下《卓有成效的程序员》。假如你不曾思考过这个问题,这本书会让看到一些不同的工作方式,我也给这本书写过一篇书评。不过,这本书里的技巧太具体了,所以,有一些已经有些过时了。

设计

SOLID 原则是一种面向对象软件设计原则。

早在1995年,Robert Martin 就提出了这些设计原则的雏形,然后在他的《敏捷软件开发:原则、实践与模式》这本书中,比较完整地阐述了这五个原则,后来,他有把这些原则进一步整理,成了今天的 “SOLID”。

有了设计原则做基础,这本书后面讲了设计模式,理解起来就容易多了。虽然书名是关于敏捷的,但这是一本讲设计的书。

设计和架构有什么区别?2017年,Robert Martin 出版了《架构整洁之道》(Clean Architecture),他在其中告诉我们,二者没有区别。所以,这也是一本关于设计的书,给出了 Robert Martin 对设计的最新理解。你可以把它看成《敏捷软件开发:原则、实践与模式》的修订版。

《设计模式》不推荐阅读,它是设计模式的开山之作,但它的起点是 Erich Gamma 的博士论文,其写作风格偏向学术,而且中文版翻译得也很一般。这里将它罗列出来只是因为其历史重要性。如果你想学习设计模式,现在有一些更容易入门的书,比如《Head First 设计模式》。

Martin Fowler 的《企业应用架构模式》将软件开发当时常见的解决方案汇集成模式,今天看来很多模式已经习以为常,但当年出场可是技惊四座的。从这本书的名字你不难看出,它出版的年代是企业级开发盛行的年代。Martin Fowler 一直认为这本书没有写完,希望能够继续更新,但不知道何时能看到这本书的新版。

《Unix 编程艺术》也是一本讲软件设计的书,只不过,它选择的切入点是 Unix 中的设计,从中你可以学到“只做一件事,把它做好”、“文本化”等编程理念,有助于你改善日常的工作。

这样的书,也就只有 Eric Raymond 这样沉浸编程几十年的人才能写出来。

工程实践

Kent Beck 有一本知名的软件工程之作《解析极限编程》(Extreme Programming Explained),它介绍了一种软件开发方法:极限编程。

但更重要的是,今天很多主流的软件开发最佳实践都是从这里出来的。这本书可以理解成诸多最佳工程实践的总纲。

Martin Fowler 在1999年写下软件行业的名著《重构:改善既有代码的设计》(Refactoring: Improving the Design of Existing Code),把重构这个小圈子实践带到了大众视野。2018年底,Martin Fowler 时隔近20年后,又写出了《重构》第二版。把他对这些年行业发展的新理解融入到重构实践中。重构应该有个目标,这个目标就是“重构成模式”,而这也是一本专门的书:《重构与模式》(Refactoring to Patterns)。

《测试驱动开发》是 Kent Beck 为世人展示 TDD 做法的一本书。它好的地方需要自己体会,Kent Beck 并没有显式的讲出来,比如:任务分解。

Jez Humble 和 Dave Farley 的《持续交付》(Continuous Delivery)让持续集成再进一步,将生产环境纳入了考量。

乔梁,他是《持续交付》这本书的中文版译者,而且在这本书出版近十年后,他自己写了《持续交付 2.0》,把自己多年来关于持续交付的新理解整理了进去。

说到遗留代码和测试,我推荐一本经典的书:Michael Feathers 的《修改代码的艺术》(Working Effectively with Legacy Code),从它的英文名中,你就不难发现,它就是一本关于遗留代码的书。

如果你打算处理遗留代码,也建议你读读这本书。这本书我也写过书评,你可以了解一下我对它看法。

领域驱动设计

Eric Evans 2003年写了《领域驱动设计》,向行业介绍一下 DDD 这套方法论,立即在行业中引起广泛的关注。

但实话说,Eric 在知识传播上的能力着实一般,这本关于 DDD 的开山之作,其写作质量却难以恭维,想要通过它去学好 DDD,是非常困难的。

所以,在国外的技术社区中,有很多人是通过各种交流讨论逐渐认识到 DDD 的价值所在,而在国内 ,DDD 几乎没怎么掀起波澜。

2013年,在 Eric Evans 出版《领域驱动设计》十年之后,DDD 已经不再是当年吴下阿蒙,有了自己一套比较完整的体系。

Vaughn Vernon 将十年的精华重新整理,写了一本《实现领域驱动设计》,普通技术人员终于有机会看明白 DDD 到底好在哪里了。

所以,你会发现,最近几年,国内的技术社区开始出现了大量关于 DDD 的讨论。

因为《实现领域驱动设计》实在太厚,Vaughn Vernon 又出手写了一本精华本《领域驱动设计精粹》,让人可以快速上手 DDD,这本书也是我向其他人推荐学习 DDD 的首选。

产品与需求

精益创业是 Eric Ries 最早总结出来的。

他在很多地方分享他的理念,不断提炼,最终在2011年写成一本同名的书:《精益创业》。如果说精益创业是理论,《精益创业实战》这本书则给了你一个操作流程。

Mike Cohn 是敏捷理念的一个重要传播者,我们在讲测试金字塔时,提到了他的著作《Scrum敏捷软件开发》(Succeeding with Agile)。

敏捷开发有两大流派:一派是工程实践,另一派是管理实践。如果你对 Scrum 这类管理实践感兴趣,可以读一下这本书。

如果你对用户故事这个话题感兴趣,推荐阅读 Mike Cohn 的两本书《用户故事与敏捷方法》(User Stories Applied)和《敏捷软件开发实践 估算与计划》(Agile Estimating and Planning)。

开发文化

软件行业里有一本名著叫《人月神话》,这算是软件开发领域第一本反思之作。今天,我们讨论的很多词汇都出自这本书,比如,没有银弹、焦油坑等等。虽然这本书出版于1975年,但其中提到的问题,依然困扰着今天的程序员。

开源概念的提出者 Eric Raymond,他的《大教堂与集市》推开了开源大门。

今天开源软件已经成为程序员日常工作的一部分,但如果没有 Eric Raymond 这些人的努力,我们还必须与复杂的企业级软件搏斗。了解一下开源的历程,可以帮助你更好地理解今天的幸福。

程序员应该如何做,Robert Martin 也写了一本书《程序员的职业素养》(Clean Coder),其中对大多数程序员最重要的一点建议是,说“不”。

软件开发拾遗

高德纳的《计算机程序设计艺术》肯定是一套程序员都知道,但没几个人读完的书。

算法的讲解经过几十年已经有了很好的发展,如果学算法,肯定有更好的选择。如果你想看图灵奖获得者如何从根源上思考问题,不妨找来这套书来翻翻。

《快速软件开发》(Rapid Development),不推荐阅读。

在这本书中,作者首次提出了解决集成问题的优秀实践:Daily Build,每日构建。通过这个名字,我们便不难看出它的集成策略,即每天集成一次。其中很多实践在当时是先进的,但今天看来有些落伍了。如果你只想从中收获一些理念性的东西,可以去读读。

《C 程序设计语言》《Unix 编程环境》等出自贝尔实验室大师级程序员之手,他们的书都值得一读,其中的内容今天看来可能有些过时,但他们解决问题的方式和手法却值得慢慢品味。

我在讲淘宝技术变迁时,提到了《淘宝技术这十年》,这本书算不上经典,但可以当作休闲读物。

技术之外

管理大师彼得·德鲁克有一本经典著作《卓有成效的管理者》,虽然标题上带着管理者几个字,但在我看来,这是一本告诉我们如何工作的书,每个人都可以读一下。

尤瓦尔·赫拉利的《人类简史》或《未来简史》,是我第一次学到“大历史观”这个说法,历史不再是一个个单独的历史事件,而是一个有内在逻辑的发展脉络。

《从一到无穷大》是一本著名科普著作,它向我们介绍了20世纪以来的科学进展。作者乔治·伽莫夫既是热宇宙大爆炸模型的提出者,也是生物学上最早提出“遗传密码”模型的人。虽然这本书是1947年出版的,但以现在社会的整体科学素养,还是有必要读读这本书的。

史蒂芬·柯维(Stephen Richards Covey)的《高效能人士的七个习惯》,其中的理念我在专栏两个不同的地方提到过,一个是讲以终为始时,那段关于智力创造的论述,另一个是讲优先级时提到的艾森豪威尔矩阵。这本书值得每个人阅读,很多程序员欠缺的就是这些观念性的东西。

很多程序员都是科幻小说迷,编程和科幻,这两个都是需要想象力的领域。

刘慈欣的《三体》,不说它给 IT 行业带来的丰富的词汇表吧,作为科幻小说来说,它就是一流的,值得阅读。它会让你仰望星空,打开思维。如果你对科幻小说有兴趣,推荐阅读阿西莫夫的《银河帝国》系列,这是科幻小说界的扛鼎之作,你会看到,一部出版于1942年的书里就有大数据的身影。

对于程序员来说,最好的工作状态就是进入心流,它会让你忘我工作。如果你对心流的概念感兴趣,可以去读米哈里·契克森米哈赖的著作《心流》,这位作者就是心流概念的提出者。

好,今天的复习就到这里,你有哪些经典的书可以推荐给这个专栏的同学呢?欢迎在留言区写下分享你的想法。

参考资料

http://learn.lianglianglee.com/%e4%b8%93%e6%a0%8f/10x%e7%a8%8b%e5%ba%8f%e5%91%98%e5%b7%a5%e4%bd%9c%e6%b3%95/%e5%8a%a0%e9%a4%90%20%e4%bd%a0%e7%9c%9f%e7%9a%84%e4%ba%86%e8%a7%a3%e9%87%8d%e6%9e%84%e5%90%97%ef%bc%9f.md