Постараюсь изложить проблему покороче, так что заранее извиняюсь, если
получится слишком общее описание.
Приложение делает запросы к БД, результаты запросов преобразуются в
классы предметной области (в качестве ORM использую NHibernate) и
показываются пользователю в некоторых представлениях (какие-то
контролы WinForms). Допускается, что пользователь видит сразу
результаты нескольких разных запросов в отдельных представлениях
(например, чтоб сравнить результаты поиска по разным критериям).
Итак, предположим мы выполняем запрос, он среди прочего возвращает
строку с ID=42. Эта строка маппится на объект A, объект показывается в
соответствующем представлении. Далее выполняем другой запрос, он также
возвращает строку с ID=42. Поскольку второй запрос выполняется позже и
в другой сессии, эта строка маппится на другой объект B; объект В
показывается в другом представлении. С точки зрения database identity
объекты А и В - это одно и то же, т.к. у них одинаковый ID; с точки
зрения .NET - это разные объекты по разным ссылкам (или точнее разные
копии одного объекта).
Самое интересное начинается, когда пользователь начинает редактировать
(через представление) объект А. Отредактировал, сохранил в базу. Как
теперь быть с объектом В? нужно же значения полей синхронизировать с
объектом А, чтобы во втором представлении тоже показывались актуальные
данные. Я пока использую паттерн Observer: 1) отредактировали объект
2) отправили уведомление "Объект с ID=42 изменился, поменялись такие-
то поля" 3) заинтересованные объекты модели ловят это уведомление,
обновляют свои копии объектов с ID=42, если они у них имеются и 4)
уведомляем представления, для которых были изменения в соответсвующих
объектах домена, чтоб перерисовались.
Правильное ли я выбрал решение проблемы? Как принято поступать в
подобных случаях?
> Но лично я при разработке настольных приложений с NHibernate поступаю
> следующим образом:
> 1) во всех представлениях использую вьюмодельки (простые DTO) вместо
> объектов домена (соответственно, выбираю одну из крайностей, описанных в
> статье, т.е. открываю сессию только на время выполнения бизнес-операции)
> 2) после редактирования какой-то сущности тупо обновляю представления (в
> частности, списки, гриды и т.д.), то есть особо не заморачиваюсь на то,
> чтобы найти только нужные объекты и обновить их.
Попробую Ваш подход, вероятно, он поможет мне упростить некоторые
вьюхи, которые у меня в основном read-only.
Еще раз спасибо, Вы мне очень помогли!
Да нет, singleton мне как раз не нужен, т.к. он приводит к другим
проблемам, в том числе и описанным в упомянутой Алексеем Романовским
(извиняюсь, если неверно траслителировал фамилию) статье.
во всех представлениях использую вьюмодельки (простые DTO) вместо объектов домена
Добрый день, Александр,
> Андрей, а что заставило вас усомниться в выбранном решении? Какие проблемы> начали у вас возникать?Как таковых проблем, которые бы можно было назвать, нет. Просто я не так давно начал изучать DDD, поэтому у меня еще не выработался свой стиль и багаж проверенных решений, которые можно применять не задумываясь (не очень нравится это выражение, думать в любом случае нужно), а просто основываясь на своем опыте. Поэтому у меня сейчас пока идет этап обучения, проб и ошибок, так что хотелось подстраховаться, убедиться, что решение, которое я принял и которое в итоге пойдет в боевой продукт, верное.
> Поддержу идею Андрей :) На View должны попадать только DTO. Если вы
> используете MVP, то это будут сформированные модели (M). Работа с доменными
> объектами на View, особенно при использовании ORM сильно свяжет данные и
> представление.
А Вы правы, так и есть, уже связало. Я только сейчас об этом
задумался ) И еще я попробовал представить, как у меня будут выглядеть
эти DTO, и получается, что они не особо будут отличаться от собственно
объектов домена. А это говорит о том, что объекты домена у меня
используются по сути только для хранения данных, т.е., видимо, у меня
в проекте получилось то, что называется анемичной доменной моделью, я
прав? Похоже, придется мне пересмотреть свою доменную модель :)
Спасибо за Ваш комментарий!
Что-то я с форматированием текста в предыдущем сообщении напутал,
извиняюсь (
On 16 мар, 11:40, Alexander Byndyu <alexander.byn...@gmail.com> wrote:
Добрый день, Александр,
> Андрей, а что заставило вас усомниться в выбранном решении? Какие проблемы> начали у вас возникать?Как таковых проблем, которые бы можно было назвать, нет. Просто я не так давно начал изучать DDD, поэтому у меня еще не выработался свой стиль и багаж проверенных решений, которые можно применять не задумываясь (не очень нравится это выражение, думать в любом случае нужно), а просто основываясь на своем опыте. Поэтому у меня сейчас пока идет этап обучения, проб и ошибок, так что хотелось подстраховаться, убедиться, что
решение, которое я принял и которое в итоге пойдет в боевой продукт, верное.
> Поддержу идею Андрей :) На View должны попадать только DTO. Если выА Вы правы, так и есть, уже связало. Я только сейчас об этом
> используете MVP, то это будут сформированные модели (M). Работа с доменными
> объектами на View, особенно при использовании ORM сильно свяжет данные и
> представление.
задумался ) И еще я попробовал представить, как у меня будут выглядеть
эти DTO, и получается, что они не особо будут отличаться от собственно
объектов домена. А это говорит о том, что объекты домена у меня
используются по сути только для хранения данных, т.е., видимо, у меня
в проекте получилось то, что называется анемичной доменной моделью, я
прав? Похоже, придется мне пересмотреть свою доменную модель :)
Спасибо за Ваш комментарий!
> Нет ничего плохого в том, что решение будет не идеальное. "Лучшее враг
> хорошего"
золотые слова :)
> Да, вы правы. Если они совершенно идентичны, то это ни что иное как
> анемичная модель, или простое CRUD приложение.
> Но в этом нет ничего плохого, не нужно лепить DDD во все места, а как любой
> инструмент применять разумно. Молотком тоже можно шурупы забивать, но не
> очень эффективно.
Да, пока у меня видимо эйфория от мощи и возможностей DDD не прошла,
подозреваю, что использую его где надо и где не надо. Пройдет )
> Как делаю я (правда вёб разработка, но когда пишу настольные приложения
> использую тот же подход за счет использования тонкого клиента):
>
> 1. создаю пустой класс
> 2. объявляю что он у меня модель для этого представления.
> 3. в представлении работаю с несуществующими полями.
> 4. создаю поля, которые понадобились.
> 5. пишу мапинг из сущностей (как автомаппер, так и вручную, в зависимости
> от настроения или практик, принятых в текущем проекте).
>
> При таком подходе я получаю следующие плюсы:
> 1. можно изменять разные представления полностью независимо.
> 2. модель домена и модель отображения можно менять независимо.
>
> Минус - возрастает количество классов, но это не беда, если использовать
> понятные соглашения именования.
Я правильно понимаю, что в итоге имеем как маппинги для DTO, так и для
объектов домена, причем первые используются в основном в режиме read-
only (прочитали из базы, сформировали DTO, показали во вьюхе), а
вторые - read/write?