介绍

这是一本非常厉害的书,里面有太多的智慧,值得每一位程序员阅读。

第一版是二十年前出版的,第二版英文版也是今年刚出版的。在读第二版时发现内容变得与时俱进了,里面居然有 Rust、webpack 之类的东西。

二十年的时间过去了,很多东西都变了,但也有很多东西没变。从这本书里也可以看到,以前有用的理论大部分依然有效;但另一部分东西也发生了变化。

笔记

摘录了原文中我觉得非常重要的观点,同时增加了部分个人点评。

第1章 务实的哲学

1 人生是你的

提示3:你有权选择

这是本书最重要的提示。你的工作环境很糟糕?你的工作很无聊?尝试纠正它。不过,不要一直试下去。正如 Martin Fowler 说的,“你可以去改变组织,或是让自己换一个组织。”

点评:你应该对自己负责,因为这是你自己的事情。

3 软件的熵

提示5:不要放任破窗

点评:如果不去清理这些问题,问题永远不会得到修复,会永远地呆在那儿。

7 交流!

提示11:英语就是另一门编程语言

将英语视作一门编程语言。写文档和编程一样要遵循 DRY 原则、ETC、自动化等。

点评:GitHub 在刚开始时是支持多语言的,后来改为只使用英语。这一点对中国的程序员更为重要,英语已经成为学习进步必须品。

第2章 务实的方法

8 优秀设计的精髓

提示14 优秀的设计比炳糕的设计更容易变更

ETC 原则(Easier To Change),ETC 是一种价值观念,不是一条规则

点评:ETC 引出了后面 DRY、正交性、可逆性等等原则,这些原则的核心都是易于变化。

14 领域特定语言

计算机的语言会影响你怎样思考问题,影响你怎样看待信息的传播。

提示22 靠近问题域编程

点评:可以减少中间转换的损失

内部语言与外部语言

内部语言是正在使用的编程语言,外部语言是除了内部语言外的其他语言。优先使用现在的外部语言,然后尝试内部语言;只有需要向用户开放编写时才考虑外部语言;另外编写领域语言花费的努力不要比节省下来的多。

估算 精确的估算能力可以判别事情的可行性。了解多精确才够,学会使用不同的词语表达精度的范围。

估算的过程;估算项目进度 PERT 乐观的 最有可能的 悲观的 估算

根据当前的进度不断地迭代进度表。

第3章 基础工具

16 纯文本的威力

点评:人类可读且人类可理解 所有工具都可以对纯文本进行处理

17 Shell 游戏

点评:通过学习 Shell,可以理解 Unix 设计理念,做一件事并把它做好。实践时可以将不同的工具组合起来,批量执行操作。

18 加强编辑能力

点评:最好每一个编辑器都可以游刃有余的使用,没有阻塞,思维顺畅。逐步熟悉编辑器,扩展编辑器的能力

19 版本控制

点评:所有内容都应以纯文本的形式存储,利于查看历史

从源码开始,一步步将所有内容都纳入版本控制中,包括不限于文档、构建和发布过程、整理日志的小脚本等等

分支出去,使用分支将内容与其他人隔离

把版本控制视为项目中枢,尽可能地集成托管工具的功能,例如:自动化构建和测试、对分支合并提供良好的支持(Pull Request)、问题管理等等

20 调试

提示29 去解决问题,而不是责备

Bug 是你的错还是别人的错并不重要。无wyx是谁的错,问题仍然要你来面对。

提示30 不要恐慌

人们很容易陷入恐慌,万其是当最后期限逼近,或是在老板或客户站在背后紧张凝视之下,拼命找出问题原因的时候。然而,这时非常重要的是要退后一步冷静思考。

第4章 务实的偏执

提示36 你无法写出完美的软件

软件不可能是完美的。对于在所难免的错误,要保护代码和用户免受其影响。

点评:接受现实,理解这一点可以有助于减少完美而冗余的设计。

23 契约式设计

DBC 与测试驱动开发

DBC 定义出骖数何时成立、何时失败的所有情况,而测试则一次只针对一种特定的情况。

TDD 及其他测试只发生在构建循环中的“测试环节”。但 DBC 和断言永远存在,无论在设计时、开发时、部署时,还是维护时。

26 如何保持资源的平衡

提示40 有始有终

点评:谁申请谁释放,坚持这个原则可以非常容易地解决资源泄露问题,而且也易于查错。

27 不要冲出前灯范围

提示42 小步前进——由始至终

点评:控制问题影响的范围,呆在安全的范围内有利于控制成本。

第5章 宁弯不折

28 解耦

解耦代码让改变更容易

只管命令不要询问 要把工作委托给对象,而不是查询

