名称命名规则-《代码整洁之道》读书笔记(一)
原文地址:https://liujiao111.github.io/2019/06/18/clean-code/
变量命名是程序最基础的部分,也是多数人容易忽视的部分,总认为它无足轻重,事实不然,命名规范的代码能让人看起来赏心悦目、清晰明了。以下是一些在变量命名时候适合遵循的一些规则。
名副其实
变量、函数、类的名称应该能回复所有大的问题,它告诉你,它为什么存在,它做什么事,应该怎么用。如果名称需要注释来补充,那就不是名副其实
例如以下代码:
public static List<int[]> getThem(List<int[]> theList) {
List<int[]> list1 = new ArrayList<>();
for (int[] x : theList) {
if(x[0] == 4) {
list1.add(x);
}
}
return list1;
}
代码看起来很简单,也没有什么错误的地方,但是问题是代码的模糊度,具体有如下问题:
- theList是什么;
- theList的0下标条目的意义是什么?
- 值4的意义是什么?
- 我怎么使用返回的列表?
改进: - 如果我们在开发一个扫雷游戏,theList代表盘面的单元格列表,那就将其改名为gameBoard
- 0下标条目是一种状态值,4表示"已标记",只要将其改为有意义的名称,代码就会得到相当程度的改进,返回的数据也是这样
private static final int STATUS_VALUE = 0;
private static final int FLAGGED = 4;
public static List<int[]> getThem(List<int[]> theList) {
List<int[]> flaggedCells = new ArrayList<>();
for (int[] cell : theList) {
if(cell[STATUS_VALUE] == FLAGGED) {
flaggedCells.add(cell);
}
}
return flaggedCells;
}
还可以更进一步,不用int数组表示单元格,而是另写一个类,该类包括一个isFlagged函数,用来判断该cell是否已经标记过了。
新版本代码如下:
public static List<Cell> getThem(List<Cell> theList) {
List<Cell> flaggedCells = new ArrayList<>();
for (Cell cell : theList) {
if(cell.isFlagged()) {
flaggedCells.add(cell);
}
}
return flaggedCells;
}
对应的cell类(书中没有代码,不一定准确)
public class Cell {
private Integer flag;
private static final int FLAGGED = 4;
public Cell(Integer flag) {
this.flag = flag;
}
private boolean isFlagged() {
return this.getFlag() == FLAGGED;
}
public Integer getFlag() {
return flag;
}
public void setFlag(Integer flag) {
this.flag = flag;
}
}
可以看出来,只要简单改一下名称,就能轻易知道发生了什么,这就是选用好名字的力量。
避免误导
- 不使用平台里面的专有名词做变量名,如hp、aix、sco等;
- 不用带List的名称来代表一组东西,例如accountList,用accountGroup或者bunchOfAccounts来代替,甚至accounts都更好些
- 使用名称区分度很小的命名;
- 名称中带有看起来比较像的字母、数字,例如字母1和大写字母O作为变量名,以及1和字母I,因为O很像0
做有意义的区分
- 以数字系列命名,如(a1, a2, a3 …),这样的名称纯属误导
- 废话也是一种无意义的区分,假如一个Product类里面有ProductInfo或者ProductData类,他们的名称虽然不同,但info和data的意义没有什么区分
使用读得出来的名称
单个字母和数字常量在文档中很难搜索到想要的,因为可能有很多,因此单个变量仅适用于短方法的本地变量,名称长短应与其作用域大小相对应,若变量或常量在代码中多处使用,应赋予其便于搜素的名称,如WORK_DAYS_PER_WEEK和5的区别
接口和实现
接口前面没有必要加个I来修饰
避免思维映射
除了在循环计数器之中使用i或者j,其他地方都应避免使用单字母变量来命名
类名
类名应该是名词或者名词短语,避免使用动词
方法名
方法名应该是动词或动词短语,如postPayment, deletePage或save,JavaBean中加上get, set,is 前缀
每个概念对应一个词
给每个抽象概念选一个词,并一以贯之
别用双关语
避免将同一单词用于不同目的。代码应该尽力让读者易懂,需要大众化的浅显易懂,而不是需要费劲去深挖的学院派模式
使用解决方案领域名称
尽量使用计算机科学术语,依据问题所涉及的领域来命令可不算是聪明的做法。
使用源自所涉及问题领域的名称
如果不能使用计算机科学领域的术语来命名,那就采用所涉及问题领域而来的名称
添加有意义的语境
多数名称都不能自我说明,反之,如果有良好命名的类、函数或名称空间来放置它们,给读者提供语境,这样能让别人更清晰。
如有一堆变量:firstName、lastName、street、houseNumber、city、state和zipcode的变量,它们放在一起时很明确是构成了一个地址,但是假如在方法中孤零零看到一个state呢?你很大概率上不会以为这是地址的一部分吧?你可以添加前缀addrFirstname、addrState等,以此提供语境,更好的方案是创建Address类。
不要添加没用的语境
比如有个GSD的应用,在其中每个类前面加个GSD前缀就是没必要的工作。
上一篇: placeHoder的对齐方式
下一篇: 二级python学习笔记2:命名规则