2012-03-05 3 views
0

В нашей системе у нас есть объект Product, который может иметь различные пользовательские свойства. Набор свойств может отличаться от продукта к продукту и хранится в поле типа List<Property>. Свойства имеют разные типы (строки, ints, double) и могут иметь некоторые особые характеристики, например. они могут быть многозначными, может быть значением определенного диапазона, значения из данного списка и т. д. Значение свойства всегда содержится в поле строки 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, не можем гарантировать, что, когда у нас есть ошибка типа say ValueNotWithinRange, мы имеем дело с классом типа RangeValidationError, а если нет, то как мы его обрабатываем? В то же время я хотел бы иметь некоторую функцию уровня дизайна, которая предотвратила бы даже такие ситуации, поскольку я не являюсь разработчиком API, который разрабатывает API. Еще одна проблема этого подхода заключается в том, что, если большинство ошибок будет в конечном итоге требует некоторой дополнительной информации, мы в конечном итоге с тем же номером aprroach 1.

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

ответ

0

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

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

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

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

Так что о том, только один класс проверки ошибок, которая выглядит следующим образом:

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

В самом деле, вы избегаете дублирования иерархии таким образом, но вы также вводите дополнительное понижение абстрактного Validator. Я предлагаю изменить Validator в параметр типа. – Basilevs

+0

@Basilevs: в любом случае (даже в иерархии ValidationError) необходимо будет использовать downcasting, если вам нужно получить доступ к членам, которые не присутствуют в корневой иерархии (например, свойства 'Min' и' Max'). Единственный способ - создать объект для динамического доступа к значениям свойств во время выполнения, что является моральным эквивалентом использования рефлексии и имеет одну и ту же основную проблему: потеря безопасности типа. – Jon

+0

@ Jon, спасибо за ответ. Нет, пока у меня нет валидаторов. Все проверки выполняются несколькими методами уровня BL. Однако, может быть, стоит подумать об их введении? Но если это так, мы сталкиваемся с той же проблемой, что и для ошибок (которые описаны в вопросе), не так ли? – Andrei

0

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

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

Смежные вопросы