前言
作为一位高水准的码农,我们的代码应该就像是我们自己的家一样,简洁而优雅。对代码质量有洁癖。之前有写过if多重逻辑的简化,这篇文章是在前几天,优化那一坨长长的if-else逻辑时,顺带记录跟分享的。以便为大家提供一种新的简洁if-else的思路。
业务场景
我们有一个实体类Example,现在业务需要我们对这个实体类中的一部分字段做一些校验,这些校验涉及一些非空校验和特殊的校验。
// Excel导入的实体类
@Data
public class ExampleImport {
// 仓库号【校验规则,导入不能为空】
private String warehouseCode;
// 商品编码【校验规则,导入不能为空】
private String skuCode;
// 货主编码【校验规则,导入不能为空】
private String ownerCode;
// 序列号【校验规则,导入不能为空,且 序列号位数不能超过60位】
private String serialNumber;
// 状态 【校验规则,导入不能为空,且状态只能为"01" "02" "03"】
private String serialState;
}
优化之前
// 这个方法是对我们线上的业务走了一个变形。
// 原方法,是一个Excel导入数据的校验,需要对Excel中先做字段的全量校验,
// 把每一行都校验不通过的重新生成一个导入失败的Excel并展示出来。
public String validateImportData(ExampleImport import) {
if (StringUtils.isEmpty(import.getWarehouseCode())) {
return "仓库号为空";
}
if (StringUtils.isEmpty(import.getSkuCode())) {
return "商品编码为空";
}
if (StringUtils.isEmpty(import.getOwnerCode())) {
return "货主编码为空";
}
if (StringUtils.isEmpty(import.getSerialNumber())) {
return "序列号为空";
}
if (StringUtils.isEmpty(import.getSerialState())) {
return "状态为空";
}
if (import.getSerialNumber().length() > 60) {
return "序列号长度不能超过60位";
}
// 状态校验的字符串逻辑而不是复杂的条件表达式
if (!"01,02,03".contains(import.getSerialState()+",")) {
return import.getSerialState().indexOf(",") > 0 ? "序列号状态非法请检查"
: "序列号状态非法请检查";
}
return "";
}
优化之后
public String validateImportData(ExampleImport import) {
Object[] validateFieldIfNecessary = new Object[]{
import.getWarehouseCode(),
import.getSkuCode(),
import.getOwnerCode(),
import.getSerialNumber(),
import.getSerialState(),
import.getSerialNumber().length() > 60,
// 状态校验的字符串逻辑而不是复杂的条件表达式
!"01,02,03".contains(import.getSerialState()+",") &&
import.getSerialState().indexOf(",") > 0
};
String necessaryField = StringUtils.join(validateFieldIfNecessary, ",");
int index = necessaryField.indexOf("null");
if (index == -1) {
// 校验特殊判断信息
index = necessaryField.indexOf("false");
return FIELD_VALIDATED_MSG.get(index) == null ? StringUtils.EMPTY : FIELD_VALIDATED_MSG.get(index);
}
// 获取不通过校验信息
return FIELD_VALIDATED_MSG.get(index);
}
// 校验信息的注册[这里可以换成枚举类]:基于表驱动的方式简化if-else
@PostConstructor
private void registerValidatedMsg() {
FIELD_VALIDATED_MSG.put(0, "仓库号为空");
FIELD_VALIDATED_MSG.put(1, "商品编码为空");
FIELD_VALIDATED_MSG.put(2, "货主编码为空");
FIELD_VALIDATED_MSG.put(3, "序列号为空");
FIELD_VALIDATED_MSG.put(4, "状态为空");
FIELD_VALIDATED_MSG.put(5, "序列号长度不能超过60位");
FIELD_VALIDATED_MSG.put(6, "序列号状态非法请检查");
}
范式总结
写这篇文章的目的是,想给大家提供一个新的思路来减少代码中的if逻辑。这里,我想给大家介绍的是,对于if的非空校验的判断,我们可以将多个字段的校验合并成String字符串,并利用分隔符进行划分字段。此时,需求就转化成对String字符串的基本方法的使用。重要的事情说三遍,对于一些特殊场景,我们会经常用if逻辑。这些if逻辑中有很多,我们可以细思考的进行,比如利用集合中的方法或者String字符串的indexOf方法等。
其次,if条件内的复杂表达式,我们可以进行转换,就比如序列号状态的非法检查。这种取巧的代码,有一个隐患点就是,对于客户端输入,我们需要做特殊处理。比如我上述例子中的import.getSerialState()+","。因为,我们是将复杂的条件表达式进行了String字符串的拼装,并使用了分隔符。切记切记切记。