暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

和读者探讨写代码用异常还是错误码哪个好

安琪拉的博客 2021-12-20
389

昨天写了关于写代码的一点心得之后,大家对于第七条有一些争议,技术群里也有关于这个问题的探讨,今天就来聊下这个问题。

我们今天来看下这个问题,比如我现在写一段代码,示例是对用户的支付请求做处理:

如果是按照错误码的方式处理,我们来看下代码应该写:

public CommonResult handlePayment(PayRequest request) {
  //1. 校验
  ErrorCodeEnum errorCodeEnum = validateUserInfo();
  if (Objects.notNull(errorCodeEnum)) {
    printWarnLog("***", errorCodeEnum);
    return Result.buildErrorResult(errorCodeEnum);
  }
  //2. 获取指定支付类型处理器
  PayTypeEnum payTypeEnum = PayTypeEnum.getPayType(request.getPayCode());
  PayHandle payHandle = PayFactory.getHandle(payTypeEnum);
  if (null == payHandle) {
    printWarnLog("***", errorCodeEnum);
    return Result.buildErrorResult(ErrorCodeEnum.NO_VALID_PAY_TYPE);
  }
  //3. 执行支付
  PayContext payContext = assemblePayContext(request);
  PayResult payResult = payHandle.doHandle(payContext);
  if (payResult == null) {
    return Result.buildErrorResult(ErrorCodeEnum.***);
  }
  if (!payResult.isSuccess()) {
    return Result.buildErrorResult(ErrorCodeEnum.***);
  }
  //4. 转化结果
  CommonResult commonResult = ResultBuilder.convertFrom(payResult);
  return commonResult;
}

复制

大家可以看到代码的业务逻辑中充斥着校验、结果判断,一旦不符合预期通过错误码形式返回,这种形式的代码会让代码的阅读不通畅,看代码的人看一段中间态的业务逻辑,接着看这段业务逻辑的校验判断,实际上好的方式是直接在具体方法中直接抛出异常,我们看下。

public CommonResult service(HttpServletRequest request, HttpServletResponse response) {
  CommonResult result = CommonResult.initResult();
  try {
     PayRequest payRequest = convertToPayResult(request);
     result = handlePayment(payRequest);
   } catch(Throwable ex) {
     //集中异常处理
     LogUtils.printErrorLog(method, msg, ex);
     result = CommonResult.errorResult(ex);
   } finally {
     LogUtils.printInfoLog(method, status, time, info);
   }
  return result;
}

//只有主要的业务逻辑
public CommonResult handlePayment(PayRequest request) {
  //1. 校验
  validateUserInfo();
  
  //2. 获取指定支付类型处理器
  PayTypeEnum payTypeEnum = PayTypeEnum.getPayType(request.getPayCode());
  PayHandle payHandle = PayFactory.getHandle(payTypeEnum);
  
  //3. 执行支付
  PayContext payContext = assemblePayContext(request);
  PayResult payResult = payHandle.doHandle(payContext);
  
  //4. 转化结果
  return ResultBuilder.convertFrom(payResult);
}

//校验逻辑直接丢异常
private void validateUserInfo() {
   UserInfo userInfo = ThreadLocalUtils.getUserInfoFromSession();
   if (illegalOf(userInfo)) {
      throw new IllegalArgumentException("userInfo");
   }
}

private boolean illegalOf(UserInfo userInfo) {
  // doCheck
}

class PayFactory {
   PayHandle getHandle(PayTypeEnum payTypeEnum) {
     if (null = payTypeEnum) {
       throw new NullPointerException("payTypeEnum");
     }
     PayHandle payHandle = payHandleMap.get(payTypeEnum.getCode());
     if (null = payHandle) {
       throw new XXXBizException();
     }
     return payHandle;
   }
}

复制

本质上来说异常只是把复杂性留在更低抽象层次,因为我们日常阅读代码最多的还是在高抽象层。

有读者可能会说异常比返回错误码更消耗性能,但是实际上我们的应用程序大部分时候是性能过剩的,而可阅读性和可维护性欠缺的,如果程序需要在这个地方做性能优化,那证明真的应该找老板扩容了。

    昨天的文章:

    最朴素的道理:程序员的核心能力是写好代码的能力

    

文章转载自安琪拉的博客,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论