时时刻刻都在命名

软件中随处可见命名。我们给变量、函数、参数、类和封包命名。我们给源代码及源代码所在目录命名。我们给jar文件、war文件和ear文件命名。我们命名、命名,不断命名。既然有这么多命名要做,不妨做好它。下文列出了取个好名字的几条简单规则。

名副其实

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

  1. int d; // 创建以来天数

名称d 加了额外的注释,本身毫无意义。

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

(1)getThem 是什么?
(2)list1 目的意义是什么?
(3)值4的意义是什么?
(4)我怎么使用返回的列表?

问题的答案没体现在代码段中,可那就是它们该在的地方。比方说,我们在开发一种扫雷游戏,我们发现,盘面是名为theList的单元格列表,那就将其名称改为gameBoard。

  1. public List<int[]> getFlaggedCells() {
  2. // List<int[]> list1 = new ArrayList<int[]>();
  3. List<int[]> flaggedCells = new ArrayList<int[]>();
  4. //for (int[] x : theList)
  5. for (int[] cell : gameBoard)
  6. // if (x[0] == 4)
  7. if (cell[STATUS_VALUE] == FLAGGED)
  8. // list1.add(x);
  9. flaggedCells.add(cell);
  10. //return list1;
  11. return flaggedCells;
  12. }

进一步优化,隐藏魔术数字

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

做有意义的区分

  1. public static void copyChars(char a1[], char a2[]) {
  2. for (int i = 0; i < a1.length; i++) {
  3. a2[i] = a1[i];
  4. }
  5. }

以数字系列命名(a1、a2,……aN)是依义命名的对立面。这样的名称纯属误导——完全没有提供正确信息;没有提供导向作者意图的线索。
如果参数名改为source(源)和destination(目标),这个函数就会像样许多。

使用正确的英文

  1. private Date genymdhms;//生成日期,年、月、日、时、分、秒

gen为generation缩写,ymdhms为格式符,如果不加那是注释毫无意义且令人费解的命名

  1. private Date generationTimestamp;

注:Timestamp 时间戳

好的名称判断:可以读出来的名称

使用可搜索的名称

单字母名称和数字常量有个问题,就是很难在一大篇代码中找出来。

  1. for (int j=0; j<34; j++) {
  2. s += (t[j]*4)/5;
  3. }
  1. int realDaysPerIdealDay = 4;
  2. final int WORK_DAYS_PER_WEEK = 5;
  3. int sum = 0;
  4. for(int j=0; j < NUMBER_OF_TASKS; j++) {
  5. int realTaskDays = taskEstimate[j] * realDaysPerIdealDay;
  6. int realTaskWeeks = (realdays / WORK_DAYS_PER_WEEK);
  7. sum += realTaskWeeks;
  8. }

消除对成员前缀

  1. public class Part {
  2. private String m_dsc; // The textual description
  3. void setName(String name) {
  4. m_dsc = name;
  5. }
  6. }

也不必用 m_前缀来标明成员变量。应当把类和函数做得足够小,消除对成员前缀的需要。你应当使用某种可以高亮或用颜色标出成员的编辑环境。

  1. public class Part {
  2. String description;
  3. void setDescription(String description) {
  4. this.description = description;
  5. }
  6. }

此外,人们会很快学会无视前缀(或后缀),只看到名称中有意义的部分。代码读得越多,眼中就越没有前缀。最终,前缀变作了不入法眼的废料,变作了旧代码的标志物。

类名不应当是动词

类名不应当是动词。
类名和对象名应该是名词或名词短语,如Customer、WikiPage、Account和AddressParser。避免使用Manager、Processor、Data或Info这样的类名,比如AccountManager 比 Manager 更具体。

方法名应当是动词或动词短语

方法名应当是动词或动词短语,如postPayment、deletePage或save。