这下对阿里java这几条规范有更深理解了
背景
阿里java开发规范是阿里巴巴总结多年来的最佳编程实践,其中每一条规范都经过仔细打磨或踩坑而来,目的是为社区提供一份最佳编程规范,提升代码质量,减少bug。
这基本也是java业界都认可的开发规范,我们团队也是以此规范为基础,在结合实际情况,补充完善。最近在团队遇到的几个问题,加深了我对这份开发规范中几个点的理解,下面就一一道来。
日志规约

这条规范说明了,在异常发送记录日志时,要记录案发现场信息和异常堆栈信息,不处理要往上throws,切勿吃掉异常。
堆栈信息比较好理解,就是把整个方法调用链打印出来,方便定位具体是哪个方法出错。而案发现场信息我认为至少要能说明:“谁发生了什么错误”。
例如,哪个uid下单报错了,哪个订单支付失败了,原因是什么。否则满屏打印:“user error”,看到你都无从下手。
在我们这次出现的问题就是有一个feign,调用外部接口报错了,降级打印了不规范日志,导致排查问题花了很多时间。伪代码如下:
@Slf4j
@Component
class MyClientFallbackFactory implements FallbackFactory<MyClient> {
@Override
public MyClient create(Throwable cause) {
return new MyClient() {
@Override
public Result<DataInfoVo> findDataInfo(Long id) {
log.error("findDataInfo error");
return Result.error(SYS_ERROR);
}
};
}
}
发版后错误日志开始告警,打开kibana看到了满屏了:“findDataInfo error”,然后开始一顿盲查。
因为这个接口本次并没有修改,所以猜测是目标服务出问题,上服务器curl接口,发现调用是正常的。
接着猜测是不是熔断器有问题,熔断后没有恢复,但重启服务后,还是继续报错。开始各种排查,arthas跟踪,最后实在没办法了,还是老老实实把异常打印出来,走发版流程。
log.error("{} findDataInfo error", id, cause);
有了异常堆栈信息就很清晰了,原来是返回参数反序列失败了,接口提供方新增一个不兼容的参数导致反序列失败。(这点在下一个规范还会提到)
可见日志打印不清晰给排查问题带来多大的麻烦,记住:日志一定要打印关键信息,异常要打印堆栈。
二方库依赖

上面提到的返回参数反序列化失败就是枚举造成的,原因是这个接口返回新增一个枚举值,这个枚举值原本返回给前端使用的,没想到还有其它服务也调用了它,最终在反序列化时就报错了,找不到“xxx”枚举值。
比如如下接口,你提交一个不认得的黑色BLACK,就会报反序列错误:
enum Color {
GREEN, RED
}
@Data
class Test {
private Color color;
}
@PostMapping(value = "/post/info")
public void info(@NotNull Test test) {
}
curl --location 'localhost/post/info' \
--header 'Content-Type: application/json' \
--data '{
"testEnum": "BLACK"
}'
关于这一点我们看下作者孤尽对它的阐述:

这就是我们出问题的场景,提供方新增了一个枚举值,而使用方没有升级,导致错误。可能有的同学说那通知使用方升级不就可以了?是的,但这出现了依赖问题,如果使用方有成百上千个,你会非常头痛。
那又为什么说不要使用枚举作为返回值,而可以作为输入参数呢?
我的理解是:作为枚举的提供者,不得随意新增/修改内容,或者说修改前要同步到所有枚举使用者,让大家知道,否则使用者就可能因为不认识这个枚举而报错,这是不可接受的。
但反过来,枚举提供者是可以将它作为输入参数的,如果调用者传了一个不存在的值就会报错,这是合理的,因为提供者并没有说支持这个值,调用者正常就不应该传递这个值,所以这种报错是合理的。
ORM映射

以下是规范里的说明:
1)增加查询分析器解析成本。
2)增减字段容易与 resultMap 配置不一致。
3)无用字段增加网络消耗,尤其是 text 类型的字段。
这都很好理解,就不过多说明。
在我们开发中,有的同学为了方便,还是使用了select *,一直以来也风平浪静,运行得好好的,直到有一天对该表加了个字段,代码没更新,报错了~,你没看错,代码没动,加个字段程序就报错了。
报错信息如下:

