目录
一、编程规约
(一) 命名规范
代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。 反例:_name / __name / $name / name_ / name$ / name__ 。
禁止使用拼音和英文混合。反例:DaZhePromotion [打折] / getPingfenByName() [评分] 。
类名使用大驼峰式命名法;方法名、参数名、成员变量、局部变量都统一使用小驼峰式命名法。
常量命名全部大写,单词间用下划线隔开;例:MAX_STOCK_COUNT / CACHE_EXPIRED_TIME 。
类型与中括号紧挨相连来表示数组。 例:定义整形数组 int[] arrayDemo。
boolean类型变量,不要以is开头,避免部分序列化框架出错。反例:boolean isExists。
杜绝完全不规范的缩写,避免望文不知义。 反例:AbstractClass“缩写”成AbsClass;condition“缩写”成 condi。
对于Service和DAO类,一定是接口,实现需要以Impl的后缀结尾。区别于接口
如:CacheService CacheServiceImpl。
枚举类名带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开。
类接口中属性和方法不要加任何修饰符。
(二) 常量定义
不允许任何魔法值(即未经预先定义的常量)直接出现在代码中。 反例:String key = “id=” + id;
long和Long初始赋值时,必须使用大写,为了避免和数字1搞混。
例:Long a = 2L 反例:Long a = 2l
不要使用一个常量类维护所有常量,尽可能根据功能进行拆分归类,分开维护。便于理解和维护。
(三) 代码格式
如果是大括号内为空,则写成{}即可,大括号中间无需换行和空格;如果是非空代码块则:( 1) 左大括号前不换行,左大括号后换行。 (2) 右大括号前换行。
左括号与后一个字符之间不出现空格,右括号与前一个字符之间不出现空格
例:if (flag == 0)。
if/for/while/switch/do 等保留字与括号之间都必须加空格。
何二目、三目运算符的左右两边都需要加一个空格。
注释的双斜线与注释内容之间有且仅有一个空格。
方法参数在定义和传入时,多个参数逗号后必须加空格。 例:method(“a”, “b”, “c”);
(四) OOP规约
直接使用类名来访问一个类的静态变量或静态方法。
所有的覆写方法,必须加@Override注解,可以准确判断是否覆盖成功。
对外的接口,原则上避免修改,可以增加新接口,过时接口使用@Deprecated注解
Object的 equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。例:"test".equals(object);
所有整型包装类对象之间值的比较,全部使用equals方法比较,使用==进行判断的话会有数值范围的限制。
循环体内字符串拼接,使用StringBuilder的append方法。
构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init方法中。
浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用equals 来判断。
(五) 日期时间
日期格式化时,传入pattern 中表示年份统一使用小写的y。
获取当前毫秒数:System.currentTimeMillis(); 而不是new Date().getTime()。
(六) 集合处理
只要重写equals,就必须重写hashCode。
判断所有集合内部的元素是否为空,使用isEmpty()方法,而不是size()==0的方式。
ArrayList的subList方法结果不可转成ArrayList。(subList返回的是ArrayList的内部类,并不是ArrayList,而且是ArrayList的一个视图,对SubList所有的操作都会反映到ArrayList原列表上。)
使用集合转数组方法,必须使用集合的toArray(T[] array)。
不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator 方式,如果并发操作,需要对Iterator对象加锁。
使用工具类Arrays.asList()将数组转换成集合时,不能使用修改集合相关方法,如:add/remove/clear都将抛出UnsupportedOperationException异常。
(七) 并发处理
获取单例对象需要保证线程安全,其中的方法也要保证线程安全。
线程资源必须通过线程池提供,不允许在应用中自行显式创建线程,避免过多创建线程、减少创建和销毁线程开销。
线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,Executors返回的线程池对象的缺点是可能会创建大量线程或堆积大量请求,导致OOM。
并发情况,多考虑锁的性能损耗。能不用锁就不用锁;能锁区块,就不要锁整个方法;能锁对象就别锁类。
对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁。
如果访问冲突概率不高,推荐使用乐观锁。
HashMap 在容量不够进行resize时由于高并发可能出现死链,导致CPU飙升,在 开发过程中注意规避此风险。
ThreadLocal对象建议使用static修饰
(八) 控制语句
switch块内,每个case要么通过break/return终止,要么注释说明将执行到哪一个case为止;在一个switch必须包含default,就算是空的。
当switch 括号内的变量类型为String并且此变量为外部参数时,必须先进行null 判断。
在 if/else/for/while/do语句中必须使用大括号。
在高并发场景中,避免使用”等于”判断作为中断或退出的条件。 反例:判断剩余奖品数量等于 0 时,终止发放奖品,但因为并发处理错误导致奖品数量瞬间变成了负数, 这样的话,活动无法终止。
(九) 注释规约
类、类属性、类方法的注释必须使用Javadoc规范,使用格式,不得使用 // xxx方式。
所有的抽象方法(包括接口中的方法),必须要用Javadoc注释
所有的类都必须添加创建者和创建日期。
(十) 前后端规约
前后端交互的API,需要明确协议、域名、路径、请求方法、请求内容、状态码、响应体。
前后端数据列表相关的接口返回,如果为空,则返回空数组[]或空集合{}。
服务端发生错误时,返回给前端的响应信息必须包含HTTP状态码,errorCode、 errorMessage、用户提示信息四个部分。
二、异常日志
(一) 错误码
错误码不体现版本号和错误等级信息。
错误码不能直接输出给用户作为提示信息使用。
(二) 异常处理
不要捕获继承自RuntimeException的运行时异常,这类异常需要自行检查规避,如:IndexOutOfBoundsException / NullPointerException。
异常捕获后不要用来做流程控制,条件控制。
捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请将该异常抛给它的调用者。
finally块必须对资源对象、流对象进行关闭,有异常也要做try-catch;不要在finally块中使用return。
(三) 日志规约
不要执行使用日志实现类,而应该使用SLF4J的API接口,使用门面模式,容易做到所有类的日志处理方式统一。
所有日志文件至少保存15天,因为有些异常具备以“周”为频次发生的特点。
避免重复打印日志,浪费磁盘空间,务必在日志配置文件中设置 additivity=false。
日志打印时禁止直接用JSON工具将对象转换成String。
三、单元测试
好的单元测试必须遵守 AIR原则,即具有自动化、独立性、可重复执行的特点。
单元测试是可以重复执行的,不能受到外界环境的影响。
保持单元测试的独立性。为了保证单元测试稳定可靠且便于维护,单元测试用例之间 决不能互相调用,也不能依赖执行的先后次序。
四、安全规约
隶属于用户个人的页面或者功能必须进行权限控制校验。
用户敏感数据禁止直接展示,必须对展示数据进行脱敏。
用户输入的 SQL参数严格使用参数绑定或者 METADATA字段值限定,防止 SQL注入, 禁止字符串拼接 SQL访问数据库。
表单、AJAX提交必须执行 CSRF安全验证。
五、MySQL数据库
(一) 建表规约
表达是与否概念的字段,必须使用is_xxx的方式命名,数据类型是unsigned tinyint (1表示是,0表示否)。
表名字段名必须使用小写字符或数字;禁止出现数字开头,禁止两个下划线之间只有数字。例:aliyun_admin,rdc_config,level3_name。
禁用保留字,如desc、range、match、delayed等。
表名不使用复数名词。
主键索引名为 pk_字段名;唯一索引名为 uk_字段名;普通索引名则为 idx_字段名。 说明:pk_ 即primary key;uk_ 即 unique key;idx_ 即index的简称。
小数类型为decimal,禁止使用float和double。
如果存储的字符串长度几乎相等,使用 char定长字符串类型。
varchar为变长字符串,长度不要超过5000,如果存储长度超过该值,使用text,并独立表出来。
表必备三字段:id, create_time, update_time。
(二) 索引规约
业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引。
超过三个表禁止 join。需要 join的字段,数据类型保持绝对一致;多表关联查询时, 保证被关联的字段需要有索引。
在 varchar字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据 实际文本区分度决定索引长度。
严禁左模糊或者全模糊。
利用覆盖索引来进行查询操作,避免回表。
(三) SQL语句
不要使用count(列名)或count(常量)来替代count(*),count(*)是SQL92定义的标 准统计行数的语法,跟数据库无关,跟NULL和非 NULL无关。
当某一列的值全是NULL时,count(col)的返回结果为0,但 sum(col)的返回结果为 NULL,因此使用sum()时需注意NPE问题。
in操作能避免则避免,若实在避免不了,需要仔细评估 in后边的集合元素数量,控 制在1000个之内。
(四) ORM映射
在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明。
POJO类的布尔属性不能加is,而数据库字段必须加is_,要求在resultMap中进行 字段与属性之间的映射。
sql.xml配置参数使用:#{},#param# 不要使用${} 此种方式容易出现 SQL注入。
更新数据表记录时,必须同时更新记录对应的update_time字段值为当前时间。
六、工程结构
(一) 应用分层
分层领域模型规约:
• DO(Data Object):此对象与数据库表结构一一对应,通过 DAO层向上传输数据源对象。
• DTO(Data Transfer Object):数据传输对象,Service 或Manager 向外传输的对象。
• BO(Business Object):业务对象,可以由Service层输出的封装业务逻辑的对象。
• Query:数据查询对象,各层接收上层的查询请求。注意超过2 个参数的查询封装,禁止使用 Map 类 来传输。
• VO(View Object):显示层对象,通常是 Web 向模板渲染引擎层传输的对象。
(二) 二方库依赖
二方库版本号命名方式:主版本号.次版本号.修订号。
2 .二方库里可以定义枚举类型,参数可以使用枚举类型,但是接口返回值不允许使用枚 举类型或者包含枚举类型的 POJO对象。
依赖于一个二方库群时,必须定义一个统一的版本变量,避免版本号不一致。
禁止在子项目的 pom依赖中出现相同的 GroupId,相同的 ArtifactId,但是不同的 Version。
(三) 服务器
高并发服务器建议调小 TCP协议的 time_wait超时时间。
给JVM环境参数设置-XX:+HeapDumpOnOutOfMemoryError参数,让JVM碰到OOM 场景时输出dump 信息。
七、设计规约
在需求分析阶段,如果与系统交互的User超过一类并且相关的User Case超过5个, 使用用例图来表达更加清晰的结构化需求。
如果某个业务对象的状态超过3个,使用状态图来表达并且明确状态变化的各个触发条件。
来源地址:https://blog.csdn.net/weixin_51360584/article/details/128098109