高效能团队的Java研发规范(进阶版)
目前大部分团队是使用的阿里巴巴Java开发规范,不过在日常开发中难免遇到覆盖不到的场景,本文在阿里巴巴Java开发规范基础上,补充一些常用的规范,用于提升代码质量及增强代码可读性。
编程规约
1、基础类型及操作
(1)转换
基本类型转换
String类型转数字:使用apache common-lang3包中的工具类NumberUtils,优势:可设置默认值,转换出错时返回默认值
NumberUtils.toInt("1");
拆箱:包装类转化为基本类型的时候,需要判定null,比如:
Integer numObject = param.get(0);
int num = numObject != null ? numObject : 0;
对象类型转换
使用MapStruct工具,转换类后缀Convertor,所有转换操作都在转换类中操作,禁止在业务代码中编写大量set代码。
(2)判断
枚举判定
使用枚举判等,而非枚举对应的数字。因为枚举更直观,方便查看代码及调试,数字容易出错。
判空
各种对象的判空:
//对象判空&非空
Objects.isNull()
Objects.nonNull()//String判空&非空
StringUtils.isEmpty() //可匹配null和空字符串
StringUtils.isNotEmpty()
StringUtils.isBlank() //可匹配null、空字符串、多个空白字符
StringUtils.isNotBlank()//集合判空&非空
CollectionUtils.isEmpty()
CollectionUtils.isNotEmpty()//Map判空&非空
MapUtils.isEmpty()
MapUtils.isNotEmpty()
断言
使用Guava里的Preconditions工具类,比如:
//如果是空则抛异常
Preconditions.checkNotNull()
//通用判断
Preconditions.checkArgument()
2、集合处理
(1)Map快捷操作
推荐:
//如果值不存在则计算
map.computeIfAbsent("key",k-> execValue(k));
//默认值
map.getOrDefault("key", DEFAULT_VALUE)
反例:
//如果值不存在则计算
String v = map.get("key");
if(v == null){v = execValue("key");map.put("key", v);
}
//默认值
map.containsKey("key") ? map.get("key") : DEFAULT_VALUE
(2)创建对象
构造方法或Builder模式,超过3个参数对象创建使用Builder模式
//Java11+:
List.of(1, 2, 3)
Set.of(1, 2, 3)
Map.of("a", 1)//Java8中不可变集合(需引入Guava)
ImmutableList.of(1,2,3)
ImmutableSet.of(1,2,3)
ImmutableMap.of("key","value")
//多值情况
ImmutableMap.builder().put("key", "value").put("key2", "value2").build()//Java8中可变集合(需引入Guava)
Lists.newArrayList(1, 2, 3)
Sets.newHashSet(1, 2, 3)
Maps.newHashMap("key", "value")
反例:
new ArrayList<>(){{add(1);add(2);
}};
(3)集合嵌套
集合里的值如果是基础类型必须加上注释,说明集合里存的是什么,比如:
//返回值: Map(key: 姓名, value: List(商品))
Map<String, List<String>> res;
超过2层集合对象封装必须封装成自定义类:
//推荐
Map<String, List<Node>> res;@Value
public static class Node {/*** 备注说明字段*/String name;/*** 备注说明字段2*/List<Integer> subjectIds;
}//反例
Map<String, List<Pair<String, List<Integer>>>> res;
异常及日志
1、异常
关于异常及错误码的思考,请参考笔者的另一篇文章:错误码设计思考
异常除了抛异常还有一种场景,即:上层发起多个必要调用,某些可能失败,需要上层自行决定处理策略,推荐使用vavr中的Either类,Either使用建议:通常我们使用左值表示异常,而右值表示正常调用后的返回结果,即: Either<Throwable, Data>
2、日志
(1)日志文件
根据日志等级一般分为4个日志文件即可:debug.log、info.log、warn.log、error.log;
如有特殊需求可根据场景单独建文件,比如请求日志:request.log、gc日志:gc.log等。
(2)所有用户日志都要有追踪字段
追踪字段包括:traceId、userId等,推荐使用MDC,常用的日志框架:Log4j、Logback都支持。
(3)日志清理及持久化
本地日志根据磁盘大小,必须设置日志保存天数,否则有硬盘满风险;
分布式环境为了方便查询,需要将日志采集到ES中查询;
重要日志:比如审计日志、B端操作日志需要持久保存,一般是保存到Hive中;
工具篇
1、JSON
推荐:使用Gson或Jackson;
不推荐:Fastjson。Fastjson爆出的漏洞多。
2、对象转换
推荐:MapStruct,根据注解编译成Java代码,没有反射,速度快;行为可预测,可查看编译后的Java代码查看转换逻辑;
不推荐:BeanUtils、Dozer等。需要反射,行为不可预测,需要测试;
不推荐:超过3个字段手动转换;
3、模板代码
推荐:Lombok,减少代码行数,提升开发效率,自动生成Java代码,没有性能损耗;
不推荐:手动生成大量set、get方法;
4、参数校验
推荐:hibernate Validation、spring-boot-starter-validation,可通过注解自动实现参数拦截;
不推荐:每个入口(比如Controller)都copy大量重复的校验逻辑;
5、缓存
推荐:Spring Cache,通过注解控制缓存逻辑,适合常用的加缓存场景。
设计篇
1、正向语义
正向语义的好处在于使代码容易理解。 比如:if(judge()){…},很容易理解,即:判定成功则执行代码块。
相反,如果是负向语义,思维还要转换一下,一般用于方法前置的参数校验。
正向语义的应用场景有:
- 方法定义:方法名推荐:canPass、checkParam,返回true代表成功。 不推荐:比如isInvalidParam返回true代表失败,增加理解成本;
- Lambda表达式:filter 操作符中返回true是可以通过的元素;
- if和三目运算符:condition ? doSomething() : doSomething2() , 条件判定后紧跟的是判定成功后执行的操作。
反例:
if (!judge()) {doSomething2()
} else {doSomething()
}
2、防御式编程
(1)外部数据校验
外部传过来数据都需要校验,一般分为两类:
- 数据流入:用户Http请求、RPC请求、MQ消费者等
- 数据依赖:依赖的第三方RPC、数据库等
如果是数据流入,一定要首先校验数据合法性再往下执行,推荐hibernate Validation这类工具,可以很方便的做数据校验
数据是数据依赖,一定要考虑各种网络、限流、背压等场景,做好熔断、降级保障。推荐建立防腐层,将第三方的限界上下文语义转换为当前上下文语义,避免理解上的歧义;
(2)Null处理
对于强依赖,没有返回值不行(比如查询数据库):直接抛异常;
需要反馈给上层处理:
(1)可能返回null的场景:使用Optional;
(2)上层需要感知信息异常信息:使用vavr中的Either;
可降级:
(1)返回值是默认值:集合类返回,数字返回0或-1,字符串返回空字符串,其他场景自定义
集合默认值:
Collections.emptyList() //空List
Collections.emptySet() //空Set
Collections.emptyMap() //空Map
总结
本文总结了Java开发常用的高级规范,暂时想到这么多,对文章中观点感兴趣,欢迎留言或加微信交流。
作者博客链接:Java研发规范(进阶版)
作者简介:木小丰,美团Java技术专家,专注分享软件研发实践、架构思考。欢迎关注公共号:Java研发
更多精彩文章:
错误码设计思考
Java线程池进阶
从MVC到DDD的架构演进
平台化建设思路浅谈
构建可回滚的应用及上线checklist实践
高效能团队的Java研发规范(进阶版)相关推荐
- 营销管理手册_麦肯锡内部培训手册,揭秘高效能团队打造的秘密,附6个案例...
无论是一个创业型公司还是一个体系发展成熟的公司而言,其高效能核心团队对于组织发展的重要性意义是不言而喻的,如何打造一个高效能的核心团队就成为必然要求. 麦肯锡内部培训手册 很多朋友都遇到了团队人才流失 ...
- 学习笔记 | 高效能团队打造
推荐以下几本书作为理论知识的相互印证参考,高效能不只是对于中高层的领导有用,对于每一个打工人的思考与行为方式都有着很好的指导意义.当你了解了如何做领导时,那么如何做一个合格的员工就比较简单了 < ...
- 支持软件快速交付的高效能团队组织架构模式
目录: 一.团队即交付 二.流式设计团队拓扑&改进团队交互来促进创新和快速交付 三.应用实践和持续改进,保持上升趋势 一.团队即交付 1.高效能交付团队的特征和问题 增强:包括但不限于以下示例 ...
- 《高效能团队模式》读书笔记2
如果我们将团队类型的数量缩减为四类基本团队拓扑,这个问题就迎刃而解了. · 流动式团队 · 赋能团队 · 复杂子系统团队 · 平台团队 只要使用得当,这四类团队拓扑能够满足构建和运行现代软件系统的需要 ...
- 打造高效能团队之测试能力提升
测试技术能力提升这件事情每个团队每年都在做,但真正效果如何不得而知.在2018年底到2019年初恰逢组织架构调整,我们人手严重不足,最近又不得不重新思考如何做好技术能力提升这件事情.通过梳理基本形成初 ...
- 《高效能团队模式》读书笔记1
在1988年,心理学家John Sweller将认知负荷定义为"工作记忆中使用的脑力劳动 总量".Sweller定义了三种不同的认知负荷. · 固有认知负荷,与问题领域的基本任务相 ...
- Java学习记录:Java飞机大战进阶版(敌人有子弹、有生命、有boss、有声音、还有大招一键清屏)
Java飞机大战 序言 一.项目需求分析 二.各个对象类的设计 加载图片类Images 抽象类FlyingObject 天空类Sky 小敌机类Airplane 大敌机类BigAirplane 侦察机类 ...
- Java研发团队高效能规范
目前大部分团队是使用的阿里巴巴Java开发规范,不过在日常开发中难免遇到覆盖不到的场景,本文在阿里巴巴Java开发规范基础上,补充一些常用的规范,用于提升代码质量及增强代码可读性. 编程规约 1.基础 ...
- 打造高效能研发团队的 5 个关键步骤
在互联网软件企业,今年是一个大家都在非常努力降本增效的年份,包括且不限于人员优化.人员结构优化.技术成本优化,提高人效,提升研发效能等等. 这篇文章我们从研发效能出发,尝试梳理一下打造高效能研发团队的 ...
最新文章
- 谈“云”色变?近80%企业曾遭受数据泄露
- 从源码分析DEARGUI之add_text_point
- Sql Server'不允许保存更改'错误►防止保存需要重新创建表的更改
- No Authorization to generate extension field
- linux c之fdopen(int fd, const char *type)使用总结
- ios 图片添加阴影
- scala编程第16章学习笔记(3)——List类的高阶方法
- 《编写可维护的JavaScript》——2.2 多行注释
- 6. Browser 对象 - Screen 对象(2)
- Atitit.sql where条件表达式的原理 attilax概括
- phpwind测试实战之phpwind安装(三)
- 瑞星搜狐畅游合作 “云安全”首次嵌入网游客户端
- 5101是多大的电阻_电阻尺寸对照表
- CentOS7.6重装系统步骤
- 【Vue轮播插件】常用的vue轮播插件整理
- python: npy数据写入excel文件
- 解决vscode下载很慢
- next_permutation函数与perv_permutation函数
- IT十年人生过客-二十七-艰难
- Python可视化常用方法和常见问题解决方案