Лучшие практики логики валидации и шаблоны проектирования - PullRequest
0 голосов
/ 07 февраля 2019

У меня есть класс, который выполняет некоторую (потенциально избыточную) логику проверки некоторого числа аргументов в функциях, которые он содержит.Для демонстрации у меня есть следующие классы Controller и ValidationHelper:

class ValidationHelper {
    void validateA(int a, String b) { /*...*/ }

    void validateB(int c, double d, String e) { /*...*/ }

    void validateC(int f) { /*...*/ }
}

class Controller {
    private ValidationHelper helper;

    void foo(int a, String b, int f) {
        this.helper.validateA(a, b);
        this.helper.validateC(f);
        // .. Rest of foo
    }

    void bar(int a, String b, int c, double d, String e) {
        this.helper.validateA(a, b);
        this.helper.validateB(c, d, e);
        // .. Rest of bar
    }
}

Мне интересно, есть ли способ улучшить эту архитектуру проверки, чтобы любое добавление в логику проверки не было бы такимнавязчиво, как текущая реализация, и валидация стала намного чище?Если это не достижимо, будут ли у вас какие-либо предложения, если все функции будут иметь одинаковые операторы проверки?(например, foo() и bar(), содержащие ТОЛЬКО this.helper.validateA(a,b)):

class Controller {
    void foo(int a, String b, int f) {
        this.helper.validateA(a, b);
        // .. Rest of foo
    }

    void bar(int a, String b, int c, double d, String e) {
        this.helper.validateA(a, b);
        // .. Rest of bar
    }
}

1 Ответ

0 голосов
/ 07 февраля 2019

ValidationHelper - это кодовый запах.Вы должны скептически относиться к любому классу, оканчивающемуся на -ER.

Я бы реализовал это с использованием проверяющих декораторов .Ваш пример немного расплывчатый со всеми случайными бессмысленными переменными, поэтому позвольте мне изобрести свою собственную.

interface CoffeeMachine
{
    Coffee brew(Volume water, Volume milk);
}

class DarkRoastCoffeeMachine implements CoffeeMachine
{
    public Coffee brew(Volume water, Volume milk) {
         return new Coffee(Roast.DARK, water, milk);
    }
}

Но что, если мы хотим применить некоторые ограничения?Допустим, должно быть хоть какое-то количество воды - мы не можем сделать кофе без воды.

class WaterEnforcingCoffeeMachine implements CoffeeMachine
{
    private CoffeeMachine delegate;

    public WaterEnforcingCoffeeMachine(CoffeeMachine delegate) {
         this.delegate = delegate;
    }

    public Coffee brew(Volume water, Volume milk) {
         if (water.millilitres() < 50) {
              throw new IllegalArgumentException("Must use more than 50ml of water");
         }
         return delegate.brew(water, milk);
    }
}

Затем вы можете составить их следующим образом:

CoffeeMachine coffeeMachine = new WaterEnforcingCoffeeMachine(
    new DarkRoastCoffeeMachine()
);

Нужна дополнительная проверка?Добавьте еще один декоратор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...