•举个栗子:
•Switch语句天生要做N件事情,怎么让函数里的switch语句只做一件事情了?
当我们遵循上面的这些规则去编程的时候,其实我们就是在结构化编程。
不要写大而臃肿的函数,那会让你回头去修改自己代码的时候都会头疼不已。
大函数阅读性差,改一处牵动全身,你需要更多的时间去确认是否会影响到函数里的其他功能。
所以让我们养成一个好习惯,写出让别人称赞的好代码。
1、Controller层不能书写业务逻辑代码,只能书写一些参数判断和Service调用代码。
2、Controller层建议接入Swagger接口生成插件,为API写上良好的注释,方便接口联调。
3、Controller层参数判断建议使用注解方式,因为注解方式代码更整洁,也可以直接抛异常到前端或者调用方,不需要去做业务逻辑的判断和处理。
3.1、注解建议使用spring的注解,对象的校验使用@Validated ,因为这个注解会抛出一个ConstraintViolationException异常,比较好进行全局异常处理。
3.2、Controller层还可以抛出一些统一的业务异常,这个需要自己去定义一个全局的业务异常类,然后通过里面的枚举类型,描述具体的什么业务场景下的什么错误。
4、Controller层接收的业务对象里面都可以使用注解去对字段做一些必填,长度和边界值的校验,比直接写代码校验方便。
5、Controller层建议都返回JSON对象,避免写EL和FreeMarker语法,不方便前后端分离和API抽取。
1、Service层代码主要书写业务逻辑。
2、规范:Service层需要面向接口编程,每个Service都需要编写对应的接口类。
3、规范:Service层只能调用对应的DAO层,不能跨模块调用其他的DAO,如果需要调用,建议在对应的模块Service层做一个封装,然后调用对应的Service接口,而不是DAO的方法。
4、建议:原子Service定义:不调用其他Service的Service;复合Service定义:调用多个Service的Service。建议把Service区分为原子Service和复合Service。
5、规范:Service层的方法里面建议不要出现字符串代码和数字书写,所有的字符串和数字需要定义为常量,字符串定义为常量便于修改,数字定义为常量可读性会很好。
6、建议:第三方接口统一放到一个包下不同的类管理,一系列同一个第三方的接口放在一个类里面,避免在Service代码里面出现重复的调用第三方代码,当第三方修改接口的时候,对应本项目需要修改的地方出现多处可能会有遗漏。如果统一管理就只需要修改一个地方就好,方便管理。
7、建议:Service层代码public方法放在最上面,private方法放在下面,按照调用逻辑,被调用方需要在调用方代码下面。
8、规范:每个Service层都需要有日志输出,输出格式为待定。
9、建议:属性注入放在Service代码最上面,或者自定义的常量放在最上面,二选一,统一一下,然后是方法。
10、建议:比较复杂的方法需要写上注释,代码逻辑比较复杂也需要加上一定的注释。建议使用英文写注释,因为中文和会出现乱码情况。
1、DAO层主要写持久层和数据库交互的逻辑,不能写业务逻辑。
2、DAO层的方法必须抽取为共有方法,尽量不要写专用方法,比如写了一个通过某个字段查询一个对象的方法,其实应该抽象为传递多个条件,动态拼装条件求查询对象,这样就可以避免,再来一个属性过滤,还得在写一个方法去过滤新的属性字段。
3、DAO层尽量不要写SQL语句,除非特殊要求,比如多表关联,hibernate支持就不太好,可以自己写SQL。
4、DAO层的查询,如果数据是有是否有效字段的(默认大多数都需要,除非特殊表),一定要加上有效字段的过滤,最好是能够抽取到共有接口或者方法里面去实现。很多时候都是忘记写该字段的过滤,导致查出一些本不应该显示的数据。抽取成共有方法可以避免每个DAO层都去添加过滤字段,产生很多重复代码。
1、工具类按照不同功能区分成N个类,相似的两个工具类可以合并。不要出现功能类似但是却有两个工具类,有时候不知道使用哪个工具类。
2、工具类里面的方法一定要是公用的,不能出现特殊为某一个接口服务的方法,这样的方法可以在基础工具方法上再封装一层,来处理特殊的逻辑。
3、工具类方法尽量不要修改原有传入的参数,应该通过返回值的方式来返回修改后的内容,不然有时候会出现一些很难定位的问题;还有一种方法就是传递一个参数去接收修改后的内容。常见的做法是在工具方法的参数上加final字段,来限制修改参数内容。
1、所有的Service都必须要有对应的单元测试。
2、Controller层代码也需要写单元测试,和Service层 稍有不同,需要先判断HTTPStatus,然后判断返回值。
3、单元测试需要测试边界值,分支测试等
4、单元测试需要能够重复执行,不能影响其他业务。
1、设计到创建数据库和表的时候需要提交评审
2、区分开DDL和DML语句,每次修改线上数据库的SQL必须评审。
3、维护一份数据库的修改记录。最好加上注释,为什么要修改。
1、针对查询频繁的字段,如果不是可枚举的,区分度很小的字段,都建议建立索引。
2、针对多条件过滤的查询,建议建立多字段的联合索引,不要单独去建立索引,减少不必要的索引。
3、索引命名规范为idx_字段名称【_number】,索引名称建议都以idx开头加上字段名称,联合所以按照索引左匹配规则,从左到右依次写上对应的字段名称。
数据库名称使用下划线连接,千万不要用横线,中划线连接,不然使用数据库名加表名插入数据的时候会报错。
1、字段名称:全部使用小写加下划线的方式命名,每个单词独立,两个单词使用下划线连接,不能两个单词直接连接,单词过长可以使用国际化的简写,如果没有,那就全部书写,不要自己去简写,别人会看不懂。
2、字段类型:boolean类型的一律使用tinyint;
enum类型的也使用tinyint
主键ID一律使用bigint
数字类型的不确定长度的一律使用bigint,只有确定不超过int长度的,使用int
日期类型建议使用DateTime,特殊情况下日期类型可以使用varchar存储
字符串类型使用varchar,名称、标题等字段建议长度为128;人名建议64;description建议512;content文本内容建议2048及以上,建议的都是2的n次方。
3、 尽量冗余一些前端需要显示的字段
一张表里经常会关联其他表的信息,正常都会存一个关联ID,但是页面展示的时候需要的是中文名称,这就会导致需要再去查询对应的关联表,获取名称信息,导致多查询一张表,如果返回的是一个列表,那么和数据库的交互次数和关联的表成正比增加,会导致查询延时高。
特别是一个字段里存了多个关联ID的情况下,显示的时候需要一个一个去查询翻译,很浪费资源,会导致接口延时比较高。
4、多表关联查询
多表关联查询的时候,关联的表较多情况下,千万不要自己通过service调用主表查询,然后根据外键,循环去查询每一个关联表,速度会很慢,建议通过持久层架构去实现多表关联查询,如果支持不太好,可以自定义返回对象通过原生SQL去查询。
5、公共字段定义
公共字段包括 ID,创建时间created_time,更新时间updated_time,创建人,修改人,数据状态字段state,如果是任务类型需要status状态字段。
公共字段定义如下:
字段名称 | java字段类型 | 数据库字段类型 | 备注 |
---|---|---|---|
id | Long | bigint | 主键ID |
created_time | Date | DateTime | 创建时间 |
updated_time | Date | DateTime | 修改时间 |
creator | String/Long | varchar/bigint | 创建人 |
modifier | String/Long | varchar/bigint | 修改人 |
state | boolean | tinyint | 数据状态,是否有效:1有效,0无效 |
status | String/enum | varchar/tinyint | 数据流转状态 |
数据库的第一个字段id,只能作为唯一主键,不能作为有特殊意义的字段。比如,不能作为定义的标签的id,标签id应该是有寓意的,必须单独用一个字段来标识。
所有数据都必须有state字段作为数据状态的标识,用来实现逻辑删除,即该条数据是否有效,1有效,0无效。
所有任务类型的数据状态字段请使用status字段作为任务状态字段。
6、定义一个公共类,实现公共字段,然后继承该类。
@MappedSuperclass
public class BaseModel {
@Id
@GeneratedValue
@Column(name = "id")
private Long id;@Column(name = "creator")
private String creator = "";@Column(name = "modifier")
private String modifier = "";@Column(name = "status")
private String status = "";@Column(name = "state")
private Boolean state = true;@Column(name = "updated_time")
private Date updatedTime;@Column(name = "created_time")
private Date createdTime;
}