验证错误层次结构设计

本文关键字:结构设计 层次 错误 验证 | 更新日期: 2023-09-27 18:26:36

在我们的系统中,我们有一个实体Product,它可能具有各种自定义属性。一组属性可能因产品而异,并且存储在类型为List<Property>的字段中。属性是不同类型的(字符串、int、double),可能具有一些特殊特性,例如,它们可能是多值的,可能是特定范围的值,也可能是给定列表中的值等。属性的值始终包含在字符串字段Value中。

现在,我目前的问题是实现这些属性的验证,我有点纠结于在验证结果的部分表示中应该采取什么方法。我必须满足的要求:-验证的结果将被其他应用层使用,因此生成的API应该清晰且易于使用-每个错误都应该有一个不同的表示-API的用户应该有足够的信息来理解错误细节(例如,对于范围错误,应该向他们提供最小可能值、最大可能值和实际值)

以下是我迄今为止考虑过的方法:

  1. 类层次结构有一个基本抽象类ValidationError,每个特定的错误都会反映在继承的类中。如果error有任何细节,那么相应的类将有必要的字段来存储所有信息。示例:

    public abstract class ValidationError
    {
        // common fields and methods, if any
    }
    public class IncorrectFormatValidationError : ValidationError
    {
        // just empty class, nothing to add here
    }
    public class RangeValidationError : ValidationError
    {
        public object MinValue { get; set; }
        public object MaxValue { get; set; }
    }
    

    这种方法对我来说似乎是多余的,因为实际上有各种各样的空类。此外,使用这样的API似乎并不正确(if (typeof(error) == typeof(RangeValidationError))-胡说八道!)。然而,这是我想到的第一件事。

  2. 错误枚举以及必要时的类层次结构所有错误都用枚举表示。在大多数情况下使用一个类ValidationError,当特定错误需要额外信息时,将创建继承器,基本上与第一种方法相同。示例:

    public enum ValidationErrors
    {
        IncorrectFormat,
        ValueNotWithinRange,
        ...
    }
    public class ValidationError
    {
        public ValidationErrors ErrorType { get; set; } 
        public ValidationError(ValidationErrors type)
        {
            this.ErrorType = type;
            ...
        }
        // common fields and methods, if any
    }
    public class RangeValidationError : ValidationError
    {
        public object MinValue { get; set; }
        public object MaxValue { get; set; }
        public RangeValidationError(object minValue, object maxValue) :
            base(ValidationErrors.ValueNotWithinRange)
        {
            ...
        }
    }
    

    这种方法看起来要好得多,但也有缺点。最大的一个问题是,作为API用户,我们无法保证当我们有ValueNotWithinRange类型的错误时,我们正在处理RangeValidationError类型的类,如果我们没有,我们如何处理它?我想有一些设计性的功能,甚至可以防止这种情况的存在,因为我不是开发API的人。这种方法的另一个问题是,如果大多数错误最终都需要一些额外的信息,我们最终会得到相同的1号蟑螂。

有人对这两种方法有什么想法可以分享,或者建议一种更好的方法吗?如有任何回应,我将不胜感激。提前谢谢。

验证错误层次结构设计

退一步重新思考整个"表示验证错误的多个类"方法可能是个好主意,因为它几乎可以保证您已经有了验证器的层次结构。

任何验证错误都可以完美地指定给:

  1. 未能接受属性值的验证器
  2. 物业名称
  3. 未能验证的值

任何进一步的信息(例如,范围的限制、不匹配的正则表达式)都已经存在于验证器实例上,并且可以通过它进行访问。

那么,如果只有一个看起来像这样的验证错误类:呢

public sealed class ValidationError
{
    public Validator Validator { get; set; }
    public string PropertyName { get; set; }
    public object AttemptedValue { get; set; }
}

您可能需要了解FluentValidation之类的内容。它重量轻、直观,涵盖了许多验证场景。

如果您对FluentValidation使用的验证结果不满意,您可以始终将它们封装在自己的自定义验证错误类中。至少你可以免费获得很多基本功能。