验证结果实践。布尔值还是计数?

时间:2009-12-15 03:31:35

标签: c#

几年来,我已经编写了一些验证课程,并且总是想知道人们认为处理它们的最佳方式。

我已经看到并完成了以下每一项工作,并对您的知识和原因感到好奇。

场景1,消息计数

class ValidationClass1
{
    public List<string> ValidationMessage { get; set; }

    public void Validate(x)
    {
        // pseudo-code
        if (!rule_logic1)
        {
            ValidationMessage.Add("Error in logic 1");
        }
        if (!rule_logic2)
        {
            ValidationMessage.Add("Error in logic 2");
        }
    }
}

场景2,返回对象或元组

class ValidationClass
{

    public Tuple<bool, List<string>> Validate(x)
    {
        List<string> ValidationMessage = new List<string>();
        bool passed = true;

        // pseudo-code
        if (!rule_logic1)
        {
            ValidationMessage.Add("Error in logic 1");
            passed = false;
        }
        if (!rule_logic2)
        {
            ValidationMessage.Add("Error in logic 2");
            passed = false;
        }

        return new Tuple<bool, List<string>>(passed, ValidationMessage);
    }

}

在场景1中,ValidationMessage列表也可以是返回类型。无论如何,调用代码必须检查列表的count属性以查看数据是否通过。如果它只是一个单数规则,则需要通过string.IsNullOrEmpty(x)检查返回的字符串长度。

在场景2中,自定义对象或元组将是返回类型,以便调用代码必须知道返回的代码并评估布尔属性以查看它是否通过,然后验证消息。

所以,在您看来,您更喜欢哪种方式,或者如果您有不同的偏好,我也很想知道这一点。

由于

5 个答案:

答案 0 :(得分:4)

我使用了Martin Fowler's Notification Pattern的变体来处理验证和相关的验证错误消息。

以下是可能解决“布尔或计数”问题的具体类:

class Notification...
    private IList _errors = new ArrayList();

    public IList Errors {
      get { return _errors; }
      set { _errors = value; }
    }
    public bool HasErrors {
      get {return 0 != Errors.Count;}       
    }

他的模式使用更细粒度的成员来指示是否发生了一般验证失败('HasErrors'返回基于'错误'集合计数的布尔值)以及具体失败的内容('错误'集合,您可以从中获取计数)运行验证的实际“验证”代码是一个单独的方法(可在需要验证的业务/域对象上找到)。

该模式可能有点过时(包括my own previous implementation)但它确实会让您接触到一些替代方案,并且可以为您提供一些建议。

答案 1 :(得分:2)

如果实现IDataErrorInfo接口,则可以自动将验证绑定到控件(Winforms和ASP.NET),而无需任何其他代码。

答案 2 :(得分:1)

乍一看,我会说第一个选项更具可读性, 但是当你想到它时,第二个似乎更合适。

这可能是一个非常主观的问题,但这就是我的想法。

在第一个版本中,消费代码必须执行“计数”,我相信 比简单地检查一个布尔值更耗费资源(尽管差异可能在各方面都可以忽略不计)。

然而,第二个版本确实有一个更“明确”的迹象表明出现了问题。 验证是一个测试,“pass = false”表示测试失败,而在第一个版本中没有这样的指示。

在这两个版本中,消费代码需要知道这一事实 在版本1 - &gt;计数&gt; 0表示失败,版本2传递= true表示失败。

就个人而言,我会像你一样收集验证失败但随后抛出异常并将该列表作为参数传递给该异常。结果,消费代码被迫处理问题。

但我的观点再一次纯粹是主观的。

答案 3 :(得分:1)

为了验证对象,我最近采用了属性的方式,其中验证规则和相关的错误消息被封装在实现IValidationAttribute接口的属性中,并且“验证下”的对象被传递到一个验证器对象,它使用反射来获取'IValidationAttribute'的所有实现并调用其中的验证逻辑。

Validator对象接受一个对象或对象列表,执行验证并返回包含结果和错误的ValidationResult

我不确定这是否会有所帮助,您的需求尚不清楚,但我发现它是对具有属性的对象执行验证的非常快速,清晰和简洁的方法。

答案 4 :(得分:0)

Broken Rules collection无疑是复杂的验证。