开发规范
开发规范设计很多部分,包括代码提交规范、代码规范、日志规范......就是由于设计庞杂,所有所以越是应该在项目启动前期将这些规范定义好。
# 📑 代码规范
代码规范,老生常谈。有规范可循,实现代码高质量、高可读以及可维护。特别是在多人协同开发时尤为重要。
Google Java Style Guide
🍻Complete definition of Google's coding standards
Alibaba Java Code Guide
🥂Gitbook for AJCG
- name: Google Java Style Guide
desc: 🍻Complete definition of Google's coding standards
link: https://google.github.io/styleguide/javaguide.html
bgColor: '#F0DFB1'
textColor: '#242A38'
- name: Alibaba Java Code Guide
desc: 🥂Gitbook for AJCG
link: https://alibaba.github.io/Alibaba-Java-Coding-Guidelines/
bgColor: '#DFEEE7'
textColor: '#2A3344'
2
3
4
5
6
7
8
9
10
禁用魔法值:除预定义的外,在编码中禁止使用魔术值。建议定义枚举值或者静态常量值,并写好注释说明。
单个方法的总行数不超过80行。除注释之外的方法签名、结束右大括号、方法内代码、空行、回车及任何不可见字符的总行数不超过80行。代码逻辑分清红花和绿叶,个性和共性,绿叶逻辑单独出来成为额外方法,使主干代码更加清晰;共性逻辑抽取成为共性方法,便于复用和维护。
及时清理不再使用的代码段或配置信息。对于垃圾代码或过时配置,坚决清理干净,避免程序过度臃肿,代码冗余。如果是暂时注释,请在上方使用 /// 标记说明。
内部的实现类用Impl的后缀与接口区别:对于Service和DAO类,基于SOA的理念,暴露出来的服务一定是接口,内部的实现类用Impl的后缀与接口区别。
循环体内,字符串的联接方式:循环体内,字符串的联接方式,使用StringBuilder的append方法进行扩展。 说明:反编译出的字节码文件显示每次循环都会new出一个StringBuilder对象,然后进行append操作,最后通过toString方法返回String对象,造成内存资源浪费。
基本数据类型与包装数据类型的使用标准
- 所有的POJO类属性必须使用包装数据类型。
- RPC方法的返回值和参数必须使用包装数据类型。
- 所有的局部变量推荐使用基本数据类型
常量命名标准:常量命名应该全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
杜绝完全不规范的缩写
- 杜绝完全不规范的缩写,避免望文不知义。
- 为了达到代码自解释的目标,任何自定义编程元素在命名时,使用尽量完整的单词组合来表达。
- 类名应该是个名词或名词词组的名字,如Customer、WikiPage、 Account、AddressParser等。
- 变量名应该是名词,如stockNumber 、username等。
- 方法名应该是一个动词或动词词组,如postPayment()、deletePage()、save()等。
所有的抽象方法(包括接口中的方法)必须要用javadoc注释:所有的抽象方法(包括接口中的方法)必须要用javadoc注释、除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。 说明:如有实现和调用注意事项,请一并说明。
方法内注释:方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释使用/* */注释。注意与代码对齐。枚举类型字段必须要有注释:所有的枚举类型字段必须要有注释,说明每个数据项的用途。
# 📝 提交规范
Git 每次提交代码,都要写 Commit message(提交说明) (opens new window),否则就不允许提交。社区有多种 Commit message 的写法规范 (opens new window)。本文介绍Angular 规范 (opens new window),这是目前使用最广的写法,比较合理和系统化,并且有配套的工具。
每次提交,Commit message 都包括三个部分:Header,Body 和 Footer。
<type>(<scope>): <subject>
// 空一行
<body>
// 空一行
<footer>
2
3
4
5
# Header
Header部分只有一行,包括三个字段:type(必需)、scope(可选)和subject(必需)。
type
- feat:新功能(feature)
- fix:修补bug
- docs:文档(documentation)
- style: 格式(不影响代码运行的变动
- refactor:重构(即不是新增功能,也不是修改bug的代码变动)
- test:增加测试
- chore:构建过程或辅助工具的变动
scope:用于说明 commit 影响的范围,比如数据层、控制层、视图层等等,视项目不同而不同。
subject:commit 目的的简短描述,不超过50个字符。
- 以动词开头,使用第一人称现在时,比如change,而不是changed或changes
- 第一个字母小写
- 结尾不加句号(.)
# Body
Body 部分是对本次 commit 的详细描述,可以分成多行。
- 使用第一人称现在时,比如使用change而不是changed或changes。
- 应该说明代码变动的动机,以及与以前行为的对比。
# Footer
footr基本不会用到。
# 📜 日志规范
日志是整个代码开发过程中非常重要的环节,如果日志打的不好,那么遇到的线上bug就没法快速定位,定位不了问题也就没法快速解决问题。直接带来的结果可能包括;客诉更多、资损更大、修复更慢。
- 选择恰当的日志级别
- error:错误日志,指比较严重的错误,对正常业务有影响,需要运维配置监控的;
- warn:警告日志,一般的错误,对业务影响不大,但是需要开发关注;
- info:信息日志,记录排查问题的关键信息,如调用时间、出参入参等等;
- debug:用于开发DEBUG的,关键逻辑里面的运行时数据;
- trace:最详细的信息,一般这些信息只记录到日志文件中。
日志要打印出方法的入参、出参。比如说,方法进来的时候,打印入参。再然后呢,在方法返回的时候,就是打印出参,返回值。入参的话,一般就是userId或者bizSeq这些关键信息。
选择合适的日志格:应当包括这些最基本的信息:如当前时间戳(一般毫秒精确度)、日志级别,线程名字等等
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} %-5level [%thread][%logger{0}] %m%n</pattern> </encoder> </appender>
1
2
3
4
5遇到if...else...等条件时,每个分支首行都尽量打印日志
日志级别比较低时,进行日志开关判断
不能直接使用日志系统(Log4j、Logback)中的 API,而是使用日志框架SLF4J中的API。
import org.slf4j.Logger; import org.slf4j.LoggerFactory; private static final Logger logger = LoggerFactory.getLogger(TianLuoBoy.class);
1
2
3建议使用参数占位{},而不是用+拼接。
logger.info("Processing trade with id: {} and symbol : {} ", id, symbol);
- 建议使用异步的方式来输出日志。 日志最终会输出到文件或者其它输出流中的,IO性能会有要求的。如果异步,就可以显著提升IO性能。 除非有特殊要求,要不然建议使用异步的方式来输出日志。以logback为例吧,要配置异步很简单,使用AsyncAppender就行
<appender name="FILE_ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="ASYNC"/>
</appender>
2
3
核心功能模块,建议打印较完整的日志
禁止在线上环境开启 debug