【问题标题】:Refactoring business logic validation重构业务逻辑验证
【发布时间】:2017-08-17 15:01:43
【问题描述】:

我正在尝试重构这段代码

private void validate(Customer customer) {

    List<String> errors = new ArrayList<>();

    if (customer == null) {
        errors.add("Customer must not be null");
    }

    if (customer != null && customer.getName() == null) {
        errors.add("Name must not be null");
    }

    if (customer != null && customer.getName().isEmpty()) {
        errors.add("Name must not be empty");
    }

    if (customer != null) {
        Customer customerFromDb = customerRepository.findByName(customer.getName());
        if (customerFromDb != null) {
            errors.add("Customer already present on db");
        }
    }

    if (!errors.isEmpty()) {
        throw new ValidationException(errors);
    }
}

我读了这篇文章Business logic validation patterns & advices

我想为我的实体和实体的字段构建一个通用验证器,我写了这个

private void validate(Customer customer) {

    List<ValidationRule> validationRules = new ArrayList<>();

    validationRules.add(new NotNullValidationRule(customer));
    validationRules.add(new NotNullValidationRule(customer, Customer::getName));
    validationRules.add(new NotEmptyValidationRule(customer, Customer::getName));
    validationRules.add(new NotExistValidationRule(customer -> customerRepository.findByName(customer.getName())));

    Validator.validate(validationRules);
}

和验证器类

public class Validator {

    public static void validate(List<ValidationRule> validationRules) {
        final List<String> errors = new ArrayList<>();
        for (final ValidationRule rule : validationRules) {
            final Optional<String> error = rule.validate();
            if (error.isPresent()) {
                errors.add(error.get());
            }
        }

        if (!errors.isEmpty()) {
            throw new ValidationException(errors);
        }
    }
}

但我不知道如何实现接口ValidationRule和其他类(NotNullValidationRule、NotEmptyValidationRule、NotExistValidationRule)

【问题讨论】:

  • 你找到答案了吗?

标签: java validation java-8


【解决方案1】:

我会写这样的:

CommonValidations.notNull(errors, customer);
if (customer != null) {
    CommonValidations.notEmpty(errors, customer.getName());
}
customerCustomeBeanValidations.validName(errors, customer.getName());
customerCustomeBeanValidations.notExist(errors, customer.getName());

【讨论】:

    【解决方案2】:

    在您引用的链接中,接受的答案建议使用Strategy 设计模式,然后给出了接口和实现的示例。在您的情况下,您将创建一个新接口 ValidationRule,其中至少有一个方法 validate(),然后您将创建每个在该接口上实现的具体类(NotNullValidationRule、NotEmptyValidationRule、AlreadyExistValidationRule)。

    【讨论】:

      【解决方案3】:

      我找到了这个解决方案:

      我创建了一个接口 ValidationRule

      import java.util.Optional;
      
      public interface ValidationRule {
          Optional<ValidationError> validate();
      }
      

      以及一些实现行为的类

      public class NotNullValidationRule implements ValidationRule {
      
          private Object object;
          private String field;
      
          public NotNullValidationRule(Object object, String field) {
              this.object = object;
              if (field == null || field.isEmpty()) {
                  throw new IllegalArgumentException("field must not be null or emtpy");
              }
              this.field = field;
          }
      
          @Override public Optional<ValidationError> validate() {
      
              if (object == null) {
                  return Optional.empty();
              }
      
              try {
                  Object value = new PropertyDescriptor(field, object.getClass()).getReadMethod().invoke(object);
                  if (value == null) {
                      ValidationError validationError = new ValidationError();
                      validationError.setName(object.getClass().getSimpleName() + "." + field);
                      validationError.setError("Field " + field + " is null");
                      return Optional.of(validationError);
                  }
              }
              catch (Exception e) {
                  throw new IllegalStateException("error during retrieve of field value");
              }
      
              return Optional.empty();
          }
      }
      

      我传递一个方法来调用的另一个地方:

      package it.winetsolutions.winactitime.core.service.validation;
      
      import java.beans.PropertyDescriptor;
      import java.util.Optional;
      import java.util.function.Function;
      
      public class NotExistValidationRule implements ValidationRule {
      
          Object object;
          String field;
          Function<? super String, ? super Object> function;
      
          public NotExistValidationRule(Object object, String field, Function<? super String, ? super Object> function) {
              this.object = object;
              if (field == null || field.isEmpty() || function == null) {
                  throw new IllegalArgumentException("field and function must not be null or emtpy");
              }
              this.field = field;
              this.function = function;
          }
      
          @Override public Optional<ValidationError> validate() {
      
              if (object == null) {
                  return Optional.empty();
              }
      
              try {
                  Object value = new PropertyDescriptor(field, object.getClass()).getReadMethod().invoke(object);
                  Long id = (Long) new PropertyDescriptor("id", object.getClass()).getReadMethod().invoke(object);
                  Object result = function.apply(value == null ? (String) value : ((String) value).trim());
                  if (result != null &&
                      !id.equals((Long) new PropertyDescriptor("id", result.getClass()).getReadMethod().invoke(result))) {
                      ValidationError validationError = new ValidationError();
                      validationError.setName(object.getClass().getSimpleName() + "." + field);
                      validationError.setError("Element with " + field +": " + value + " already exists");
                      return Optional.of(validationError);
                  }
              }
              catch (Exception e) {
                  throw new IllegalStateException("error during retrieve of field value");
              }
      
              return Optional.empty();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多