目录
命名原则
1. 有意义的命名
由例子引出概念:
模糊示例1:
var i int //elapsed time in days---已用的时间
改良示例1:
var elaspedTimeInDays int
这里给出了两个例子,前者的变量名为i,再加注释,后者使用了注释的内容作为变量名,好的命名应该让它的命名就可以直接读懂,因为变量使用并不是只使用一次,如果后续代码中继续出现了,那么还要加注释吗,这显然就不够优雅。
使用一个能够让人读懂的变量名,这样在使用到这个变量的时候也可以直接读懂。
模糊示例2:
public List<int []> getThem(){
List<int []> list1 = new ArrayList<int []>();
for (int x: theList)
if (x[0] == 4)
list1.add(x);
return list1;
}
在这个例子里面,存在着几个问题:
- getThem的名字太过抽象。
- list1的命名有点太随便了。
- thelist是一个list,用途不明,保存东西不明。
- x[0]是什么东西,为什么要对他进行判断。
- 4的作用是什么。
改良的话,可以考虑根据这些问题进行修改。
public List<int []> getFlaggedCells(){
List<int []> flaggedCells= new ArrayList<int []>();
for (int[] cell: gameBoard)
if (cell(STATUS_VALUE) == FLAGGED) //FLAGGED为原来的4,STATUS_VALUE为原来的0
flaggedCells.add(cell);
return flaggedCells;
}
改良之后从函数名上看,这个函数的返回对象应该是一个flaggedCells的东西。
在进去函数的第一步命名了一个flagedCells的东西,这样的话我们就可以知道,这个函数要返回的东西就是这一个了。
这里的thelist改名成gameBoard,大概知道这个对象是游戏面板一样的东西。
为了避免魔法数字的出现,这里的STATUS_VALUE定义成了一个常量,名字是状态值,可能是这个位置是用来做状态判断的,FLAGGED可能是这个位置里面的一个具体的状态量。
命名的作用在这个例子里面可以初见成效,给人一个大概的印象,而不是一头雾水。
模糊例子中的代码并不是说运行会出现问题,而是当程序换一个人来看或者自己隔个半个月来看的时候会不想看,因为这里面的东西太含糊了,得去了解上下文才能知道这个函数的作用。
2. 避免误导
不要使用保留字作变量名,例如hp、aix、sco(UNIX平台或类UNIX平台的专有名称)。
不要使用很相似的命名给自己增加难度。例如:gameName1、gameName2,happyGameEndController,happyBoyEndController,
这里文中给的例子是又长又相似,
XYZControllerForEfficientStorageOfStrings 和 XYZControllerForEfficientHandlingOfStrings
我感觉有点强行了。。
这样只会让人花费更多时间在阅读命名上。
3. 做有意义的区分
例如:workNight和workEvening,
这一类的命名,翻译过来的意思是一样的,如果没有强烈需要不建议同一作用范围里有两个意思相同但是命名不同的命名形式。
这也同时是在说添加数字作区分方法的习惯。
var workNight1 int
var workNight2 int
这样的命名方法只是写给了编译器看,我做了区分,而不是让读代码的人看。
4. 使用读得出来的名称
例如:
genymdhms(生成日期(generate)、年(y)、月(m)、日(d)、时(h)、分(m)、秒(s))
这样的命名,原是要给时间戳命名但是自己造了一个新的英语单词,但是不知道的人就不知道这个单词是什么。违反了平时储存在大脑里面的单词库。给人一头雾水的代码模糊感。
用英语单词而不是自造词
5. 使用可搜索的名称
在代码中使用了魔法数字。
public List<int []> getThem(){
List<int []> list1 = new ArrayList<int []>();
for (int x: theList)
if (x[0] == 4)
list1.add(x);
return list1;
在这个代码片段里面出现了0和4,我们并不知道这两个数字在这段代码里面是什么意思,如果它们被泛滥的使用在全部代码里面时就会出现很多看不懂的数字,也被叫做魔法数字。
解决方法:在使用这些数字时我们应该给他定义成常量,并且给一个可以看懂的常量名,这样在使用的时候我们就可以看出这个数字具体的含义,并且这个常量名也是可以被搜索到的。
public List<int []> getThem(){
List<int []> list1 = new ArrayList<int []>();
for (int x: theList)
if (x[STATUS_VALUE] == FLAGGED)
list1.add(x);
return list1;
这一部分只针对数字进行修改。
6. 避免使用编码
- 在命名里面尽量不要出现编码,例如:
var timeString string
string是go语言里面的一种类型,但是我们不应该在这个变量的命名里面加上对应的类型,这样就会要求阅读这个代码的人需要了解go语言中的string类型,才能明白这个string意思。这样的命名就需要读者能理解编码者使用的一套编码规则。
- 尽量减少成员前缀
private String m_dec;
这种m_
的前缀应该尽可能的避免使用,因为没有表名某种意义。
- 接口和实现
//抽象类工厂命名
IShapeFactory
接口应该不加修饰,I
就显得很突兀。
7 避免思维映射
思维映射指读者看到代码,还要去脑海里进行一番想象才能得出结果。
例如循环外的单字母名称,
string a;
string b;
string c;
这样的以单字母来命名的名称,无法让人想象他们是否有什么关系。
8 类名
类名和对象名,命名时应该使用名词而不是使用动词。
举个例子:
Customer、WikiPage、Account、AddressParser
也应该避免使用意思丰富的名词:
Data、Info、Manager
9 方法名
方法名应该是动词和动词短语。也可以在前缀加上get、set、is。
重载方法名时,方法名可以使用描述了参数的静态工厂名
Complex fulcrumPoint = Complex.FromRealNumber(23.0);
这样的方法名阅读性更高,相比起下面的例子来说:
Complex fulcrumPoint = new Complex(23.0);
10 别抖机灵
名称不应该包含一些俚语或者脑筋急转弯。
HolyHandGrenade
如果用上面这个名称来命名函数,谁知道这个函数是做什么的呢,这个词来自于一部电影《巨蟒与圣杯》,意译为圣手雷。
11 同种概念的词应该统一
给每种抽象的概念选一个词。什么叫抽象概念呢?举个例子:
获取
这个词可以用get
,fetch
,retrieve
等等单词来命名,但是如果都是获取的方法,如果我们使用了多个不同的获取英文单词,就会出现方法名字变得多样化,这样并不利于理解。大多数情况下只要有一种就可以了。
12 别用双关语
不要将不同的动作用同一个单词进行说明。举个例子:
add
可以用来求和,那如果是数据库插入也用add
就会让这个add
出现了不同的意思。我们可以适当的进行更换成insert
。
13 使用解决方案领域名称
只用程序员才会阅读你的代码,所以我们可以使用计算机领域的术语,算法名来进行命名。
14 使用源自所涉问题领域的名称
当前面一点(13)无法使用时,我们应该尽量使用和问题相关的领域的名称来进行命名,这要程序员也好去问别人。
源自所涉问题领域的名称,和解决方案领域名称的对比使用中,优先选择解决方案领域名称。
15 添加有意义的语境
firstName、lastName、houseNumber
单独看这样的名称,我们只能推测出它的意思。如果再添加上语境来修饰可能会得到更具体的信息。
addrFirstName、addrLastName、addrHouseNumber
addr就是和地址相关,我们可以初步理解这几个量都会和addr有关的,而addr是地址的缩写。
16 不添加无意义的语境
好的语境能够让读者更清晰的了解到具体的含义,而无意义的语境就会让编码时要多耗费时间但是对读者没有意义。
theFirstName、theLastName、theHouseNumber
本节内容学自《代码整洁之道》,是对本人编码坏习惯的一次清洗。也希望能写出足够优雅的语言,不要掉头都不想看自己的代码。