验证逻辑最佳做法和设计模式

时间:2019-02-07 10:14:52

标签: java validation design-patterns

我有一个类,对它所包含的函数中的某些参数执行某种(可能是冗余的)验证逻辑。为了演示,我有以下ControllerValidationHelper类:

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 :(得分:1)

ValidationHelper是一种代码气味。您应该对以-ER结尾的任何类表示怀疑。

我将使用验证decorators来实现此目的。您的示例对所有随机无意义的变量有点含糊,所以让我发明自己的变量。

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

需要其他验证吗?添加另一个装饰器。