要想写出清晰易读的代码,有意义的命名是最基础的要求。
在软件开发的过程中,命名这项工作随处可见。我们给变量、函数、类、包体命名,以便让它们表明自己的功能。好的名字具有自解释性,无需额外的注释,更方便维护。 在写代码时,我很大一部分精力都花费在了如何给变量命名上。我认为这是重要且必须的,因为你写的代码,大部分时间是会被别人阅读到的。良好的命名会节省很大的沟通和维护成本 ,让自己和同事都节省很多时间。那么,如何给代码取名字呢? 其实取名字只有一条最重要的原则,那就是:
良好命名需要有自解释性。
就是说,对一个实体的命名,需要名副其实,要表明自身的作用。只有遵循这条原则,才能写出易读性高的代码。衡量标准也很简单:
是否需要额外的注释来补充意图。
如果名称需要注释来补充,那就不算是名副其实,自解释性就比较差。最好的名字,是名字本身已经解答了我们关心的大部分问题。
例如对于一个表示已创建天数的变量,有以下两种命名方法,很明显,指明了计量对象和计量单位的第二种命名方式,更容易让人明白这个变量的用途。
int d; //单字母缩写命名方式
int daysSinceCreate; // 表明了计量对象和计量单位的命名方式
简洁的代码有时候并不容易理解,对于软件来说,命名的优先级应该是这样的。语义清楚 > 代码简洁。在LeetCode上有很多看似非常酷炫简洁的一行代码解法,但其实可读性很长,实际工作中如果你这样写代码,可能会被同事打死。
那么,原则知道了,如何才能写出具有良好自解释性的命名呢?有以下几条原则可以参考。相信只要在命名是遵循以下几条军规,就可以写出好的命名。
- 不要长得非常类似的名称。 例如
ListAllEfficientProjectOfUser和ListAllEffectProjectOfUser就是两个外形非常相似的方法名,不要用这种名字。 - 不要混用长得非常相似的字母或数字。 比如小写字母
l和数字1,大写字母O和数字0,非常迷惑。 - 避免将同一单词用于不同目的。 例如
add这个词,如果已经在代码中使用add表示两个数字相加,就不要再用add表示把一个元素添加到一个集合中了,可以换用insert或者append等其他词。 - 名字要有区分度。 不要加一些毫无区分度的字眼,命名要有区分度,减少名字里的冗余词汇,例如
ProjectData和ProjectInfo意思就毫无区别,Consumer和ConsumerUser也无法表达出任何不同的意思。所以类似的名字不要同时出现在同一块代码中。 - 名字要能读出来。 公司里最常见的场景是两个同时讨论一段代码的逻辑是不是有问题,如果这个时候你俩讨论的时候用的是可以念出来的
generatedTimestamp,而不是你自创的缩写gents,沟通起来就会顺畅很多。 - 使用便于搜索的名字。 代码的读和写的时间占比,大概要占到7:3。也就是说大部分时间我们是在查阅代码。那么轻松找到想看的代码就非常重要了。如果你用
workDaysPerWeek代替5就会感到非常幸福。 - 长名称好于短名称。 目的仍然是容易搜到,而且名称的长短应该与它的作用域成正比。比如
ListAllVipUsers就比ListUsers要好一些。 - 类和对象的名称应该使用名词。 类名应该是名词而不是动词,因为类和对象都是一种实体。
- 方法名使用动词。 方法名应该是动词而不是形容词,因为方法往往表示一种行为。
- 每个抽象概念应该使用一个一以贯之的词汇。 软件就是构建一个一个的抽象概念,使用统一的命名来指代相同的抽象概念,会更容易让人理解。例如对于
用户这个抽象概念,代码中即出现了user,又出现了consumer,还出现了tenant,就很容易让人迷惑,不如统一使用user来代替,更为清晰。 - 添加有意义的语上下文语境。 对于
firstName,lastName,adress等变量,可以放在一个名为User的类中,更不容易产生歧义。 - 不添加没用的上下文语境。 例如对于
User这一个对象,需要一组增删改查接口,create,list,update和delete就比createUser,listUser,updateUser和deleteUser要强,短名称就足够清晰,不需要添加不必要的语境。
取一个好名字不是容易的事情,但如果名称取得好,你的同事们真的会感谢你。好的办法就是不断重构,就像童子军军规一样:让营地比来的时候更干净。也就是看见问题就修复掉。现代IDE的帮助,让改名字变成了一个很容易,成本很低的事情,所以不要吝啬你的一点微小努力,试着提升代码可读性吧。