@ddd329

Всегда ли объект должен валидным?

Привет, ребята.
Допустим, у меня есть в коде объект-сущность Document, у которого имеется свойство RegNumber, т.е. регистрационный номер. Правило такое - регистрационный номер должен быть определенного формата и быть уникальным для каждого документа. Номер может быть сгенерирован автоматически или быть присвоенным вручную. Рассмотрим случай когда пользователь вводит в форму номер документа и View передает этот номер Presenter'у. Если номер оказался неверного формата или не является уникальным, то может ли Presenter присвоить значение свойству RegNumber объекта Document?

Я всегда считал что НЕТ, потому что объект предметной области должен всегда находится в валидном состоянии, т.е. соблюдать все инварианты. Если объект Document имеет какую-то операцию, то после ее выполнения объект должен соблюдать инварианты, а если он до выполнения операции не валиден, то. и после тоже...

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

И как считываете Вы, может ли объект предметной области на протяжении своего жизненного цикла находится в не валидном состоянии, т.е. нарушая инварианты?
  • Вопрос задан
  • 356 просмотров
Решения вопроса 1
myrkoxx
@myrkoxx
developer
Моя позиция по даному вопросу - да, всегда объект должен оставаться валидным если разговор идет о entity или value object.

Рассмотрим случай когда пользователь вводит в форму номер документа и View передает этот номер Presenter'у. Если номер оказался неверного формата или не является уникальным, то может ли Presenter присвоить значение свойству RegNumber объекта Document?


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

На View и с View передавал бы Presentation . Он может быть как раз не валидным. По сути он тупая DTO'шка, всего лиш ресурс. Отдавать напрямую entity не очень хорогая идея. Простой пример - REST. В REST ключевая единица ето ресурс. Ресурс по сути ето проеция или мапинг entity или нескольких entities:

A resource is a conceptual mapping to a set of entities, not the entity that corresponds to the mapping at any particular point in time. Architectural Styles and the Design of Network-bas...


RegNumber - я б делал ValueObject с валидацией внутри (прям в конструкторе ), вот псевдо-код:

class RegNumber
{
    private regNumber;

    private construct(regNumber)
    {
        this.setRegNumber(regNumber);
    }

    private setRegNumber(regNumber)
    {
        this.assertRegNumberIsValid(
            regNumber
        );

        this.regNumber = regNumber;
    }

    public static function create(regNumber)
    {
        return new self(regNumber);
    }

    private function assertRegNumberIsValid(regNumber)
    {
        if (regNumber is bad) {
             throw new InvalidRegNumber()
        }
    }
}


и уже его испольовал в Document. И так, по сути, он всегда будет валидным, так как не валидный объект не сможет создатся
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@ddd329 Автор вопроса
Да, вопрос как раз об Entity и ValueObject'ы.

Я пишу код на C#, но не суть... Я уже пробовал регистрационный номер выразить в коде через ValueObject, который бы занимался валидацией входной строки, и всегда создавался валидным. По началу казалось мне все проще, я проверял входную строку регулярным выражением, но этого оказалось мало.
Входная строка, которая представляла регистрационный номер состоит из трех частей, первая часть это бизнес-направление, вторая часть вид документа и третья часть это порядковый номер, т.е. надо еще проверять существует ли бизнес-направление и вид документа, да и еще глобальную уникальность самого номера. Я сомневаюсь что этим всем должен заниматься ValueObject т.к. требуется обращение к Repository.

Может сделать так: вынести класс Document в отдельную сборку Domain, выставить у свойства RegNumber модификатор доступа internal, чтобы клиентский код, например Presenter, не смог на прямую устанавливать значения. Ввести доменную службу DocumentService и в нем реализовать логику присвоения регистрационного номера, здесь как раз будет и парсинг строки, и проверка всех частей номера в базе данных обращение к которой будет осуществляться через репозиторий?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы