2010-11-12 4 views
6

Я немного читал DDD, и я смущен тем, как это будет соответствовать при использовании ORM, например, NHibernate.Можно использовать чистый DDD-подход с NHibernate?

Прямо сейчас у меня есть приложение .NET MVC с довольно «живыми» контроллерами, и я пытаюсь выяснить, как лучше всего это исправить. Перемещение этой бизнес-логики в слой модели было бы лучшим способом сделать это, но я не уверен, как это можно сделать.

Мое приложение настроено таким образом, что сеанс NHibernate управляется HttpModule (получает сеанс/транзакцию с моего пути), который используется репозиториями, возвращающими объекты сущности (Think S # arp arch ... получается в действительности это дублирует много их функциональных возможностей). Эти репозитории используются DataServices, которые прямо сейчас являются обертками вокруг репозиториев (взаимно однозначное сопоставление между ними, например UserDataService принимает UserRepository или фактически репозиторий). Эти DataServices прямо сейчас гарантируют, что аннотации данных, украшающие классы сущностей, проверяются при сохранении/обновлении.

Таким образом, мои объекты на самом деле являются объектами данных, но не содержат никакой реальной логики. Хотя я мог бы поместить некоторые вещи в классы сущностей (например, метод «Утвердить»), когда это действие должно выполнить что-то вроде отправки электронной почты или касания других несвязанных объектов или, например, проверки, чтобы увидеть, есть пользователи, которые имеют одинаковое электронное письмо перед утверждением и т. д., тогда сущности потребуется доступ к другим репозиториям и т. д. Ввод данных с помощью IoC не будет работать с NHibernate, поэтому вам придется использовать фабрику Я предполагаю получить их. Я не понимаю, как вы могли бы издеваться над темистами.

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

Другой способ взглянуть на это, я думаю, что каждая из этих служб образует единую модель с объектом данных, с которым она работает (разделение полей хранения данных и логики, которая работает на нем), но я просто хотел чтобы увидеть, что делают другие, чтобы решить проблему «живого контроллера» с помощью DDD, используя ORM, например NHibernate, который работает, возвращая заполненные объекты данных и модель репозитория.

Обновлено Я думаю, что моя проблема в том, как я смотрю на это: NHibernate, кажется, поставить бизнес-объекты (сущности) в нижней части стека, который репозиториях затем действовать дальше. Репозитории используются службами, которые могут использовать несколько репозиториев и другие службы (электронная почта, доступ к файлам) для выполнения действий. Т.е.: Приложение> Услуги> Репозитории> Бизнес-объекты

Чистый подход DDD, который я читаю, по-видимому, отражает смещение Active Record, где функции CRUD существуют в бизнес-объектах (это я вызываю User.Delete непосредственно вместо Repository.Delete из службы), а фактический бизнес-объект обрабатывает логику вещей, которые должны выполняться в этом экземпляре (например, отправка по электронной почте пользователя и удаление файлов, принадлежащих пользователю, и т. Д.). То есть Приложение> (Сервисы)> Бизнес-объекты> Репозитории

С NHibernate, кажется, мне было бы лучше использовать первый подход, учитывая функции NHibernate, и я ищу подтверждение по моей логике. Или, если я просто смущен, некоторые разъяснения о том, как должен работать этот многоуровневый подход. Я понимаю, что если у меня есть метод «Утвердить», который обновляет модель User, сохраняется и, скажем, посылает несколько сообщений нескольким людям, что этот метод должен идти на объект объекта User, но для обеспечения надлежащего IoC, чтобы я мог введите messagingService, мне нужно сделать это на моем уровне обслуживания, а не на объекте User.

С точки зрения «множественного UI» это имеет смысл, так как логика делать вещи выведена из моего уровня пользовательского интерфейса (MVC) и помещается в эти сервисы ... но я по сути просто факторинга логика в другой класс вместо того, чтобы делать это непосредственно в контроллере, и если у меня не будет никакого другого интерфейса, я просто торгую «жирным контроллером» для «толстой службы», поскольку служба по существу, собирается инкапсулировать метод на каждое действие контроллера для выполнения его работы.

+0

Я не уверен, что «чистый подход DDD» отражает активное смещение записи. Это явно не похоже на все, что я помню в книге Эрика Эванса. Какой источник вы используете, что предполагает, что объекты используют ActiveRecord? – JasonTrue

+0

Для чего это стоит, вы можете использовать Castle ActiveRecord, если хотите, чтобы Nhibernate использовал ActiveRecord вместо подхода DDD. – JasonTrue

ответ

4

DDD делает не иметь активный скос записи. Удалить is не метод, который должен находиться на объекте (например, User) в DDD.

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

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

Один кусок головоломки это кажется вам не хватает в Доменные событий. Объект домена не должен отправлять электронную почту напрямую. Это должно вызвать событие в Домене, чтобы произошло какое-то значительное событие. Внедрите класс, целью которого является отправка электронной почты при возникновении события, и зарегистрируйте его для прослушивания события домена.

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

В этом, вероятно, следует проверить до того подачи вызова «одобрить , а не в функции, которая выполняет утверждение. Нажимайте решение до уровня в вызове кода.

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

Это может работать, если это делается с пониманием того, что служба является точкой входа для клиента. Целью службы является использование параметров в DTO с помощью интерфейса/клиента и перевод этого метода в вызовы методов против объекта, чтобы выполнить требуемую функциональность.

+0

Я не думаю о таких событиях, нет ... Итак, вы говорите, что сущности должны ТОЛЬКО иметь методы, которые касаются изменения состояния домена (например, изменение значения). Что-либо за пределами этого должно быть поднято как событие, а обработчики событий используются для выполнения других действий, таких как удаление файлов и отправка электронной почты? –

+0

Да, в основном, доменное состояние * есть *, за что отвечают сущности. События очень естественны для реализации многих требований, и они имеют ценность сами по себе (фиксируя намерение изменений, аудита и т. Д.). Хотя я бы не сказал ТОЛЬКО или Любые. Иногда более прямолинейно иметь исключение из правила. Это всегда решение и решение, но события помогли мне увидеть, где во многих случаях включить функции с большей ясностью. –

+0

Есть ли хороший форум для обсуждения этих вещей? Я чувствую, что у меня будет больше вопросов ... –

0

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

Поскольку вы строите свою модель домена после DDD, я бы ожидал, что большая часть бизнес-логики, которая нашла вас в вас, MVC-контроллеры, вероятно, должны находиться в объектах вашего домена. В моей первой попытке использовать ASP.NET MVC я быстро оказался в том же положении, что и вы, - регуляторы жира и модель анемичного домена.

Чтобы избежать этого, я теперь придерживаюсь подхода к созданию богатой модели домена, которая реализует бизнес-логику и использует модель MVC как по существу простые объекты данных, используемые моими представлениями. Это упрощает мои контроллеры - они взаимодействуют с моей моделью домена и предоставляют простые объекты данных (из модели MVC) в представления.

Обновлено

Чистый DDD подход я читаю о, кажется, отражает смещение активной записи ...

Для меня активный шаблон записи означает, что субъекты осознают их механизм персистентности и сущность сопоставляется непосредственно с записью таблицы базы данных. Это один из способов использования NHibernate, например. см. Castle Active Record, однако я нахожу это загрязняющим доменом enitities со знанием их механизма сохранения. Вместо этого, как правило, у меня будет репозиторий на aggregate root в моей модели домена, которая реализует абстрактный репозиторий. В репозитарии представлены основные методы CRUD, такие как:

public IList<TEntity> GetAll() 
public TEntity GetById(int id) 
public void SaveOrUpdate(TEntity entity) 
public void Delete(TEntity entity) 

.. которые могут быть дополнены/продлены мои конкретные хранилища.

См. this post on The NHibernate FAQ, на котором я основал множество своих материалов. Также помните, что NHibernate (в зависимости от того, как вы настроили свои сопоставления) позволит вам дестабилизировать полный графический объект, т. Е. Ваш совокупный корень плюс все объекты, свисающие с него, и как только вы закончите работать с ним, можете каскадно экономить через вас весь графический объект, это, конечно, не активная запись.

... так как услуга по существу будет инкапсулировать метод в действии контроллера, чтобы сделать это работа ...

Я все еще думаю, что вы должны рассмотреть, какие функциональные возможности, которые вы в настоящее время в контроллерах должны, более логично, быть реализованы в ваших объектах домена. например в вашем примере утверждения, я думаю, было бы разумно, чтобы сущность предоставила одобряющий метод, который делает все, что ему нужно сделать внутри объекта, и если, как в вашем примере, необходимо отправить электронные письма, делегируйте это службе. Услуги должны быть зарезервированы для cross-cutting concerns. Затем, как только вы закончите работу с объектами домена, переместите их обратно в свой репозиторий, чтобы сохранить изменения.

Несколько книг, которые я нашел полезным на эти темы являются:
Domain-Driven Design by Eric Evans
Applying Domain-Driven Design and Patterns by Jimmy Nilsson

+0

Да, я использую подход ViewModel для моего контроллера для просмотра данных. Мой вопрос вращается вокруг того факта, что DDD, похоже, указывает больше на активную запись, такую ​​как дизайн (например, у пользователя есть метод «Удалить», который проходит и удаляет все файлы, связанные с пользователем). Использование шаблона репозитория muddies это больше. См. Мои заметки выше. –

+0

@Michael Я обновил свой ответ на основе ваших комментариев. – Graham

+0

@Graham, да, эта статья является основой для моей системы. Моя проблема пытается понять, где вещи нарезаются.Я начинаю получать некоторые из этого сейчас, и вижу способы сделать что-то, например, вводя мои требования во время выполнения метода (вместо Form.Approve() у меня будет Form.Approve (currentUser, booleanSomething и т. Д.),). Тогда события, которые должны произойти вне контекста домена (которые являются объектами базы данных), могут обрабатываться поднятыми событиями. –

0

Единственные ограничения, которые NHibernate создает для классов, - все методы/свойства должны быть виртуальными, а класс должен иметь конструктор по умолчанию (может быть внутренним или защищенным). В противном случае он не [edit] вмешивается в структуру объекта и может отображать довольно сложные модели.

+0

Вы имели в виду «В противном случае, он делает ** не ** вмешивается в структуру объекта»? –

+0

Ну, мой вопрос об методе удаления состоял в том, что казалось, что если для удаления объекта необходимо иметь ДРУГИЕ ДЕЙСТВИЯ, то метод удаления должен идти в сущности. Методология событий домена делает это MUCH более чистым для меня для таких вещей, как электронная почта, теперь, когда я это понимаю. Другим вариантом, конечно же, является выполнение этих дополнительных действий на уровнях сервисов приложения, что может быть лучше, например, при удалении связанных файлов при удалении сущности из хранилища сохраняемости. Я просто с трудом понимал, как подходят события, не связанные с постоянством. –

Смежные вопросы