数组越界!问题可以在本地稳定复现,先把程序跑起来,执行 select * 的sql,再add column给表新增一个字段,再次执行相同的sql,报错。

具体原因是我们程序使用了sharding-jdbc做分表(5.1.2版本),它会在服务启动时,加载字段信息缓存,在查询后做字段匹配,出错就在匹配时。
具体代码位置在:com.mysql.cj.protocol.a.MergingColumnDefinitionFactory#createFromFields

这个缓存是跟数据库链接相关的,只有链接失效时,才会重新加载。主要有两个参数和它相关:
spring.shardingsphere.datasource.master.idle-timeout 默认10min
spring.shardingsphere.datasource.master.max-lifetime 默认30min
默认缓存时间都比较长,你只能赶紧重启服务解决,而如果服务数量非常多,又是一个生产事故。
我在sharding sphere github搜了一圈,没有好的处理方案,相关链接如:
https://github.com/apache/shardingsphere/issues/21728
https://github.com/apache/shardingsphere/issues/22824
大体意思是如果真想这么做,数据库ddl需要通过sharding proxy,它会负责刷新客户端的缓存,但我们使用的是sharding jdbc模式,那只能老老实实遵循规范,不要select * 了。如果select具体字段,那新增的字段也不会被select出来,和缓存的就能对应上。
那么以后面试除了上面规范说到的,把这一点亲身经历也摆出来,应该可以加分吧。
总结
每条开发规范都有其背后的含义,都是经验总结和踩坑教训,对于团队的开发规范我们都要仔细阅读,严格遵守。可以看到上面每个小问题都可能导致不小的生产事故,保持敬畏之心,大概就是这个意思了吧。
这下对阿里java这几条规范有更深理解了的更多相关文章
- Effective.Java第45-55条(规范相关)
45. 明智谨慎地使用Stream 46. 优先考虑流中无副作用的函数 47. 优先使用Collection而不是Stream作为方法的返回类型 48. 谨慎使用流并行 49. 检查参数有效 ...
- 【微信Java开发 --1---番外1】在windows下,使用JAVA执行多条DOS命令+文件夹/路径中有空格怎么解决【目的是实现内容穿透外网】
内网穿透外网的那一篇,参正集1 但是每次都要Ctrl+R 启动DOS窗口,也就是CMD,一句一句的去粘,略显繁琐. 所以将这些任务写在JAVA程序中,启动一次程序就可以实现[内网穿透]的功能,多好啊! ...
- Effective.Java第56-66条(规范相关)
56. 为所有已公开的API元素编写文档注释 要正确地记录API,必须在每个导出的类.接口.构造方法.方法和属性声明之前加上文档注释.如果一个类是可序列化的,还需要记录它的序列化形式. 文档注释在源 ...
- java名词解释,让你更好理解
Java 开发工具包 (JDK) Java开发工具包是Java环境的核心组件,并提供编译.调试和运行一个Java程序所需的所有工具,可执行文件和二进制文件.JDK是一个平台特定的软件,有针对Windo ...
- 点评阿里JAVA手册之编程规约(命名风格、常量定义、代码风格、控制语句、注释规约)
下载原版阿里JAVA开发手册 [阿里巴巴Java开发手册v1.2.0] 本文主要是对照阿里开发手册,注释自己在工作中运用情况. 本文难度系数为一星(★) 码出高效.码出质量. 代码的字里行间流淌的是 ...
- 点评阿里JAVA手册之MySQL数据库 (建表规约、索引规约、SQL语句、ORM映射)
下载原版阿里JAVA开发手册 [阿里巴巴Java开发手册v1.2.0] 本文主要是对照阿里开发手册,注释自己在工作中运用情况. 本文内容:MySQL数据库 (建表规约.索引规约.SQL语句.ORM映 ...
- 点评阿里JAVA手册之异常日志(异常处理 日志规约 )
下载原版阿里JAVA开发手册 [阿里巴巴Java开发手册v1.2.0] 本文主要是对照阿里开发手册,注释自己在工作中运用情况. 本文内容:异常处理 日志规约 本文难度系数为一星(★) 本文为第三篇 ...
- 阿里JAVA开发手册零度的思考理解(一)
转载请注明原创出处,谢谢! 缘由 阿里JAVA开发手册已经发表有很长时间了,值得认真研究思考推广 阿里官方的Java代码规范标准,这份开发手册不仅规范了一些开发细节,也提出了很多工程开发的哲学,值得好 ...
- 阿里JAVA开发手册零度的思考理解(二)
转载请注明原创出处,谢谢! 说在前面 人生的大道上默默地走,就必须要有一盏灯亮着为你引导方向!而这盏灯抑或只是一句话,一句鼓励,一个赞美,一次承认,一次认可,一次相识一次交流-- 上篇文章:阿里JAV ...
- MyEclipse中阿里JAVA代码规范插件(P3C)的安装及使用
JAVA代码规范插件(P3C)是阿里巴巴2017年10月14日在杭州云栖大会上首发的,使之前的阿里巴巴JAVA开发手册正式以插件形式公开走向业界.插件的相关信息及安装包都可以在GitHub(https ...
随机推荐
- 合宙ESP32C3使用PlatformIO开发点亮ST7735S
开发背景 模块使用的合宙的ESP32-C3(经典款) 购买连接 CORE ESP32核心板是基于乐鑫ESP32-C3进行设计的一款核心板,尺寸仅有21mm*51mm,板边采用邮票孔设计,方便开发者在不 ...
- 《最新出炉》系列初窥篇-Python+Playwright自动化测试-11-playwright操作iframe-上篇
1.简介 原估计宏哥这里就不对iframe这个知识点做介绍和讲解了,因为前边的窗口切换就为这种网页处理提供了思路,另一个原因就是虽然iframe很强大,但是现在很少有网站用它了.但是还是有小伙伴或者童 ...
- ubuntu20.4操作指令合集
每个指令前面尽量加上sudo,避免麻烦的权限问题 下载软件:sudo apt install 包名 开启/关闭防火墙(开启/关闭所有端口):sudo ufw enable/disable 防火墙状态: ...
- SAP 传输请求释放及传输过程 SE10 STMS
T-CODE:SE10 STMS 1.传输请求释放 首先通过SE10打开传输组织器. 点击[显示],可以看到待释放的请求. 此时将可修改请求中的请求,点击进行展开,可以看到子请求号和请求属性. 选中请 ...
- Linux-源码安装软件
一.源码安装步骤 源码的安装一般由3个步骤组成:配置(configure).编译(make).安装(make install). 1.配置(configure) Configure是一个可执行脚本,它 ...
- ChatGPT如何生成可视化图表-示例中国近几年出生人口
本教程收集于:AIGC从入门到精通教程汇总 ChatGPT本身不能直接生成可视化图表,但可以配合其他可视化工具或库 方法一:前端可视化开发库 Echarts(地址:Apache ECharts ) 方 ...
- 《SQL与数据库基础》17. InnoDB引擎
目录 InnoDB引擎 逻辑存储结构 架构 内存结构 磁盘结构 后台线程 事务原理 事务基础 redo log undo log MVCC 基本概念 隐式字段 undo log版本链 readView ...
- phpstudy搭建虚拟域名
phpstudy搭建虚拟域名 先使用phpstudy搭建好对应的环境 打开phpstudy控制面板,点击 其他选项菜单,选择 站点域名管理 输入网站虚拟域名,比如我这里DVWA靶场,我就写 www.d ...
- 关于wake on lan远程唤醒主机的问题,长时间关机无法远程唤醒
英特尔在年初发布了几款低功耗的CPU,国内厂商在迷你主机领域纷纷搭载新款CPU,卖的火爆.之前关注过迷你主机这块,于是,我也入手一个迷你主机玩玩,买的是板载N100的迷你主机.使用过程中会涉及到如何远 ...
- day01 java 数据类型
数据类型 1. 数值型:整数类型 byte short int long 浮点类型 double float 基本数据类型:2.字符型:char 3.布尔型:boolean 1. ...