Валидация на среднем уровне - PullRequest
2 голосов
/ 30 октября 2008

Я хочу сделать проверку моего бизнес-кода. Я думаю о 2 способах сделать это.

Во-первых, выполните проверку на мои установщики свойств класса следующим образом

class Student{
    public string Name{
        get { return _name; }
        set {
            if (value.IsNullOrEmpty) throw exception ...
        }
    } 
} 

Теперь, проблема с этим подходом состоит в том, что код проверки запускается каждый раз, когда присваивается имя, которое нам может не понадобиться, например, при заполнении его данными из БД.

Два, которые я предпочитаю, помещают статические методы в эти классы сущностей, как

class Student {
    public **static** void ValidateName(**string name**) {
        if (string.IsNullorEmpty(name)) 
        {
            throw ...
        }
        ...
    } 

Обратите внимание, что я использую статический метод вместо метода экземпляра, например

class Student{
    public void Validate() {
        // validation logic on instance properties
        if (string.IsNullorEmpty(Name)) 
        {
            throw ...
        }

        ...
    } 

потому что я не всегда передаю объект Student, я получаю примитивные типы, такие как имя строки, часто передаваемое в метод, например

public static FindStudentByName(string name)
{
   // here I want to first do validation
   Student.ValidateName(name);

   // query DB
   ...
}

Если меня зачисляют в студенческую школу, тогда, конечно, я могу сделать

public static AddStudent(Student s)
{
    // call the instance method
    s.Validate();
}

Теперь я хотел бы, чтобы все было очень просто, поэтому я не хочу, чтобы использовал какой-либо из следующих подходов

  1. Используйте атрибуты свойств, например [StringLength (25)].

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

    Во-вторых, я хочу, чтобы мой сайт мог работать в Medium Trust. Для размышления, насколько я понимаю, требуется полное доверие.

  2. Используйте любой из блоков валидации, например MS. Корпоративная библиотека и т. Д. Найдена в CodePlex.

Теперь я хочу узнать ваше мнение по этому поводу,

Каковы некоторые потенциальные проблемы с подходом, с которым я иду?
Будет ли этот подход работать лучше, более читабельным, легче поддерживать, чем другие подходы?

Как вы делаете проверку на своем среднем уровне?

Спасибо большое!

Ray.

Ответы [ 3 ]

4 голосов
/ 30 октября 2008

Я выполняю проверку домена на среднем уровне с помощью механизма правил, очень похожего на тот, который написан здесь . В проекте друга используется подход, аналогичный тому, который вы предлагаете в последнем примере, и конечный результат не поддерживается (хрупкий, трудно реализуемый универсальный пользовательский интерфейс проверки). Подход с помощью механизма правил можно поддерживать, поскольку он локализует все правила проверки и сохранения в одном хорошо организованном месте и имеет каждое правило как полноценный класс, но предоставляет проверку для классов домена, аналогичную предложенной вами. Некоторым людям нравится динамическая компиляция, поэтому они хранят их в базе данных для высокого уровня конфигурации после развертывания; в моем случае они мне нравятся, когда проверяется время компиляции, поэтому в статическом классе есть определения правил с лямбдами.

Я знаю, что это не соответствует тому, что вы хотите сделать, но спросить, как бы я это сделал, и сказать, что другие подходы недостаточно просты, это все равно, что сказать: «Как вы можете написать надежный код, я хочу сохранить это просто, поэтому о модульных тестах не может быть и речи ». С моей точки зрения, каждое правило следует рассматривать как отдельный класс, поскольку его легче поддерживать и документировать, хотя и сложнее реализовать.

1 голос
/ 30 октября 2008

Подход, который вы предлагаете, указывает на то, что набор проверки не должен применяться всегда. Что в порядке. Я видел множество правил и проверок, которые мы хотим «большую часть времени», но не всегда. Таким образом, возникает вопрос: «Когда вы хотите применить эти проверки»?

Скажем, например, у вас есть некоторые проверки, которые вы всегда хотите применить, а некоторые вы хотите проверить только тогда, когда ... я не знаю ... вы собираетесь сохранить в хранилище (база данных). В этом случае проверки, которые применяются всегда, должны быть в свойствах (см. Подробнее об этом ниже), а проверки, которые применяются только тогда, когда вы собираетесь сохранить в хранилище, должны быть в методе (может быть назван в виде строки ' VerifyRulesForStorage '), который будет вызываться при необходимости (например, в середине вашего метода SaveToStorage).

Одна вещь, на которую стоит обратить внимание, я думаю, это дублирование, которое вы рискуете получить, когда у вас одинаковая проверка на нескольких объектах. Будь то в свойстве или в методе «VerifyRulesForStorage», вполне вероятно, что у вас будет одна и та же проверка (например, String.IsNullOrEmpty, CheckItsANumber, CheckItsOneOfTheAcceptedValues ​​и т. Д.) Во многих местах во многих классах. Конечно, вы можете решить эту проблему с помощью наследования (например, все ваши сущности наследуют от базового класса Entity, в котором есть методы, реализующие каждый тип проверки) или композиции (возможно, это лучший подход, так что дерево классов ваших сущностей управляется другими, более уместны соображения, например: все ваши сущности имеют объект Validator, который реализует все эти проверки). В любом случае, вы можете захотеть держаться подальше от статических методов, так как они, как правило, создают проблемные ситуации, если вы управляем тестом (есть способы обхода, когда это необходимо).

В нашей системе у нас фактически есть метаданные, описывающие правила проверки. Имя свойства класса используется для получения правильных метаданных, которые затем сообщают системе, какие правила применять. Затем у нас есть объект-валидатор, который создает экземпляр соответствующего типа объекта для фактической проверки с помощью фабрики (например, у нас есть один класс, реализующий правило IsRequiredString, другой, реализующий правило IsNumber и т. Д. И т. Д.). Звучит как сложность, но в такой системе, как наша, это определенно стоило того.

Наконец, готовые библиотеки могут быть хорошей альтернативой. В нашем случае они были не из-за особых требований, которые у нас были - но в целом ... есть преимущества в использовании колеса, которое кто-то другой разработал (и поддержит), по сравнению с созданием собственного (поверьте мне, я люблю восстанавливать колеса, когда я может .. я просто говорю, что есть случаи, когда каждый подход лучше другого).

1 голос
/ 30 октября 2008

Второй вариант - это то, что на самом деле не требует проверки, по крайней мере, если вы не вызовете validate вручную. Поэтому потребители ваших объектов могут нарушать правила.

Лично я бы пошел с чем-то похожим на ваш первый пример, так как он гарантирует, что ВСЕ данные верны. это дополнительная проверка на стороне БД, но из того, что я заметил, как правило, нет ничего сложного.

...