Commit 4578e297d52339a47460f8f74c37350ab9627d8d
1 parent
8565ecf8
Exists in
master
feat: 添加开发注意事项
Showing
1 changed file
with
207 additions
and
0 deletions
Show diff stats
| ... | ... | @@ -0,0 +1,207 @@ |
| 1 | +## 则一后端开发注意事项 | |
| 2 | + | |
| 3 | +### 数据库 | |
| 4 | + | |
| 5 | +目前数据库1个主库,2个读库,应用服务使用写库以及读库1,报表服务使用读库2 | |
| 6 | + | |
| 7 | +#### 创建表 | |
| 8 | + | |
| 9 | +必须字段 | |
| 10 | + | |
| 11 | +主键: id varchar(36) | |
| 12 | + | |
| 13 | +删除标识: delete_flag tinyint(1) | |
| 14 | + | |
| 15 | +创建时间:create_time datetime | |
| 16 | + | |
| 17 | +创建人:create_user varchar(255) 创建人 | |
| 18 | + | |
| 19 | +修改时间:modify_time datetime 修改时间 | |
| 20 | + | |
| 21 | +修改人: modify_user varchar(255)修改人 | |
| 22 | + | |
| 23 | +一般还需要业务主键、状态、备注等字段 | |
| 24 | + | |
| 25 | +#### 索引 | |
| 26 | + | |
| 27 | +创建表必须加一个主键索引id | |
| 28 | + | |
| 29 | +一般需要加一个业务主键,索引类型为唯一索引,保证数据不能重复添加(例如派车单号,运单号,账单号) | |
| 30 | + | |
| 31 | +where后面查询字段要设置索引 | |
| 32 | + | |
| 33 | +SQL写完一定要在生产环境执行一下,看下执行计划有没有走索引,执行时间一般控制在1-2秒以内 | |
| 34 | + | |
| 35 | +大量数据的查询要控制时间范围,例如运单,派车单一次最多查询3个月的数据据 | |
| 36 | + | |
| 37 | +事务内的查询会走主库 | |
| 38 | + | |
| 39 | +#### 常见生产问题⭐⭐⭐⭐⭐ | |
| 40 | + | |
| 41 | +- 慢SQL导致大量会话阻塞,系统查询慢或者无法查询 | |
| 42 | +- 关联查询或主子查询创建了大数据量临时表,导致数据库临时表空间暴增,数据库无法读写 | |
| 43 | +- 事务中的查询SQL直接走主库,SQL的where条件没加索引,大数据量查询导致了主库的CPU飙高 | |
| 44 | +- 数据更新事务长时间未提交,导致其他事务无法操作,造成数据库死锁 例如开启事务之后http请求超时未响应 | |
| 45 | + | |
| 46 | +### 后台接口 | |
| 47 | + | |
| 48 | +#### 接口设计 | |
| 49 | + | |
| 50 | +##### 命名规范⭐⭐⭐⭐ | |
| 51 | + | |
| 52 | +类名需要使用大驼峰命名法(UpperCamelCase) 风格 | |
| 53 | + | |
| 54 | +方法名、参数名、成员变量、局部变量需要使用小驼峰命名法(lowerCamelCase) | |
| 55 | + | |
| 56 | +常量、枚举名称需要使用蛇形命名法(snake_case),常量以及枚举名称需要全部大写 例如:OUT_INVITE | |
| 57 | + | |
| 58 | +包名统一使用小写,尽量使用单个单词作为包名,各个单词通过"."分隔符连接,并且各个单词必须为单数 | |
| 59 | + | |
| 60 | +POJO类中布尔类型的变量,都不要加is前缀,否则部分框架解析会引起序列化错误 | |
| 61 | + | |
| 62 | +如果模块、接口、类、方法使用了设计模式,在命名时需体现出具体模式 | |
| 63 | + | |
| 64 | +抽象类命名使用Abstract开头 | |
| 65 | + | |
| 66 | +异常类命名使用Exception结尾 | |
| 67 | + | |
| 68 | +测试类命名以它要测试的类的名称开始,以Test结尾 | |
| 69 | + | |
| 70 | +##### 接口定义⭐⭐⭐⭐ | |
| 71 | + | |
| 72 | +单一职责原则(Single Responsibility Principle) | |
| 73 | +开闭原则(Open Closed Principle) | |
| 74 | +里氏替换原则(Liskov Substitution Principle) | |
| 75 | +<u>迪米特法则(Law of Demeter)又叫"最少知道法则"</u> | |
| 76 | +接口隔离原则(Interface Segregation Principle) | |
| 77 | +依赖倒置原则(Dependence Inversion Principle) | |
| 78 | + | |
| 79 | +##### 方法定义⭐⭐⭐⭐ | |
| 80 | + | |
| 81 | +方法名的第一个单词应该是动词,首字母应小写。参数的名字必须和变量的命名规范一致。使用有意义的参数命名。参数尽量简化,不要定义方法中用不到的参数。超过5个则定义成对象类型 | |
| 82 | + | |
| 83 | +注意:方法职责一定要拎清楚 | |
| 84 | + | |
| 85 | +##### 注释⭐⭐⭐ | |
| 86 | + | |
| 87 | +接口方法注释一定要写清楚 | |
| 88 | + | |
| 89 | +#### 缓存⭐⭐⭐ | |
| 90 | + | |
| 91 | +基础数据最好加缓存,减小数据库压力,提高查询效率 | |
| 92 | + | |
| 93 | +#### 事务⭐⭐⭐⭐ | |
| 94 | + | |
| 95 | +增删改方法一定要加事务注解 | |
| 96 | + | |
| 97 | +嵌套事务注意用try catch包住内部事务方法的异常 | |
| 98 | + | |
| 99 | +###### 常见问题⭐⭐⭐⭐⭐ | |
| 100 | + | |
| 101 | +未加事务注解导致数据不一致 | |
| 102 | + | |
| 103 | +```java | |
| 104 | +@Override | |
| 105 | +@Transactional | |
| 106 | +public String createDispatch(CreateDispatchRequestDto createDispatchRequestDto) { | |
| 107 | + waybillService.createWaybill(dispatchCode, waybillCode); | |
| 108 | + dispatchStopOverStationService.createDispatchStation(createDispatchStationRequestDto); | |
| 109 | + dispatchVehicleService.createDispatchVehicle(createDispatchRequestDto); | |
| 110 | + dispatchPriceService.createDispatchPrice(createDispatchRequestDto); | |
| 111 | + dispatchSupplierPriceService.createDispatchSupplierPrice(createDispatchRequestDto); | |
| 112 | + try { | |
| 113 | + //带事务方法 | |
| 114 | + dispatchOperationRecordService.createDispatchOperationRecord(createDispatchRequestDto); | |
| 115 | + } catch (Exception e) { | |
| 116 | + log.error("创建派车单异常!"); | |
| 117 | + } | |
| 118 | +} | |
| 119 | +``` | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | +##### 异常 | |
| 124 | + | |
| 125 | +检查性异常处理一定要打日志 | |
| 126 | + | |
| 127 | +###### 常见问题⭐⭐⭐⭐⭐ | |
| 128 | + | |
| 129 | +直接catch掉异常,异常信息无法定位 | |
| 130 | + | |
| 131 | +```java | |
| 132 | +try { | |
| 133 | + //业务逻辑 | |
| 134 | +} catch (Exception e) { | |
| 135 | + log.error("钉钉审批回调消费异常!"); | |
| 136 | + throw new BusinessException("钉钉审批回调消费异常!"); | |
| 137 | +} | |
| 138 | +``` | |
| 139 | + | |
| 140 | +正确示例 | |
| 141 | + | |
| 142 | +```java | |
| 143 | +try { | |
| 144 | + //业务逻辑 | |
| 145 | +} catch (Exception e) { | |
| 146 | + log.error("钉钉审批回调消费异常!", e); | |
| 147 | + throw new BusinessException("钉钉审批回调消费异常!", e); | |
| 148 | +} | |
| 149 | +``` | |
| 150 | + | |
| 151 | +#### 版本兼容 | |
| 152 | + | |
| 153 | +APP后台开发要注意版本兼容问题,APP前端版本上线后不一定所有用户都能及时更新版本。要保证老版本使用的接口也能做出准确的响应 | |
| 154 | + | |
| 155 | +外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方造成影响。接口过时加@Deprecated注解,并清晰地说明新接口或新服务是什么 | |
| 156 | + | |
| 157 | +###### 常见问题⭐⭐⭐⭐⭐ | |
| 158 | + | |
| 159 | +APP未做版本兼容,导致老版本APP无法正常使用 | |
| 160 | + | |
| 161 | +直接改外部正在调用的接口,导致别的服务不可用 | |
| 162 | + | |
| 163 | +废弃的接口直接抛业务异常 | |
| 164 | + | |
| 165 | +```java | |
| 166 | +@PostMapping("/add") | |
| 167 | +public Response<Void> addDriverVehicleLicense(@RequestBody @Validated DriverVehicleLicenseAddRequestDto driverVehicleLicenseAddRequestDto) { | |
| 168 | + throw new BusinessException("请下载最新APP版本!"); | |
| 169 | +} | |
| 170 | +``` | |
| 171 | + | |
| 172 | +新老版本并行的接口加版本区分 | |
| 173 | + | |
| 174 | +```java | |
| 175 | +/** | |
| 176 | +* 新增 | |
| 177 | +*/ | |
| 178 | +@PostMapping("/add") | |
| 179 | +public Response<Void> addDriverVehicleLicense(@RequestBody @Validated DriverVehicleLicenseDiscernAddRequestDto driverVehicleLicenseAddRequestDto) { | |
| 180 | + driverVehicleLicenseService.addDriverVehicleLicense(driverVehicleLicenseAddRequestDto); | |
| 181 | + return returnSuccess(); | |
| 182 | +} | |
| 183 | + | |
| 184 | +/** | |
| 185 | +* 新增(接口兼容:增加行驶证背面传递到副页字段) | |
| 186 | +*/ | |
| 187 | +@PostMapping("/add/v1") | |
| 188 | +public Response<Void> addDriverVehicleLicenseV1(@RequestBody @Validated DriverVehicleLicenseDiscernAddRequestDto driverVehicleLicenseAddRequestDto) { | |
| 189 | + driverVehicleLicenseService.addDriverVehicleLicenseV1(driverVehicleLicenseAddRequestDto); | |
| 190 | + return returnSuccess(); | |
| 191 | +} | |
| 192 | +``` | |
| 193 | + | |
| 194 | +#### git | |
| 195 | + | |
| 196 | +分支:开发分支,测试分支,上线分支,master | |
| 197 | + | |
| 198 | +开发分支: 开发功能时要创建自己的开发分支 | |
| 199 | +测试分支: 测试环境部署的分支,功能开发完通过单元测试后就可以把代码合并到测试分支进行测试 | |
| 200 | +上线分支: 每周会有一个上线版本,上线之前需要把要上线的代码合并到上线分支 | |
| 201 | +master: 生产环境部署分支 | |
| 202 | + | |
| 203 | +__<font color=#FF000 >push之前一定拉下代码,push时一定要看下是不是自己的代码。如果把不上线的代码push到上线分支,所有人都得重新合代码了,直接影响上线。一定要注意!!!!!</font>__ | |
| 204 | + | |
| 205 | +##### 常见问题⭐⭐⭐⭐⭐ | |
| 206 | + | |
| 207 | +push时把别人不上线的代码push到上线分支 | |
| 0 | 208 | \ No newline at end of file | ... | ... |