有读者看到就开始敲键盘了,这还需要写个文章来水?命名不就是不能用 abc、123 这种,名字要有意义嘛,这有啥好讲的?
但现实中,虽然懂得名字要有意义,很多程序员依然无法逃离命名沼泽。
万金油命名法
什么叫精准?
看段代码:
看上去不是挺正常吗?有何不可?
那我问你,这段代码在干嘛?你就得全神贯注去阅读代码细节了。已阅后,你说这段代码不就是把一个章节的翻译状态改成翻译中。
为何你得阅完这段代码细节,才知道该方法在干嘛?
问题就在方法名 - processChapter,该方法是在处理章节没错,但这名太宽泛。如果说“将章节的翻译状态改成翻译中”就叫处理章节,那么请问:
- 将章节的翻译状态改成翻译完毕
- 修改章节内容
是不是也能叫处理章节呢?
所以,这的确是个过于宽泛的方法名,没有大错,但不精确!
乍一看,这名字有含义,但实际却不能有效反映这段代码的具体含义。
若做的是个信息处理系统,你根本无法判断,这是个博客平台还是个图书管理系统呢?
从沟通角度看,这就不是一个有效信息表达。想理解它,需要消耗大量时间精力。
命名过于宽泛,不能精确描述,这是很多代码命名现状,也是让祖传代码难以理解的根因。
回想这些命名:data、info、flag、process、handle、build、maintain、manage、modify......
这些都属于 过于宽泛的命名,当这些名字出现在你的代码,可以肯定作者当时也没想好用啥名字,就开始随便起个万金油名字继续coding了。
扯半天,那它不能叫处理章节,那该叫啥?
- 命名要能精确描述该方法在做什么
这段代码就是“将章节改为翻译中”。那是不是该叫 changeChapterToTranlsating?相比处理章节,这个名字已经算进步了,但也不算是个好名字,因为它更多的是在描述这段代码在做的细节。而封装一段代码成方法,就是因为我们不想知道过多细节。如果把细节平铺开来,那就和直接读代码细节没啥区别了。
- 好名字应该描述意图,而非细节
这段代码为何要将翻译状态修改成翻译中呢?一定是有所图的。把翻译状态改成翻译中,是因为我们在这里开启了一个翻译的过程。所以,这个方法应该叫 startTranslation
技术术语命名法
再看一段代码:
这!也能有问题?我天天看到还写这种代码啊。
是的,我知道你们都在写这种风格代码,这就是另一个经典问题:技术术语命名法。
之所以叫 bookList,在于其声明类型是 List。这种命名几乎随处可见,如 xxMap、xxSet。
这也是种不费脑命名法,但这种命名却会带来很多问题,因为是基于技术实现细节的命名方式。
我们都知道面向接口编程原则,就是不要面向实现编程,因为接口是稳定的,而实现易变不稳定。大多数人只觉得该原则是针对类型的,但命名方面,也同样应该遵循。比如,我发现现在需要的是个不重复作品集合,即我得把这个变量的类型从 List 改成 Set。变量类型相信你一定会改,但变量名你会改吗?还真不一定,一旦忘了,就会出现:一个 bookList 变量,居然是Set类型!
那怎么命名呢?得有个更能表达意图的名字,这段代码表达的就是拿到一堆书,所以可以叫 books。
这名字更简单,也很表达意图了。
追根究底,使用技术名词,一般因为它缺少对应模型。
比如,在业务代码里若直接出现 Redis:
通常来说,这里真正需要的是个缓存。Redis 只是缓存模型的一个具体实现:
但其实缓存这个概念也是个技术专业术语,也不应出现在业务代码中。
做得好的是 Spring,使用 Spring 时,若需要缓存,一般是加个注解:
很多人爱用技术名词去命名,大多因为:
- 熟悉的语言
- 写代码,很多都是参考别人代码,优秀代码都是一些开源技术项目。那在一个技术类项目中,这些技术术语其实也就是它的业务语言。但对于我们的业务类项目,就不能生搬硬套了
若该部分确实就是处理一些技术,使用技术术语无可厚非,但若是在处理业务,就要尽可能规避技术术语。
像xxMap这种命名,表示映射关系,如:书id与书的映射关系,难道也不能命名为bookIdMap?
Map 表示的是个数据结构,而映射关系推荐写成 Mapping。
高级点的坏味道
前面的坏味道其实本质都是同一问题:对业务理解不到位。
编写可维护的代码要使用业务语言。那如何知道自己的命名是否用的是业务语言呢?
把这个词讲给PM听,看他懂是啥不。
团队里若每个人都根据自己理解命名,就可能出现百家争鸣的命名,所以,一个良好的团队实践是建立团队的业务词汇表,统一业务命名。
当团队对业务有了一致的理解后,兴许还能发现更高级的坏味道:
看方法名,应该是确认章节内容审核通过。
但我有一问,chapterId 是审核章节的 ID,这没问题,但 userId 是啥?了解背景后,才知道这里要 userId,是因为需要记录审核人信息。
通过业务的分析,就发现,这个 userId 不是个好名字,因为它还需要更多解释,更好的命名是 reviewerUserId,因为这用户在当前场景下就是审核人(Reviewer)角色。
这也是一种万金油命名法,但它不是那种一眼就能看出的坏味道,而是需要在业务层进行讨论,所以,算个高级坏味道。