代码整洁之道_02有意义的命名

第二章 有意义的命名

  • 一旦发现更好的名称,就必须换掉旧的;
  • 起好名字最难的地方在于需要良好的描述技巧共有文化背景

1. 名副其实

变量、函数或类名应该已经答复了所有的大问题,它该告诉你,它为什么会存在,它做什么事,应该怎么用。如果名称需要注释来补充,那就不算是名副其实。

选择体现本意的名称,能让人更容易理解和修改代码,如下例:

1
2
3
4
5
6
7
8
9
public list<int[]> getThem(){
List<int[]> list1 = new ArrayList<int[]>();
for(int[] x:theList){
if(x[0]==4){
list1.add(x);
}
}
return list1;
}

上述代码表述模糊:

  1. theList 中是什么类型的东西?
  2. theList 0下标条目的意义是什么?
  3. 值4的意义是什么?
  4. 我怎么使用返回的列表?

改进:

1
2
3
4
5
6
7
8
9
10
// 扫雷游戏,标记网格
public list<int[]> getFlaggedCells(){
List<int[]> flaggedCells = new ArrayList<int[]>();
for(int[] cell:gameBoard){
if(cell[STATUS_VALUE]==FLAGGED){
flaggedCells.add(cell);
}
}
return flaggedCells;
}

还可以更进一步:不用int数组表示单元格,另写一个类,包含一个名副其实的函数(isFlagged),从而掩盖住那个魔术数。

1
2
3
4
5
6
7
8
9
public list<Cell> getFlaggedCells(){
List<Cell> flaggedCells = new ArrayList<Cell>();
for(Cell cell:gameBoard){
if(cell.isFlagged()){
flaggedCells.add(cell);
}
}
return flaggedCells;
}

2. 避免误导

程序员必须避免留下掩藏代码本意的错误线索。

提防使用外形相似度较高的名称。

3. 做有意义的区分

如果名称必须相异,那其意思也应该不同(不要使用 words1,words2等添加数字或字母的形式区分变量)。

废话是另一种没意义的区分:Product、ProductInfo、ProductData

4. 读的出来

如果名称读不出来,讨论的时候就会像只傻鸟。比较下面代码:

1
2
3
4
5
class DtaRcrd102{
private Date genymdhms;
private Date modymdhms;
private final String pszqint='102';
}
1
2
3
4
5
class Customer{
private Date generationTimestamp;
private Date modificationTimestamp;
private final String recordId = '102';
}

5. 可搜索

对于单字母名称和数字变量,有一个问题就是很难在一大篇文字中找出来。

若变量或常量可能在代码中多处使用,则应赋予其便于搜索的名称。

6. 避免使用编码

把类型或作用域编进名称里面,徒然增加了解码的负担。

  1. 匈牙利标记法:类型置于实际名称前;
  2. 成员前缀;
  3. 接口和实现。

7. 避免思维映射

不应当让读者在脑海中把你的名称翻译为他们熟知的名称,选择问题领域术语还是解决方案领域术语

8. 类名-名词或名词短语

9. 方法名-动词或动词短语

10. 别抖机灵

11. 每个概念对应一个词

函数名称应当独一无二,而且要一以贯之:不要一会儿Manger,一会儿Controller.

12. 别用双关语

13. 使用解决方案领域名称

只有程序员才会读你的代码

14. 使用源自所涉问题领域的名称

如果不能用程序员熟悉的术语来给手头的工作命名,就采用从所涉问题领域而来的名称,这样维护代码的程序员就能去请教领域专家了。

优秀的程序员和设计师,其工作之一就是分离解决方案领域和问题领域的概念。

15. 添加有意义的语境

很少有名称能自我说明——多数都不能。反之,你需要用命名良好的类、函数或名称空间来放置名称,给读者提供语境。

如果不选择添加语境,给名称添加前缀就是最后一招了。

  • firstName, lastName, street, state……

  • addrFirstName, addrLastName, addrState等.

语境不明确的变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static void printGuessStatistics(String candidate,int count){
String number;
String verb;
String pluralModifier;
if(count ==0){
number="no";
verb="are";
pluralModifier="s";
}else if(count==1){
number="1";
verb="is";
pluralModifier="";
}else{
number=count+"";
verb="are";
pluralModifier="s";
}
String guessMessage =String.format("there %s %s %s", number,verb,candidate,pluralModifier);
System.out.println(guessMessage);
}

有语境的变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

public class GuessStatisticsMessage{
private String number;
private String verb;
private String pluralModifier;

public String make(char candidate,int count){
createPluralDependentMessageParts(count);
return String.format("there %s %s %s", number,verb,candidate,pluralModifier);
}
private void createPluralDependentMessageParts(int count){
if(count==0){
thereAreNoTettle();
}else if (count==1){
thereAreOneLetter();
}else{
thereAreManyLitters(count);
}
}
private void thereAreNoTettle(){
number ="no";
verb="are";
pluralModifier="s";
}
private void thereAreOneLetter(){
number ="1";
verb="is";
pluralModifier="";
}

private void thereAreManyLitters(int count){
number =count+"";
verb="are";
pluralModifier="s";
}
}

16. 不要添加没用的语境

只要短名称足够清楚,就比长名称好。