上一篇文章讲了标识符命名的约定,今天讲下标识符命名的选择。
简单的讲,看到一个标识符一定要可以见名知意。
-
名字一定要能够表达出标识符的含意
标识符名字必须要表达出该标识符的意义,绝对不可以使用无意义的v1,v2…vn之类的命名。
public static void CloneChars(char[] cl1, char[] cl2)
{
for (var i = 0; i < cl1.Count(); i++)
{
cl2[i] = cl1[i];
}
}
代码的调用者不看这函数是无法知道cl1还是cl2是要拷贝的char数组,他必须进到这个函数去看完整个逻辑才可以调用。而且在看的过程中cl2[i] = cl1[i]; 也需要他花几秒钟来思考是做什么的。
如果改成有意义的名字: source 和target那么这个方法调用者一看名字就知道使用方法了。
public static void CloneChars(char[] source, char[] target)
{
for (var i = 0; i < source.Count(); i++)
{
target[i] = source[i];
}
}
-
选择意义单一明确的名字
在命名时要使用专业的单词,避免使用"空洞"的单词
如: class BinaryTree
{
public int Size()
看到这行代码你想到Size会返回什么,树的高度,节点数还是树在内存中的空间?
我们可以使用更单一明确的词来告诉读者这个方法的具体含义,如Height,NodesNum,Memory_Bytes
-
使用不会产生歧义的名字
在给标识符命名时,一定不能产生歧义,代码中的很多错误都是由于命名时的歧义造成的。例如:
public const int CART_TOO_BIG_LIMIT = 10;
if (ShoppingCart.Count() >= CART_TOO_BIG_LIMIT)
{
LogError("Too many items in cart.");
}
这段代码有个很经典的"大小差一缺陷"。在判断购物车物品上限时,我是应该使用 ">"还是应该使用">=",我是无法从代码中判断出来的,所以这个地方很容易出现bug.如果我们换成MAX_ITEMS_IN_CART, 那我马上就可以判定出这里要使用">"。
-
命名要与使用者的期望相匹配
有些名字之所以会让人误解是因为带吗阅读者对它们有先入为主的印象,就算你本意并非如此。这种情况下,你最好是选用一个与使用者期望所匹配的名字。
如很多程序员都习惯了把Get开始的方法当作"轻量级访问器",他只是简单的返回成员变量。
大家看到以下的代码
class BinaryTree
{
public int GetNodesCount()
会以为只是返回内部private int _nodesCount; 私有变量的访问器。
但如果实际你的代码可能是一个非常耗时的代码,内部实现是广度优先遍历所有的树节点,还要去数据库查找父节点和子节点的关系,然后累加。
那么这么一个耗时的方法可能由于你的命名,导致了被调用者反复多次的调用,导致整个系统性能下降。
如果你将命名改为ComputeNodesCount那么调用者就会知道这是个耗时的操作,需要缓存调用结果并减少调用。
-
为名字附加更多的信息
一个变量名就像一个小注释,尽管空间不大,但不管你在命中挤进任何额外的信息,每次有人看到命名时都会看到这些信息。
例子:当你从网页接收了请求的表单,里面可能还有不安全的代码,如注入语句等,这时你在命名时需要体现该数据不安全,可以使用unsafeFormData,当调用完安全检查方法后可以将其改为 safeFormData = HandleUnsafeData(unsafeFormData).这样代码阅读者就知道可以放心的使用该变量了。
下表给出了更多需要给名字附加额外信息的例子
-
不要卖弄风骚
使用最常用,众所周知的单词。不要在代码命名时卖弄你的学识,要让你的代码快速准确的表达出你的想法才是真正的牛人。
如public static string ConvertXml2Html (string sourcePath)
有些人在看到这个方法的时候怎么想也想不明白这个2是做什么用的,是把一个Xml文件变成两个Html?
熟悉英语文化的人可能知道这是To的俚语表达。如果你不能保证所有阅读你代码的人都知道2是To的缩写。那么请使用ConvertXmlToHtml命名。