簡體   English   中英

重構業務邏輯驗證

[英]Refactoring business logic validation

我正在嘗試重構此代碼

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);
    }
}

我讀了這篇文章業務邏輯驗證模式和建議

我想為我的實體和實體字段構建通用驗證器,我寫了這個

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);
}

和Validator類

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)

我會寫類似:

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

在您參考的鏈接中,建議使用策略設計模式回答可接受的問題,然后給出界面和實現的示例。 在您的情況下,您將使用至少一個方法validate()創建一個新的接口ValidationRule,然后創建每個在該接口上實現的具體類(NotNullValidationRule,NotEmptyValidationRule,AlreadyExistValidationRule)。

我找到了這個解決方案:

我創建一個接口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();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM