Должен ли я помещать логику проверки в POCO?

Скажем, у меня есть POCO, например:

public class Name
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Имя FirstName и LastName не может быть нулевым. Должен ли я добавить такой метод:

public List<Error> Validate()
{
    var errors = new List<Error>();

    if (String.IsNullOrEmpty(FirstName))
        errors.Add(new Error("FirstName", "You must fill out first name."));
    if (String.IsNullOrEmpty(LastName))
        errors.Add(new Error("LastName", "You must fill out last name."));
}

где Error - это структура, содержащая a NameValueDictionary. Это хороший способ сделать что-то? Я могу потенциально увидеть проблему с репозиторием, где кто-то пытается сохранить этот POCO, прежде чем запускать его через Validate().

Ответ 1

Рассмотрим использование аспектно-ориентированной структуры проверки, например xVal.

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

public class Name
{
    [Required]
    public string FirstName { get; set; }
    [Required]
    public string LastName { get; set; }
}

Чтобы более точно ответить на ваш вопрос, добавление правил проверки в ваш POCO - это простой способ делать то, что будет работать, но оно может стать тяжелым для поддержания, и вам нужно будет обеспечить интерфейс Validate для всех ваших объектов, которая является собственной головной болью. Аспектно-ориентированное решение довольно элегантное, которое решает эти проблемы и многие другие.

Ответ 2

Я бы не стал. Мой POCO имеет тенденцию иметь другую валидацию, основанную на их контексте. "Объекты My Person должны иметь адрес в этом приложении, но они должны иметь только номер телефона в этом другом приложении"... это то, о чем вы хотите следить и быть гибким.

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

При внедрении новых функций я обычно смотрю на свой класс и задаю себе этот вопрос: похоже ли это, как ответственность этого класса, или он будет более подходящим для класса с другим набором обязанностей? Мы называем эту проверку "Feature Envy", и она эффективно помогает отделить класс и не беспокоится о нем.

Ответ 3

Я не нахожу ничего неправильного в проверке в модели. Он хорошо работает со всеми технологиями Microsoft UI, которые ожидают, что модель может быть задана, если она действительна или нет, и вы не сохраняете отображение одного DTO другому, только чтобы завершить повторение вашей проверки в модели просмотра или редактирования (или хуже, ТОЛЬКО ставить его там).

Правила в вашем примере просты, но вам часто приходится писать более сложные правила. Вероятно, вы должны проверить структуру Csla.Net.