不要链式调用方法 只有在调用的东西不太可能改变,如语言自己的库时才可以链式调用

避免全局数据 包括单例与全局变量,如果全局唯一非常重要,那么将它包装到 API 中

29 在现实世界中抛球杂耍

事件 包括:有限状态机、观察者模式、发布/订阅、响应式编程与流

事件流是异步集合

这是一个非常强大的抽象方法:我们不再须要将时间视为必须管理的东西。事件流将同步和异步处理统一到一个通用的、方便的 API 之后。

点评:事件流真是一个强大的东西,可以轻松地处理与时间相关的问题。

30 变换式编程

所有程序其实都是对数据的一种变换——将输入转换成输出。

31 继承税

  • 继承就是耦合。
  • 不要付继承税 可以使用 接口与协议、委托、mixin 与特征
  • 尽量使用接口表达多态
  • 用委托提供服务:“有一个”胜过“是一个”

32 配置

  • 基本上,对于任何以后必须要改而又可以表达在代码主体之外的内容,只要事先知道,就要找出来并放入某个配置容器。
  • 配置应该是动态的,应用程序可以在运行时动态地修改配置并生效

第6章 并发

34 共享状态是不正确的状态

共享状态会带来无穷的麻烦,而且往往只有重启才能解决。

第7章 当你编码时

38 巧合式编程

提示62 不要依赖巧合编程

点评:计算机是确定性的机器,因此如果程序的结果是随机的不受控制的,那说明一定哪里出问题了。不要在出问题的时候对其视而不见,这会导致更大的问题。

40 重构

提示65 尽早重构,经常重构

点评:这里推荐阅读《重构2》这本书,里面详细介绍了各种重构方法。

41 为编码测试

  • TDD:你需要知道该去何方
  • 既非自上而下,也不自下而上,基于端对端构建
  • 测试开发有帮助,但是,就像每次驱动汽车一样,除非心里有一个目的地,否则就能会兜圈子。

42 基于特性的测试

可以按照规则生成测试,即可以测试符合规则的一组数据;而单元测试只能测试一个数据

43 出门在外注意安全

  • 安全的默认值,在应用程序或网站用户的设置里,默认值应该是最安全的。
  • 尽早打上安全补丁,包括所有可以联网的设备。

点评:之前遇到过,Redis 默认的密码是空,导致部署在线上的服务器被攻击。

44 事物命名

在很多时候,对于正要去做的事情,一旦我们怎么都想不出一个适梧它的名字,往往就会幡然醒悟,意识到这件事情其实毫无意义。

尊重文化 不同的语言和社区有不同的文化,使用不同的约定

一致性 所有人都应该使用相同的命名,在团队中维护术语表以及结对编程可以帮助统一。

第8章 在项目启动之前

45 需求之坑

通常情况下,它们被埋在层层的假设、误解和政治之下。更糟糕的是,需求通常根本不存在。

  • 提示75 无人确切知道自己想要什么
  • 提示76 程序员帮助人们理解他们想要什么
  • 提示77 需求是从反馈循环中学到的

需求的文档化

需求文档是为计划准备的

提示80 使用项目术语表

为项目的所有特定词泄创建一张术语表,并且在单一源头维护。

点评:这就是 Single Source Of Truth 原则的应用。

48 敏捷的本质

敏捷是一个形容词,它指向你做事情的方式。

第9章 务实的项目

49 务实的团队

提示85 排上日程以待其成

为知识组合安排日程:旧系统的维护、流程的反思与精炼、实验新技术、学习和提升技能

51 务实的入门套件

提示89 版本控制戏驱动

使用版本控制来驱动构建、测试和发布

提示90 尽早测试,经常测试,自动测试

提示93 测试状态覆盖率,而非代码覆盖率 即使你碰巧命中了代码的每一行,也不代表全部。重要的是程序可能具有的状态数。状态和代码行并不等价。

提示95 不要使用手动程序

一切都要依赖于自动化。一旦你引入了手动步骤(“就只有这一部分……”),就打破了一扇非常大的窗户。

52 取悦用户

提示96 取悦用户,而不要只是交付代码

用户真正要的不是代码,他们只是遇到某个业务问题,需要在目标和预算范围内解决。他们的信念是,通过与你的团队合作,能够做到这一点。 这真是最重要的一点,大部分人做的东西根本不考虑这点。

提示97 在作品上签名

你的签名应该被认为是质量的标志。

点评:签名能让你为质量负责,因为后来者会看到你的签名、会去评价。

吐槽

书中脚注提到了外部的引用地址,但是找遍了图书的中文与英文网站也没找到链接列表。

链接