从沟通的角度看,这就不是一个有效的沟通。要想理解它,需要消耗大量的认知成本,时间和精力,同样也增加了后来人包括我们自己维护代码的成本。
其中,Info、data、flag、process、handler、build、maintain、manager、modify
等,都是属于典型的过于宽泛的名字,当这些名字出现的地方,多半都是写代码的人当时没有想好用什么名字。
命名要能够描述出这段代码在做的事情,好的名字应该描述意图,而非细节。
命名演化示例:
processChapter:处理章节,命名宽泛
changeChapterToTranlsating:将章节修改为翻译中 在描述细节
startTranslation:开始翻译,描述意图
xxxList,xxxMap,xxxSet
这是一种不费脑子的命名方式,因为它是一种基于实现细节的命名方式。
重要原则:面向接口编程,不要面向实现编程。因为接口是稳定的,而实现是易变的。
正确示例:
bookList -> books
xxxMap -> xxxMaping
实际上,在实际的代码中,技术术语的出现,往往代表着缺少了一个应有的模型。
比如在业务代码中直接出现了redis,通常来说,我们真正需要的只是一个缓存,而redis只是缓存这个模型的一个实现而已。
而再进一步,缓存这个概念也是一种技术术语,从某种意义上,它也不应该出现在业务代码中。Spring就做的比较好,需要缓存,就加上@Cacheable
的注解。
注意,在技术类项目中,存在技术术语即是业务语言的情况;但对于业务项目,这个说法就必须重新审视。
编写可维护的代码,要使用业务语音,而怎么知道自己的命名是否用的是业务语音呢,就是把这个词讲给产品经理,看他是否知道。
一个好的做法:在团队建立自己的业务语言词汇表。
approveChapter(long chapterId,long userId)
-> approveChapter(long chapterId,long reviewerId)
完成翻译,方法名:completedTranslate 不是有效的动宾结构 ->completeTranslation
重新翻译,方法名:retranslation 应该是一个动词 -> retranslate
常见的命名规则:类名是一个名词,表示一个对象;方法名是一个动词,或是动宾短语,表示一个动作。
审核:
audit:更官方,偏向审计
review
常用的做法就是把中文词扔到字典网站从返回的众多结果中找到一个自己看着顺眼的。好一点的做法是根据google翻译,然后根据二者的英文释义进行比较。
其实,在这种情况下,最好的解决方案就是建立一个业务词汇表,而不是自己臆想。建立词汇表的一个关键点是用集体智慧,而非个体智慧。另外,业务词汇表也是属于构建团队同样语言的一部分成果。
一个好的解决方案,借助工具插件检查拼写错误。
重复代码产生的一些常见原因:
示例如下:
@Task
public void sendBook() {
try {
this.service.sendBook();
} catch (Throwable t) {
this.notification.send(new SendFailure(t)));
throw t;
}
}
@Task
public void sendChapter() {
try {
this.service.sendChapter();
} catch (Throwable t) {
this.notification.send(new SendFailure(t)));
throw t;
}
}
优化之后:
@Task
public void sendChapter() {
executeTask(this.service::sendChapter);
}
@Task
public void sendBook() {
executeTask(this.service::sendBook);
}
private void executeTask(final Runnable runnable) {
try {
runnable.run();
} catch (Throwable t) {
this.notification.send(new SendFailure(t)));
throw t;
}
}
对于支持函数式编程的程序设计语言来说,可以用语言提供的便利写法简化代码的编写,就像上面的代码就是用了 Java 里的方法引用(Method Reference)
。
只要你看到 if 语句出现,而且 if 和 else 的代码块长得又比较像,多半就是出现了这个坏味道。
if (user.isEditor()) {
service.editChapter(chapterId, title, content, true);
} else {
service.editChapter(chapterId, title, content, false);
}
优化之后:
service.editChapter(chapterId, title, content, user.isEditor());