java代码规范之不合理命名与重复代码示例详解
作者:GuangHui
一. 命名
1.1 命名是否具有业务含义
(1) 命名不精准,用词宽泛,不能有效反应代码含义
从沟通的角度看,这就不是一个有效的沟通。要想理解它,需要消耗大量的认知成本,时间和精力,同样也增加了后来人包括我们自己维护代码的成本。
其中,Info、data、flag、process、handler、build、maintain、manager、modify
等,都是属于典型的过于宽泛的名字,当这些名字出现的地方,多半都是写代码的人当时没有想好用什么名字。
命名要能够描述出这段代码在做的事情,好的名字应该描述意图,而非细节。
命名演化示例:
processChapter:处理章节,命名宽泛
changeChapterToTranlsating:将章节修改为翻译中 在描述细节
startTranslation:开始翻译,描述意图
(2) 用技术术语命名
xxxList,xxxMap,xxxSet
这是一种不费脑子的命名方式,因为它是一种基于实现细节的命名方式。
重要原则:面向接口编程,不要面向实现编程。因为接口是稳定的,而实现是易变的。
正确示例:
bookList -> books xxxMap -> xxxMaping
实际上,在实际的代码中,技术术语的出现,往往代表着缺少了一个应有的模型。
比如在业务代码中直接出现了redis,通常来说,我们真正需要的只是一个缓存,而redis只是缓存这个模型的一个实现而已。
而再进一步,缓存这个概念也是一种技术术语,从某种意义上,它也不应该出现在业务代码中。Spring就做的比较好,需要缓存,就加上@Cacheable
的注解。
注意,在技术类项目中,存在技术术语即是业务语言的情况;但对于业务项目,这个说法就必须重新审视。
(3) 用业务语音写代码
编写可维护的代码,要使用业务语音,而怎么知道自己的命名是否用的是业务语音呢,就是把这个词讲给产品经理,看他是否知道。
一个好的做法:在团队建立自己的业务语言词汇表。
approveChapter(long chapterId,long userId) -> approveChapter(long chapterId,long reviewerId)
(4) 小结
- 坏味道:不精准的命名,用技术术语命名。
- 解决之道:好的命名要体现代码在做什么,但无需展示代码的细节,更进一步,要准确体现意图,而不是实现细节,更高的要求是,用业务语言写代码。
- 原则:描述意图,而非细节;面向接口编程,接口是稳定的,实现是易变的;命名出现技术名词,往往是缺少了一个模型;使用业务语音。
1.2 命名是否符合英语语法
(1)违反语法规则命名
完成翻译,方法名:completedTranslate 不是有效的动宾结构 ->completeTranslation
重新翻译,方法名:retranslation 应该是一个动词 -> retranslate
常见的命名规则:类名是一个名词,表示一个对象;方法名是一个动词,或是动宾短语,表示一个动作。
(2)不准确的英语词汇
审核:
audit:更官方,偏向审计
review
常用的做法就是把中文词扔到字典网站从返回的众多结果中找到一个自己看着顺眼的。好一点的做法是根据google翻译,然后根据二者的英文释义进行比较。
其实,在这种情况下,最好的解决方案就是建立一个业务词汇表,而不是自己臆想。建立词汇表的一个关键点是用集体智慧,而非个体智慧。另外,业务词汇表也是属于构建团队同样语言的一部分成果。
(3)英语单词拼写错误
一个好的解决方案,借助工具插件检查拼写错误。
(4)小结
- 坏味道:命名违反语法规则,用词不准确,单词拼写错误。更低级的一些,使用拼音,使用不恰当的单词简写。(如果非要用缩写,可以用一些行业通用的缩写,而最好不要自己创造,前提是一定要约定好)
- 解决之道:制定代码规范,比如类名用名词,函数名用动词或动宾短语;建立团队词汇表;经常进行代码评审。
-小工具:命名插件codelf。
二. 重复代码
重复代码产生的一些常见原因:
- 代码结构不合理导致同一个实现散落各处。由于初期代码结构设计不合理导致后续功能实现无法快速找到已有实现,或者找到了但是不好引用已有实现。改进:初期设计代码逻辑合理,对于不合理的地方要及时重构 防止演变成原因2。
- 为了稳定性,不动老逻辑,拷贝一份。由于对于业务的不熟悉和对自己代码能力的不信任,不敢重构导致。改进:通过微重构进行多次迭代小改进慢慢优化。
- 写的时候为了快,由于时间紧张或者能力问题,无法识别出的坏代码。改进:提升能力。
复制粘贴的代码
结构重复的代码
示例如下:
@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 和 else 代码块中的语句高度类似
只要你看到 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());
小结
- 坏味道:重复的代码,重复的结构,if 和 else 代码块中的语句高度类似
- 解决之道:不要使用复制粘贴;先提取函数,然后在需要的地方调用这个函数。
以上就是java代码规范之不合理命名与重复代码示例详解的详细内容,更多关于java命名代码规范的资料请关注脚本之家其它相关文章!