今天是孤尽T31训练营的第12天,总结编码规约的知识
《Java开发手册——黄山版》预计于2021年12月发布
编码规约
熵增定律:没有外力干预有序干预,任何系统都会向混乱无序的方向发展
现代软件时多人协作的产物,协作就是生产力,代码的大部分时间是在维护状态的无形协作
代码不规范导致代码生产力损耗
帕金森琐碎定理
编码规约存在的意义
减少代码维护成本
改善可读性
提高团队开发的合作效率
锻炼出更加严谨的思维
身心愉快
代码格式与命名风格
代码风格:简单清爽是一种追求
命名风格与代码格式的两个要求
命名体现代码元素特征
- 抽象类命名使用Abstract或Base开头
- 异常类命名使用Exception结尾
- 测试类命名以它要测试的类名开始,以Test结尾
- 类型与中括号紧挨相连来定义数组
- 枚举类名带上Enum后缀,枚举成员名称需要全大写,单词用下划线隔开
命名最好望文知义
- 某些不规范的缩写或导致理解成本增加
- 主流的编程语言基本上以英语为基础,此处望文知义,此处的文指的是英文,不要出现拼音
包、抽象类、接口与实现类命名规约
按照规约设计,做到层次分明,见名知义
client、config、dao、service、impl、filter、controller…
代码设计与规约
缩进规范,层次清晰
常量定义设计与规约
不允许任何魔法值(即未经预先定义的常量)直接出现在代码中
统一常量一定是需要统一的管理,统一的维护,统一的使用
【推荐】常量的复用层次有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包内共享常量、类内共享常量
跨应用共享常量:放置在SDK中
应用内共享常量:放置在一方库中
子工程内共享常量:即再当前工程的constant下
包内共享常量:放在当前包下单独的constant目录下
类内共享常量:直接在类内部private static final
常量命名应该全部大写,单词间用下划线分隔开,力求语义表达清楚,不要嫌名字长
最大库存数量命名: MAX_STOCK_COUNT
缓存失效时间命名: CACHE_EXPIRED_TIME
用户注册错误:USER_REGISTER_ERROR
注释规约
注释作用
增加代码可读性
使程序条理清晰
方便后期代码维护
方便程序员间的沟通交流
生成帮助文档
警示作用,防止踩坑
通俗做法
附加说明
- 附加说明:业务细节规则
- 附加说明:声明是架构上的决定
- 附加说明:声明时存储或中间件调用方式决定
部分与整体
- 部分与整体:某一部分在哪里
- 部分与整体:整体是做什么的
- 部分与整体:使用的部分是什么
风险提示
- 风险提示:可以使用,注意例外情况
- 风险提示:临时写法,请避开使用。
- 风险提示:魔法值,解释含义
考验文本能力、理解能力、架构能力
无参的一目了然的方法不用写注释
前后端设计规约
接口名称与风格
空集合返回空数组[]或空集合{}
JSON组装格式,纵向组装还是横向组装
错误信息与用户提示切忌混合
【强制】前后端数据列表相关的接口返回,如果为空,则返回空数组[]或空集合{}。
说明:此条约定有利于数据层面上的协作更加高效,减少前端很多琐碎的 null 判断。
前后端交互的API,需要明确协议、域名、路径、请求方法、请求内容、状态码、响应体
errorMessage userTips可以映射
系统错误跟用户提示相映射,不要将系统错误直接抛给用户
Java与JS对数字类型变量处理方式不同。若数字太大或者有精度要求,最好使用String类型
科学计数法的作用
表示极大数、极小数、浮点数的表示范围
Float:比特数为32,有效数字为7位(⼗进制),数值范围为 -3.4E+38 和 3.4E+38
Double:⽐特数为64,有效数字为16(⼗进制),数值范围为-1.7E-308和1.7E+308
浮点数格式
单精度浮点数
符号位 1位
指数 8位,是为阶码
有效数字 23位,是为尾数
数制由十进制转为二进制,需要考虑内存硬件设备的实现方式
规格化表示存有差异
1、规格化
2、尾数部分转为二进制
3、尾数截断,转为十进制
4、计算结果
JS浮点数
JS没有整型,只有Number类型(Double)
后台传递给前端整数值时,必须转换为科学计数法
Double只能表示16位十进制整数,超过就会被截断
最大表示:2^53 = 9007199254740992
为什么后台Long传递给前端Double就不准了呢?
Long传递给前端,不是Double表示精度有问题,Double的表示范围比Long类型还要大,是有效数字被截断
Long转成String,前端不会截断,以String方式处理,前端的框架拿到String,以String的方式计算
为什么Long必须转成科学计数法?
JS采用科学计数表示数字,因为JS是弱类型的语言,所有数字以最大表示范围接收,统一以Number接收,可以接收Double、Long、Integer...
JS只有Double类型,以科学计数法存储
前后端设计规约
详见《Java开发手册——嵩山版》
【强制】对于需要使用超大整数的场景,服务端一律使用 String 字符串类型返回,禁止使用Long 类型。
说明:Java 服务端如果直接返回 Long 整型数据给前端,JS 会自动转换为 Number 类型(注:此类型为双精度浮点数,表示原理与取值范围等同于 Java 中的 Double)。Long 类型能表示的最大值是 2 的 63 次方-1,在取值范围之内,超过 2 的 53 次方 (9007199254740992)的数值转化为 JS 的 Number 时,有些数
值会有精度损失。扩展说明,在 Long 取值范围内,任何 2 的指数次整数都是绝对不会存在精度损失的,所以说精度损失是一个概率问题。若浮点数尾数位与指数位空间不限,则可以精确表示任何整数,但很不幸,双精度浮点数的尾数位只有 52 位。
反例:通常在订单号或交易号大于等于 16 位,大概率会出现前后端单据不一致的情况,比如,“orderId”:
362909601374617692,前端拿到的值却是: 362909601374617660。
【强制】HTTP 请求通过 URL 传递参数时,不能超过 2048 字节。
说明:不同浏览器对于 URL 的最大长度限制略有不同,并且对超出最大长度的处理逻辑也有差异,2048
字节是取所有浏览器的最小值。
反例:某业务将退货的商品 id 列表放在 URL 中作为参数传递,当一次退货商品数量过多时,URL 参数超长,
传递到后端的参数被截断,导致部分商品未能正确退货
对于枚举类型,接口定义中使用int还是String,比如表示移动端系统类型: 1.使用int,0代表Android,1代表iOS,优点是不会拼写错误,缺点是不直观 2.使用String,约定使用“Android”、“iOS”,优点是直观,不容易传错,缺点是容易拼写错误、大小写不一致
数据库中存储,当字符串很固定,拼写常规用String;
字符串很长(超过5个,拼写复杂),用数字,读数据库时进行映射
服务端的字段为int类型,初始时客户端没有这个数据需要传空,下列方式哪种好: 1.定义一个整型值(如-1)表示空 2.传null 3.不传该字段 4.接口使用String类型,传空字符串,服务端处理类型转换
倾向于传null,前端团队需要统一
我觉得存数字,在数据库中好点,省内存,如果是索引字段,在排序的时候也会占优势
不用纠结内存,索引消耗不大
Restful风格的API,URL如何规范设计?HTTP Method统一用GET、POST,还是GET、POST、PUT、DELETE、PATCH?服务端错误码与HTTP Status Code如何映射,服务端收到请求不管执行结果,统一用200,还是具体细分,如何映射?
errorCode跟http状态码无关,200也要查看errorCode,提倡GET、POST、PUT、DELETE、PATCH
前后端制定统一的方式
请求成功,也有可能产生错误
请求后台时,错误时需要拿错误码、错误信息、用户提示,后端需要直接映射好给前端
URL是RPC风格,还是REST资源风格?
REST
如果返回前端的字段的是string类型,字段值为空,返回null还是‘’?
null
f(String s); f(Integer i) >>>> f(null)
编译不通过,继承树自底端向上找,先找到的就调用对应方法,String跟Integer没有继承关系,不知道找那个
f(String s); f(Object o) >>>> f(null)
调用f(String s),继承树自底端向上找,先找到Strin