Skip to content

Commit 3a4b918

Browse files
committed
docs: udpate clean-code
1 parent fbca6c1 commit 3a4b918

File tree

1 file changed

+53
-2
lines changed

1 file changed

+53
-2
lines changed

docs/clean-code.md

+53-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
## 第一章 整洁代码
66
1. 勒布朗法则:稍后等于永不(Later equals never.)
77
1. 制造混乱无助于赶上期限。混乱只会立刻拖慢你,叫你错过期限。赶上期限的唯一方法——做的快的唯一方法——就是始终尽可能保持代码整洁。
8-
1. Javadoc 中的 `@author` 字段告诉我们自己是什么人。我们是作者作者都有读者。实际上,作者有责任与读者做良好沟通。下次你写代码的时候,记得自己是作者,要为评判你工作的读者写代码。
8+
1. Javadoc 中的 `@author` 字段告诉我们自己是什么人。我们是作者作者都有读者。实际上,作者有责任与读者做良好沟通。下次你写代码的时候,记得自己是作者,要为评判你工作的读者写代码。
99

1010
## 第二章 有意义的命名
1111
## 第三章 函数
@@ -58,4 +58,55 @@ public class UserValidator {
5858
1. 在很久以前,许多语言都不支持异常。这些语言处理和汇报错误的手段都有限。你要么设置一个错误标识,要么返回给调用者检查的错误码。这类手段的问题在于,它们搞乱了调用者代码。调用者必须在调用之后即可检查错误。不幸的是,这个步骤很容易被遗忘。最好是抛出一个异常,这样其逻辑不会被错误处理搞乱。
5959
1. 使用不可控异常。可控异常 `checked exception` 的代价是违反开闭原则。如果你在方法中抛出可控异常,而 catch 语句在三个层级之上,你就得在 catch 语句和抛出异常处之间的每个方法签名中声明该异常。这意味着对软件中低层级的修改,都将涉及较高层级的签名。最终得到的就是一个从软件最底端贯穿到最高端的修改链。
6060
1. 别返回 null 值。我不想去计算曾经见过多少每行代码都在检查 null 值的应用程序。Java 中有 `Colletions.emptyList()` 方法,该方法返回一个预定义不可变列表,这样编码,就能尽量避免 `NullPointerException` 的出现,代码也就更整洁了。
61-
1. 别传递 null 值。在大多数编程语言中,没有良好的方法能对付由调用者意外传入 null 值。事已如此,恰当的做法就是禁止传入 null 值。
61+
1. 别传递 null 值。在大多数编程语言中,没有良好的方法能对付由调用者意外传入 null 值。事已如此,恰当的做法就是禁止传入 null 值。
62+
63+
## 第八章 边界
64+
1. 第三方代码帮助我们在更少时间内发布更丰富的功能。在利用第三方程序包时,该从何处入手呢?我们没有测试第三方代码的职责,但为要使用的第三方代码编写测试,可能最符合我们的利益。
65+
1. 学习第三方代码很难,整合第三方代码也很难,同时做这两件事难上加难。不要在生产代码中试验新东西,而是编写测试来遍览和理解第三方代码,这叫“学习性测试”。
66+
67+
## 第九章 单元测试
68+
1. TDD 三定律:
69+
- **定律一** 在编写不能通过的单元测试前,不可编写生产代码。
70+
- **定律二** 只可编写刚好无法通过的单元测试,不能编译也算不通过。
71+
- **定律三** 只可编写刚好足以通过当前失败测试的生产代码。
72+
1. TDD 三定律其实说的是,先写失败的 Case,写完之后才开始写功能 Code,只要 Code 通过了 Case,就不要再写功能代码了。也就是说,写完一个测试,就要写对应的生产代码。
73+
1. 测试代码和生产代码一样重要。它可不是二等公民。它需要被思考、被设计和被照料。它该像生产代码一般保持整洁。
74+
1. 如果测试不能保持整洁,你就会失去它们。没有了测试,你就会失去保证生产代码可扩展的一切要素。有了测试,你就不担心对代码的修改!没有测试,每次修改都可能带来缺陷。
75+
1. 覆盖了生产代码的自动化单元测试程序组能尽可能地保持设计和架构的整洁。测试带来了一切好处,因为测试使改动变得可能。
76+
1. 整洁的测试有三个要素:可读性、可读性、可读性。测试应该明确、简洁,还有足够的表达力。在测试中,要以尽量少的文字表达大量的内容。
77+
1. F.I.R.S.T 规则:
78+
- **Fast**(快速) 测试应该能快速运行。测试运行缓慢,你就不会想要频繁地运行它。如果你不频繁运行测试,就不能尽早发现问题,也无法轻易修正。
79+
- **Independent**(独立) 测试应该相互独立。某个测试不应为下一个测试设定条件。你应该可以单独运行每个测试,及以任何顺序运行测试。
80+
- **Repeatable**(可重复) 测试应当可在任何环境中重复通过。
81+
- **Self-Validating** (自足验证) 测试应该有布尔值输出。
82+
- **Timely**(及时) 测试应及时编写。单元测试应该恰好在使其通过的生产代码之前编写。
83+
84+
## 第十章 类
85+
1. 面向对象的其中一个设计原则是“开放——闭合原则”,即类应当对扩展开放,对修改封闭。我们希望将系统打造成在添加或修改特性时尽可能少惹麻烦的架子。在理想系统中,我们通过扩展系统而不是修改现有代码来添加新特性。
86+
1. 类的另一条设计原则是“依赖倒置原则”(Dependency Inversion Principle, DIP),DIP 认为类应该依赖于抽象而不是依赖于具体细节。
87+
88+
## 第十一章 系统
89+
1. 有一种强大的机制可以实现分离构造与使用,那就是依赖注入(Dependency Injection, DI),它是控制反转(Inversion of Control, IoC)在依赖管理中的一种应用手段。控制反转将第二权责从对象中拿出来,转移到另一个专注于此的对象中,从而遵循了**单一权责原则**。在依赖管理情境中,对象不应负责实体化对自身的依赖,而应当将这份权责移交给其它“有权力”的机制,从而实现控制的反转。
90+
1. “一开始就做对系统”纯属神话。反之,我们应该只去实现今天的用户故事,然后重构,明天再扩展系统、实现新的用户故事。这就是迭代和增量敏捷的精髓所在。
91+
92+
## 第十二章 迭进
93+
1. 简单设计的四条规则,按重要程度排序:
94+
- 运行所有测试;
95+
- 不可重复;
96+
- 表达了程序员的意图;
97+
- 尽可能减少类和方法的数量。
98+
1. 全面测试并持续通过所有测试的系统,就是可测试的系统。看似浅显,但却重要。不可测试的系统同样不可验证。不可验证的系统,绝不应该部署。
99+
1. 重复是拥有良好设计系统的大敌,它代表着额外的工作、额外的风险和额外且不必要的复杂度。要想创建整洁的系统,需要有消除重复的意愿。
100+
1. 软件项目的主要成本在于长期维护。代码应当清晰地表达其作者的意图。作者把代码写得越清晰,其他人花在理解代码上的时间也就越少,从而减少缺陷,缩减维护成本。
101+
1. 为了保持类和函数短小,我们可能会造出太多的细小类和方法。所以这条规则也主张函数和类的数量要少。我们的目标是在保持函数和类短小的同时,保持整个系统短小精悍。不过更重要的是测试、消除重复和表达力。
102+
103+
## 第十三章 并发编程
104+
1. 并发是一种解耦策略。它帮助我们把**做什么**(目的)和**何时做**(时机)分解开。解耦目的与时机能明显地改进应用程序的吞吐量和结构。
105+
1. 并发有时能改进性能,但只在多个线程或处理器之间能分享大量等待时间的时候管用,事情没那么简单。
106+
1. 并发算法的设计有可能与单线程系统的设计极不相同。目的与时机的解耦往往对系统结构产生巨大影响。
107+
1. 并发编程中的一些基础定义:
108+
- **限定资源**:并发环境中有着固定尺寸或数量的资源。
109+
- **互斥**:每一时刻仅有一个线程能访问共享数据或共享资源。
110+
- **线程饥饿**:一个或一组线程在很长时间内或永久被禁止。例如,总是让执行得快的线程先运行,加入执行得快得线程没完没了,则执行时间长的线程就会“饥饿”。
111+
- **死锁**:两个或多个线程互相等待执行结束。每个线程都拥有其它线程需要的资源,得不到其它线程拥有的资源,就无法终止。
112+
- **活锁**:执行次序一致的线程,每个都想要起步,但发现其它线程已经“在路上”。由于竞步的原因,线程会持续尝试起步,但在很长时间内却无法如愿,甚至永远无法启动。

0 commit comments

Comments
 (0)