优化错误调用

优化错误调用

Posted by lijian on September 11, 2019

来源

今天早上在写订单相关的代码

        OrderInfo orderInfo = getByOrderNo(payProcessor.getOrderNo());
        if (ObjectUtil.isNull(orderInfo)) {
            throw new BusinessException(CourseErrorCode.ORDER_NOT_EXIST);
        }
        if (orderInfo.getDelFlag().equals(DelFlagEnum.YES.getValue())) {
            throw new BusinessException(OrderErrorCode.TRANSFER_ORDER_INVALIDATE);
        }
        if (orderInfo.getStatus().equals(DelFlagEnum.YES.getValue())) {
            throw new BusinessException(OrderErrorCode.SIGNUP_CANCEL);
        }
        if (orderInfo.getPurchaseStatus().equals(PayResultEnum.SUCCESS.getValue())) {
            throw new BusinessException(OrderErrorCode.PURCHASE_ID_ALREADY_PAY_SUCC);
        }

不得不说,这个代码看着好看,但是写起来是真的有点恶心,if throw , if throw , if throw

google 封装的 Preconditions 判断就相比优化了很多,但是 google 抛错都是公共的错误,比如 IllegalArgumentException , IllegalStateException 这些错误我们系统的公共错误拦截很可能不是希望获取到的,我们自己的系统更多是 像上面代码中的 BusinessException

代码

/**
 * 在一个方法的开始,通常是大量的参数验证,很可能连续四五个 if(condition){throw new Business....},
 * <p>
 * 类似于 google 的 Preconditions.checkArgument(orgId != null, "orgId is null");,但是 google throw IllegalArgumentException ,我们一般使用 throw Business...
 *
 * @author lijian
 * @date 2019/9/11 上午10:46
 */
@Slf4j
public class ErrorCodeUtils {


    /**
     * 如果 illegal 为 true 则会抛错 errorCode
     *
     * @param illegal
     * @param errorCode
     */
    public static void illegal(Boolean illegal, UniverseErrorCode errorCode) {
        illegal(illegal, errorCode, null);
    }

    /**
     * 如果 illegal 为 true 则会抛错 errorCode ,msg 为 errorCode
     * 简化
     * <pre> {@code
     * if (campusId == null ) {
     *     throw new BusinessException(BaseErrorCode.PARAM_ERROR,"校区ID为空");
     * }}</pre>
     * 为
     * <pre> {@code
     * ErrorCodeUtils.illegal(campusId == null, BaseErrorCode.PARAM_ERROR,"校区ID为空");
     * }</pre>
     *
     * @param illegal
     * @param errorCode
     * @param errorCode
     */
    public static void illegal(Boolean illegal, UniverseErrorCode errorCode, String extMsg) {
        if (illegal != null && illegal && errorCode != null) {
            log.error("illegal illegal {},errorCode {},extMsg {}", illegal, errorCode, extMsg);
            throw new BusinessException(errorCode, extMsg);
        }
    }
}

拓展

我们看一下现在的调用 ,由最开始的几行代码优化为一行代码

ErrorCodeUtils.illegal(campusId == null, BaseErrorCode.PARAM_ERROR,"校区ID为空");

在上面的这个调用中,同样有很多是重复代码,我们再次尝试消除这些,我们先看一下我们的错误枚举(简单举例,实际的错误枚举继承,内部枚举等相对复杂但是对本例无用)

public enum OrderErrorCode  {
    
    ORDER_PAY_DOING(6007, "订单支付处理中,请刷新后重试");
    
    private int code;
    private String message;
}

我们现在如果想要验证这个枚举,使用代码

ErrorCodeUtils.illegal(isDoing!=null && isDoing, OrderErrorCode.ORDER_PAY_DOING,"订单号为xxx 的订单正在处理中");

将 OrderErrorCode 继续优化

public enum OrderErrorCode  {
    
    ORDER_PAY_DOING(6007, "订单支付处理中,请刷新后重试");
    
    private int code;
    private String message;
    public void illegal(Boolean illegal,String extMsg){
        if(illegal!=null && illegal){
            throw new BusinessException(this,extMsg);
        }
    }
}

我们现在再次想要验证这个枚举,使用代码

OrderErrorCode.ORDER_PAY_DOING.illegal(isDoing!=null && isDoing,"订单号为xxx 的订单正在处理中");

现在我们使用这个代码,代码不仅仅成为了一行,而且相对上面的再次精简

再优化

我们可能有这种需求,

if(condition){
    log.info("this is error and params is {}",params);
    throw new .....;
}

新建回调函数


/**
 * @author lijian
 * @date 2019/10/22 下午5:52
 */
@FunctionalInterface
public interface ErrorCallBack {
    /**
     * call when error
     */
    void error();
}

添加处理方法

@Slf4j
public class ErrorCodeUtils {

    
    public static void illegal(Boolean illegal, UniverseErrorCode errorCode) {
        illegal(illegal, errorCode, "");
    }
    
    public static void illegal(Boolean illegal, UniverseErrorCode errorCode, String extMsg) {
        illegal(illegal, errorCode, extMsg, null);
    }

    public static void illegal(Boolean illegal, UniverseErrorCode errorCode, String extMsg, ErrorCallBack callBack) {
        if (illegal != null && illegal && errorCode != null) {
            log.error("illegal illegal {},errorCode {},extMsg {}", illegal, errorCode, extMsg);
            if (Objects.nonNull(callBack)) {
                callBack.error();
            }
            throw new BusinessException(errorCode, extMsg);
        }
    }

    public static void illegal(Boolean illegal, UniverseErrorCode errorCode, ErrorCallBack callBack) {
        illegal(illegal, errorCode, null, callBack);
    }
}

现在的调用方法

ErrorCodeUtils.illegal(isDoing!=null && isDoing,OrderErrorCode.ORDER_PAY_DOING,"订单正在处理中",()->log.warn("order is processoring ... orderNo {}",orderNo));