最近在学习 郑晔 在极客时间上的一个专栏《代码之丑》,并根据自身情况整理了一份笔记
01 | 缺乏业务含义的命名:如何精准命名?
例如这样一段代码:
public void processChapter(long chapterId) {
Chapter chapter = this.repository.findByChapterId(chapterId);
if (chapter == null) {
throw new IllegalArgumentException("Unknown chapter [" + chapterId + "]");
}
chapter.setTranslationState(TranslationState.TRANSLATING);
this.repository.save(chapter);
}
经过阅读我们发现,这段代码做的就是把一个章节的翻译状态改成翻译中,但是我们需要读完代码的细节才知道这段代码的意思。
data、info、flag、process、handle、build、maintain、manage、modify等等。这些名字都属于典型的过于宽泛的名字
processChapter(处理章节)的命名过于宽泛,不能精准描述,这是很多代码在命名上存在的严重问题,也是代码难以理解的根源所在。
1.命名要能够描述出这段代码在做的事情。
这段代码在做的事情就是“将章节修改为翻译中”。那是不是它就应该叫
changeChapterToTranslating
呢?
2.一个好的名字应该描述意图,而非细节。
就这段代码而言, 我们为什么要把翻译状态修改成翻译中,这一定是有原因的,也就是意图。具体到这里的业务,我们把翻译状态修改成翻译中,是因为我们在这里开启了一个翻译的过程。所以,这段函数应该命名
startTranslation
最终修改为:
public void startTranslation(long chapterId) {
Chapter chapter = this.repository.findByChapterId(chapterId);
if (chapter == null) {
throw new IllegalArgumentException("Unknown chapter [" + chapterId + "]");
}
chapter.setTranslationState(TranslationState.TRANSLATING);
this.repository.save(chapter);
}
3.不要用技术术语命名
例如:
List<Book> bookList = service.getBooks();
这个 bookList 变量之所以叫 bookList,原因就是它声明的类型是 List。
比如,如果我发现,我现在需要的是一个不重复的作品集合,也就是说,我需要把这个变量的类型从 List 改成 Set。变量类型你一定会改,但变量名你会改吗?这还真不一定,一旦出现遗忘,就会出现一个奇特的现象,一个叫 bookList 的变量,它的类型是一个 Set。这样,一个新的混淆就此产生了。
因为接口是稳定的,而实现是易变的。 我们需要一个更面向意图的名字。其实,我们在这段代码里真正要表达的是拿到了一堆书,所以,这个名字可以命名成 books
List<Book> books = service.getBooks();
虽然这里我们只是以变量为例说明了以技术术语命名存在的问题,事实上,在实际的代码中,技术名词的出现,往往就代表着它缺少了一个应有的模型。
在一个技术类的项目中,这些技术术语其实就是它的业务语言。但对于业务项目,这个说法就必须重新审视了。
4.用业务语言写代码
编写可维护的代码要使用业务语言,例如以下一段代码
public void approveChapter(long chapterId, long userId) {
...
}
这个函数的意图是,确认章节内容审核通过。这里有一个问题,chapterId 是审核章节的 ID,这个没问题,但 userId 是什么呢?了解了一下背景,我们才知道,之所以这里要有一个 userId,是因为这里需要记录一下审核人的信息,这个 userId 就是审核人的 userId。你看,通过业务的分析,我们会发现,这个 userId 并不是一个好的命名,因为它还需要更多的解释,更好的命名是 reviewerUserId,之所以起这个名字,因为这个用户在这个场景下扮演的角色是审核人(Reviewer)。
public void approveChapter(long chapterId, long reviewerUserId) {
...
}
从某种意义上来说,这个坏味道也是一种不精准的命名,但它不是那种一眼可见的坏味道,而是需要在业务层面上再进行讨论,所以,它是一种更高级的坏味道。
总结
好的命名要体现出这段代码在做的事情,而无需展开代码了解其中的细节,这是最低的要求。再进一步,好的命名要准确地体现意图,而不是实现细节。更高的要求是,用业务语言写代码。
如果今天的内容你只能记住一件事,那请记住:好的命名,是体现业务含义的命名
。