Разработка иерархии ошибок валидации - PullRequest
0 голосов
/ 05 марта 2012

В нашей системе у нас есть сущность Product, которая может иметь различные пользовательские свойства.Набор свойств может отличаться от продукта к продукту и хранится в поле типа List<Property>.Свойства имеют разные типы (строки, целые, двойные) и могут иметь некоторые специальные характеристики, например, они могут быть многозначными, могут быть значением определенного диапазона, значением из данного списка и т. Д. Значение свойства всегда содержится встроковое поле Value.

Теперь моя текущая проблема состоит в том, чтобы реализовать проверку этих свойств, и я застрял на том, какой подход использовать в части представления результатов проверки.Требования, которые я должен выполнить: - Результаты проверки будут использоваться другими прикладными уровнями, поэтому результирующий API должен быть понятным и простым в использовании - Каждая ошибка должна иметь четкое представление - Пользователи API должны иметь достаточно информации для пониманияособенности ошибок (например, для ошибок диапазона они должны быть представлены с минимально возможным значением, максимально возможным значением и фактическим значением)

Вот подходы, которые я рассмотрел до сих пор:

  1. Иерархия классов. Существует один базовый абстрактный класс ValidationError, и каждая конкретная ошибка будет отражена в унаследованном классе.Если ошибка имеет какую-либо специфику, соответствующий класс будет иметь необходимые поля для хранения всей информации.Пример:

    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.

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

Ответы [ 2 ]

0 голосов
/ 05 марта 2012

Возможно, вы захотите взглянуть на что-то вроде FluentValidation .Это легкий, интуитивно понятный и охватывает множество сценариев проверки.

Если вас не устраивают результаты проверки, используемые FluentValidation, вы всегда можете обернуть их в свои собственные классы ошибок проверки.По крайней мере, вы получите множество базовых функций бесплатно.

0 голосов
/ 05 марта 2012

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

Любая ошибка проверки может быть точно указана с учетом:

  1. Валидатору, который не смог принять значение свойства
  2. Имя свойства
  3. Значение, которое не удалось проверить

Любая дополнительная информация (например, пределы диапазона, регулярное выражение, которое не соответствует) уже присутствует в экземпляре средства проверки и доступна черезчто.

Так что насчет всего одного класса ошибки проверки, который выглядит так:

public sealed class ValidationError
{
    public Validator Validator { get; set; }
    public string PropertyName { get; set; }
    public object AttemptedValue { get; set; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...