Skip to content

Commit 51ccf01

Browse files
committed
docs: update clean-code
1 parent 3a4b918 commit 51ccf01

File tree

1 file changed

+42
-5
lines changed

1 file changed

+42
-5
lines changed

docs/clean-code.md

+42-5
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@
33
1. 我们就像一群代码猴子,上蹿下跳,自以为领略了编程的真谛。可惜,当我们抓着几个酸桃子,得意洋洋坐到树枝上,却对自己造成的混乱熟视无睹。那堆“可以运行”的乱麻程序,就在我们的眼皮底下慢慢腐坏。
44

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

10-
## 第二章 有意义的命名
1110
## 第三章 函数
1211
1. 函数的第一规则是要短小。第二条规则是还要更短小...经过漫长的试错,经验告诉我,函数就该小。
1312
1. 函数应该做一件事。做好这件事。只做这一件事。判断函数是否不止做了一件事,有一个方法,就是看是否能再拆出一个函数,该函数不仅只是单纯地重新诠释其实现。
1413
1. 要确保函数只做一件事,函数中的语句都要在同一抽象层级上。函数中混杂不同的抽象层级,往往让人迷惑。读者可能无法判断某个表达式是基础概念还是细节。更恶劣的是,就像破损的窗户,一旦细节与基础概念混杂,更多的细节就会在函数中纠结起来。
15-
1. 写出短小的 switch 语句往往很难。写出只做一件事的 switch 语句也很难。我们总不发避开 switch 语句,不过还是能够确保 switch 都埋藏在较低的抽象层级,而且永远不重复。
14+
1. 写出短小的 `switch` 语句往往很难。写出只做一件事的 `switch` 语句也很难。我们总不发避开 `switch` 语句,不过还是能够确保 `switch` 都埋藏在较低的抽象层级,而且永远不重复。
1615
1. 最理想的参数数量是零,其次是一,再次是二...从测试的角度看,参数甚至更叫人为难。想想看,要编写能确保参数的各种组合运行正常的测试用例,是多么困难的事。如果没有参数,就是小菜一碟。
1716
1. 函数承诺只做一件事,但还是会做其它被藏起来的事。有时,它会对自己类中的变量做出未能预期的改动,导致古怪的时序性耦合及顺序依赖。
1817

@@ -52,7 +51,7 @@ public class UserValidator {
5251
1. 若某个函数调用了另外一个,就应该把它们放在一起,而且调用者应该尽可能放在被调用者上面。
5352

5453
## 第六章 对象和数据结构
55-
1. 最为精炼的数据结构,是一个只有公共变量、没有函数的类。这种数据结构有时被称为数据传送对象,或 DTO(Data Transfer Objects)。DTO 是非常有用的结构,尤其是在于数据库通信、或解析套接字传输的消息之类的场景中。
54+
1. 最为精炼的数据结构,是一个只有公共变量、没有函数的类。这种数据结构有时被称为数据传送对象,或 `DTO`(Data Transfer Objects)。DTO 是非常有用的结构,尤其是在于数据库通信、或解析套接字传输的消息之类的场景中。
5655

5756
## 第七章 使用异常而非返回码
5857
1. 在很久以前,许多语言都不支持异常。这些语言处理和汇报错误的手段都有限。你要么设置一个错误标识,要么返回给调用者检查的错误码。这类手段的问题在于,它们搞乱了调用者代码。调用者必须在调用之后即可检查错误。不幸的是,这个步骤很容易被遗忘。最好是抛出一个异常,这样其逻辑不会被错误处理搞乱。
@@ -109,4 +108,42 @@ public class UserValidator {
109108
- **互斥**:每一时刻仅有一个线程能访问共享数据或共享资源。
110109
- **线程饥饿**:一个或一组线程在很长时间内或永久被禁止。例如,总是让执行得快的线程先运行,加入执行得快得线程没完没了,则执行时间长的线程就会“饥饿”。
111110
- **死锁**:两个或多个线程互相等待执行结束。每个线程都拥有其它线程需要的资源,得不到其它线程拥有的资源,就无法终止。
112-
- **活锁**:执行次序一致的线程,每个都想要起步,但发现其它线程已经“在路上”。由于竞步的原因,线程会持续尝试起步,但在很长时间内却无法如愿,甚至永远无法启动。
111+
- **活锁**:执行次序一致的线程,每个都想要起步,但发现其它线程已经“在路上”。由于竞步的原因,线程会持续尝试起步,但在很长时间内却无法如愿,甚至永远无法启动。
112+
113+
## 第十四章 逐步改进
114+
1. 代码能工作还不够,能工作的代码经常会严重崩溃。满足于仅仅让代码工作的程序员不够专业。他们会害怕没时间改进代码的结构和设计,我不敢苟同。没什么比糟糕的代码给开发项目带来更深远和长期的损害了。
115+
1. 进度可以重订,需求可以重新定义,团队动态可以修正。糟糕的代码只会一直腐败发酵,无情地拖着团队的后腿。
116+
1. 保持代码持续整洁和简单,永不让腐坏有机会开始。
117+
118+
## 第十五章 JUnit 框架
119+
1. 成员变量的前缀可以删除。在现今的运行环境中,这类范围性编码纯属多余。
120+
1. 条件判断应当封装起来,从而更清晰地表达代码的意图。可以拆解处一个方法,解释这个条件判断。
121+
```java
122+
public String compact(String message) {
123+
if (expected == null || actual == null || areStringsEqual()) {
124+
return Assert.format(message, expected, actual);
125+
}
126+
}
127+
128+
// 拆解后...
129+
public String compact(String message) {
130+
if (shouldNotCompact()) {
131+
return Assert.format(message, expected, actual);
132+
}
133+
}
134+
135+
private boolean shouldNotCompact() {
136+
return expected == null || actual == null || areStringsEqual();
137+
}
138+
```
139+
140+
## 第十七章 味道与启发
141+
1. 让注释传达本该更好地在源代码控制系统、问题追踪系统或任何其它记录系统中保存的信息,是不恰当的。
142+
1. 除函数签名之外什么也没说的 Javadoc,也是多余的。
143+
1. 看到注释掉的代码,就删除它!别担心,源代码控制系统还会记得它。
144+
1. 每次看到重复代码,都代表遗漏了抽象。将重复代码叠放进类似的抽象,增加了你的设计语言的词汇量。其它程序员可以用到你创建的抽象设施。编码变得越来越快,错误越来越少,因为你提升了抽象层级。
145+
1. 死代码就是不执行的代码,可以在检查不会发生的条件的 if 语句中找到,可以在从不抛出异常的 try/catch 块中找到,可以在从不调用的小工具方法中找到,也可以在不会发生 switch/case 条件中找到。如果你找到死代码,就体面地埋葬它,将它从系统中删除掉。
146+
1. 特性依恋是 Martin Fowler 提出的代码味道之一。类的方法只应对其所属类中的变量和函数感兴趣,不该垂青其它类中的变量和函数。我们要消除特性依恋。
147+
1. 用多态替代 if/else 或 switch/case。对于给定的选择类型,不应有多于一个 switch 语句。在那个 switch 语句中的多个 case,必须创建多态对象,取代系统中其它类似 switch 语句。
148+
1. 用命名常量替代魔术数。
149+
1. 现在 enum 已经加入 java 语言了,放心用吧!别再用那个 `public static final int` 老花招。那样做 int 的意义就丧失了,而用 enum 则不然,因为它们隶属于有名称的枚举。

0 commit comments

Comments
 (0)