第二章 有意义的命名
- 一旦发现更好的名称,就必须换掉旧的;
- 起好名字最难的地方在于需要良好的描述技巧和共有文化背景;
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; }
|
上述代码表述模糊:
- theList 中是什么类型的东西?
- theList 0下标条目的意义是什么?
- 值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. 避免使用编码
把类型或作用域编进名称里面,徒然增加了解码的负担。
- 匈牙利标记法:类型置于实际名称前;
- 成员前缀;
- 接口和实现。
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. 不要添加没用的语境
只要短名称足够清楚,就比长名称好。