代码整洁实践案例:针对DTO若干字段进行非空校验的优雅写法

CR时,看到了如下代码片段。项目中出现多处类似的写法,本文只取其中一处作为案例来分析。

private boolean checkVehicleConditionValue(OrderDTO orderDTO) {
    if (StringUtils.isNotBlank(orderDTO.getOrderNumber()) || StringUtils.isNotBlank(orderDTO.getOwnerCellPhone())
            || StringUtils.isNotBlank(orderDTO.getCellPhone()) || StringUtils.isNotBlank(orderDTO.getFullNameList())
            || StringUtils.isNotBlank(orderDTO.getAccountPhoneNumber()) || StringUtils.isNotBlank(orderDTO.getSuperId())
            || StringUtils.isNotBlank(orderDTO.getDeliveryAgentName()) || StringUtils.isNotBlank(orderDTO.getOwnerIdentityNo())
            || StringUtils.isNotBlank(orderDTO.getStartActualDeliveryTime()) || StringUtils.isNotBlank(orderDTO.getEndActualDeliveryTime())
            || StringUtils.isNotBlank(orderDTO.getSalesBelongedStoreName()) || StringUtils.isNotBlank(orderDTO.getStoreAgentName())
            || StringUtils.isNotBlank(orderDTO.getStartBlindLockTime()) || StringUtils.isNotBlank(orderDTO.getEndBlindLockTime())
            || StringUtils.isNotBlank(orderDTO.getStartCompletedTime()) || StringUtils.isNotBlank(orderDTO.getEndCompletedTime())
            || StringUtils.isNotBlank(orderDTO.getExperienceCenter()) || StringUtils.isNotBlank(orderDTO.getOwnerFullName())
            || StringUtils.isNotBlank(orderDTO.getStartOrderTime()) || StringUtils.isNotBlank(orderDTO.getEndOrderTime())
            || StringUtils.isNotBlank(orderDTO.getStartLockTime()) || StringUtils.isNotBlank(orderDTO.getEndLockTime())
            || StringUtils.isNotBlank(orderDTO.getIsBlindLock()) || StringUtils.isNotBlank(orderDTO.getRefundAmount())
            || StringUtils.isNotBlank(orderDTO.getHoldStatus())
    ) {
        return true;
    }
    if (!CollectionUtils.isEmpty(orderDTO.getOrderStatusList()) || !CollectionUtils.isEmpty(orderDTO.getStoreNameList())
            || !CollectionUtils.isEmpty(orderDTO.getChannelList()) || !CollectionUtils.isEmpty(orderDTO.getSalesModeList())
            || !CollectionUtils.isEmpty(orderDTO.getInvoiceCenterNameList()) || !CollectionUtils.isEmpty(orderDTO.getDeliveryCenterNameList())
            || !CollectionUtils.isEmpty(orderDTO.getFinalPaymentWayList()) || !CollectionUtils.isEmpty(orderDTO.getHoldOrderNumbers())
            || !CollectionUtils.isEmpty(orderDTO.getLicenseProvinceList()) || !CollectionUtils.isEmpty(orderDTO.getLicenseCityList())
            || !CollectionUtils.isEmpty(orderDTO.getWebOrderTypeList()) || !CollectionUtils.isEmpty(orderDTO.getPaymentTypeList())
            || !CollectionUtils.isEmpty(orderDTO.getProps()) || !CollectionUtils.isEmpty(orderDTO.getEntrustTypeList())
            || !CollectionUtils.isEmpty(orderDTO.getInvoiceStatusList())
    ) {
        return true;
    }
    return false;
}

如上代码,其主要功能就是对DTO的若干字段进行简单的非空校验。很明显,这样的代码非常不优雅。

这段代码可以通过多种方式来优化,使其更加优雅和可读性更强。建议如下:

  1. 使用Stream API:Java 8引入的Stream API可以用来简化集合操作,使代码更简洁。
  2. 提取方法:将长逻辑拆分为更小的方法,每个方法执行单一职责,这样不仅提高了代码的可读性,也便于后续的维护和测试。
  3. 利用Optional:对于可能为null的字段,使用Optional可以避免显式检查null,同时使意图更清晰。
  4. 减少重复代码:如果有类似的条件判断,尝试抽象出共用的逻辑。

基于以上原则,可以这样重构代码:

private boolean checkVehicleConditionValue(OrderDTO orderDTO) {
    return hasNonBlankStringFields(orderDTO)
           || hasNonEmptyCollections(orderDTO);
}

private boolean hasNonBlankStringFields(OrderDTO orderDTO) {
    return Stream.of(
        orderDTO.getOrderNumber(), 
        orderDTO.getOwnerCellPhone(), 
        // ... 其他字符串字段 ...
        orderDTO.getHoldStatus()
    ).anyMatch(StringUtils::isNotBlank);
}

private boolean hasNonEmptyCollections(OrderDTO orderDTO) {
    return Stream.of(
        orderDTO.getOrderStatusList(), 
        orderDTO.getStoreNameList(), 
        // ... 其他集合字段 ...
        orderDTO.getInvoiceStatusList()
    ).anyMatch(CollectionUtils::isNotEmpty);
}

完毕!