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

40 views
Skip to first unread message

Progger .Net

unread,
Jan 11, 2018, 10:08:27 AM1/11/18
to dotnetconf
Привет, ребята.
Допустим, у меня есть в коде объект-сущность Document, у которого имеется свойство RegNumber, т.е. регистрационный номер. Правило такое - регистрационный номер должен быть определенного формата и быть уникальным для каждого документа. Номер может быть сгенерирован автоматически или быть присвоенным вручную. Рассмотрим случай когда пользователь вводит в форму номер документа и View передает этот номер Presenter'у. Если номер оказался неверного формата или не является уникальным, то может ли Presenter присвоить значение свойству RegNumber объекта Document?

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

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

И как считываете Вы, может ли объект предметной области на протяжении своего жизненного цикла находится в не валидном состоянии, т.е. нарушая инварианты?

Андрей Чистяков

unread,
Jan 12, 2018, 12:38:14 AM1/12/18
to dotnetconf
Рассмотрим случай когда пользователь вводит в форму номер документа и View передает этот номер Presenter'у. Если номер оказался неверного формата или не является уникальным, то может ли Presenter присвоить значение свойству RegNumber объекта Document?

Я не использую в качестви модели в MVP доменные сущности, т.е., в твоём примере у меня Presenter будет присваивть RegNumber не Document'у, а соответствующей вью-модели, представляющей документ (DocumentViewModel). Далее (условно в тот момент, когда пользователь нажимает кнопку "Сохранить") происходит валидация вью-модели, и, если она валидна, по ней уже строится сущность Document, которая и сохраняется в БД или куда там ещё. Минус (а может и не минус) такого подхода в том, что код валидации находится не в классе Document, а где-то сбоку.

Progger .Net

unread,
Jan 12, 2018, 10:45:46 AM1/12/18
to dotnetconf
Интересно...

Ну Вас все устраивает в таком подходе, я имею ввиду с практической точки зрения?

пятница, 12 января 2018 г., 12:38:14 UTC+7 пользователь Андрей Чистяков написал:

Андрей Чистяков

unread,
Jan 12, 2018, 4:40:13 PM1/12/18
to dotnetconf
пятница, 12 января 2018 г., 18:45:46 UTC+3 пользователь Progger .Net написал:
Интересно...

Ну Вас все устраивает в таком подходе, я имею ввиду с практической точки зрения?


Нет, конечно. Не существует единственно верного подхода, т.к. если бы он существовал, то мы бы просто каждый день уныло писали Лучшие в Мире Программы Самым Правильным Способом :) Любой подход - это всегда компромисс.

Мне нравится то, что вью-модели отделены от доменных сущностей и, как правило, это имеет смысл, потому что то, что мы показываем в UI не всегда один-к-одному соответствует тому, что мы храним в базе:
- вью-модель может содержать некоторые поля/свойства, которых нет в доменной сущности. Например, я часто добавляю вью-модели свойства, связанные с визуалным оформлением, например, можно завести свойство ValueColor, которое будет возвращать красный цвет для отрицательной суммы и зелёный для положительной. Понятно, что эта логика относится только к UI и, следовательно, в доменной сущности ей делать нечего, а во вью-модели ей будет хорошо
- вью-модель может наоборот не содержать полей/свойств доменной сущности, если они в данном месте UI не нужны. Вообще говоря, одной доменной сущности может соответствовть несколько разных вью-моделей (т.к. одна и та же информация в разных местах интерфейса может выглядеть по-разному, с разной степенью подробности)
- одна вью-модель может служить для отоборажения нескольких доменных сущностей. Например, есть доменная сущность Department (отдел), в которой содержится коллекция сущностей Employee (сотрудник) и для этого агрегата можно сделать вью-модель DepartmentViewModel с двумя свойствами: string Name (название отдела) и string Employees (имена сотрудников, перечисленные через запятую), т.е. одна вью-модель будет отражать две доменные сущности (точне одну сущность и одну коллекцию сущностей).

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

Но, в целом, для меня плюсы всё-таки кажутся значительнее, чем минусы, поэтому пользуюсь таким подходом. 
Reply all
Reply to author
Forward
0 new messages