你可不能像给狗狗取名字那样给类、方法、变量命名。仅仅因为它很可爱或者听上去不错。
在写代码的时候,你要经常想着,那个最终维护你代码的人可能将是一个有暴力倾向的疯子,并且他还知道你住在哪里。
一、为什么命名很重要?
在项目中,从项目的创建到方法的实现,每一步都以命名为起点,我们需要给变量、方法、参数、类命名,这些名字出现在代码的每个角落,随处可见,混乱或错误的命名不仅让我们对代码难以理解,更糟糕的是,会误导我们的思维,导致对代码的理解完全错误。如果整个项目始终贯穿着好的命名,就能给阅读者一个神清气爽的开始,也能给阅读者一个好的指引。
要知道,代码的阅读次数远远多于编写的次数。请确保你所取的名字更侧重于阅读方便而不是编写方便。
二、为什么很难正确命名?
有人称编程中最难的事情就是命名。我同样深以为然,中国有句古话叫做万事开头难。抛开环境搭建,真正到了编码阶段第一件事就是命名,而最常见的一种情况,就是毫无目的、仅凭个人的喜好的去决定了一个名字。但因为没有想清楚目标和具体实施步骤,所以进行过程中往往会面临无数次的小重构甚至是推倒重来。
1、缺乏意愿
害怕在选择名字上花时间,对做好命名的意愿不足,随心所欲,甚至无视团队对命名的基本规范,觉得编译器能编译通过,代码能正常运行就成。其实对发现的命名问题进行重构和推倒重来并不可怕,最可怕的是当下程序员不具备发现问题后肯回过头来纠偏的意愿。这终将演变成为一场灾难。
2、缺乏思考
没想清楚被命名的事物是什么,事物应该承担什么职责,是否会对其他人造成误解。新手程序员总会花很多时间学习一门编程语言、代码语法、技术和工具。他们觉得如果掌握了这些东西,就能成为一个好程序员。然而事实并不是这样,事实上,编程不仅仅关乎掌握技能和工具,更重要的是在特定范畴内解决问题的能力,还有和其他程序员合作的能力。因此,能在代码中准确的表达自己的想法就变得异常重要,代码中最直观的表达方式是命名,其次是注释。
3、缺乏技巧
选一个好的名字真很难,你可能得有较高的描述能力和共同的文化背景。并且知晓一些常见且应该避免的命名问题。如果最终还是没法找到合适的名字,还请添加准确的注释辅助他人理解,等想到合适的名字后再进行替换,不过往往能够通过注释(母语)描述清楚的事物,命名应该问题不大,问题大的是连注释都无法准确表达,那说明可能当前类、函数、变量承担的职责太多太杂。
三、如何正确的命名?
这里不讨论具体语言的命名规则,原因是不同编程语言命名规则各不相同,甚至不同团队间相同语言的命名规则也有出入。这里主要从提高可读性出发,结合我所在的客户端团队日常开发情况,以Java作为演示语言,给一些关于命名的建议。
1、名副其实
无论是变量、方法、或者类,在看到他名称的时候应该以及答复了所有的大问题,它应该告诉你,它为什么会存在,他做什么事,应该怎么做。如果在看到名称时,还需要去查找注释来确认自己的理解,那就不算名副其实。而且在发现有更好的命名时,记得果断替换。
Case1:到底怎样算End?
代码示例:
public interface OnRequestListener { /** * 请求结束 只有成功点才认为是真正的结束 * @param ... */ void onRequestEnd(....); /** * 请求开始 * @param ... */ void onRequestStart(...); }
大脑活动:onRequestEnd是请求的什么阶段?请求成功和失败任一情况都算 “end”吗?喔,原来注释有写:“只有成功点才认为是真正的结束”。
修改建议:
// 省略注释 public interface OnRequestListener { void onStart(....); void onSuccess(....); void onFailure(...); }
2、避免误导
在每种语言中都有内置的标识符,他们都有特定的含义,如果和他们没有关联就不要在命名中加上他们。
2.1 避免使用令人误解的名字
Case1:命错名的集合
代码示例:
private List<SectionModel> dataSet;
大脑活动:
“dataSet” 在最初一定是为了元素去重选择了Set类型,肯定后来某一个历史时刻发现有bug被偷偷改成了List类型,但是变量名没变。
代码跟读:
跟踪提交记录,呃,在18年被刚定义时就是 List<***> dataSet;
修改建议:
private List<SectionModel> dataList; 或者 private List<SectionModel> sections;
Case2:不是View的View类
代码示例:
/** 作者+日期 */ public class RItemOverlayView { }
/** 作者+日期 */ public class NRItemOverlayView { }
大脑活动:
“N”是啥意思?类名只有一个N的字母差别,难道是新旧的差别,新的和旧的有什么区别呢?
类名以View结尾,嗯,应该是一个视图,可是,视图为啥不用继承视图基类的?
代码跟读:
喔,N确实代表“New”的意思,NRItemOverlayView被首页推荐使用,RItemOverlayView被购后推荐使用。
这个类主要核心工作是构建浮层视图(职责并不单一),而类本身并不是一个真正的视图;
修改建议:
// 放在首页推荐场景的包下 public class ItemOverlayViewCreator { }
// 放在购后推荐场景的包下 public class ItemOverlayViewCreator { }