Можно ли использовать чистый подход DDD с NHibernate? - PullRequest
6 голосов
/ 12 ноября 2010

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

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

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

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

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

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

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

Чистый подход DDD, о котором я читаю, кажется, отражает смещение Active Record, когда функции CRUD существуют в бизнес-объектах (это я вызываю User.Delete напрямуювместо Repository.Delete from service), а фактический бизнес-объект обрабатывает логику действий, которые необходимо выполнить в этом случае (например, отправка электронной почты пользователю, удаление принадлежащих ему файлов и т. д.).Т.е. App> (Services)> Business Objects> Repositories

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

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

Ответы [ 3 ]

4 голосов
/ 12 ноября 2010

DDD не имеет наклон Active Record. Удалить - это , а не метод, который должен быть на объекте (например, пользователь) в DDD.

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

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

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

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

Вероятно, следует проверить до отправки вызова на утверждение, а не в функции, выполняющей утверждение.Поднимите решение на уровень вызова кода.

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

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

0 голосов
/ 16 ноября 2010

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

0 голосов
/ 12 ноября 2010

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

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

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

Обновлено

Подход чистого DDD, о котором я читаю, похоже, отражает смещение Active Record ...

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

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

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

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

... поскольку служба, по сути, собирается инкапсулировать метод в действие контроллера для выполнения своей работы ...

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

Несколько книг, которые я нашел полезными по этим темам:
Доменный дизайн Эрика Эванса
Применение доменного дизайна и шаблонов от Джимми Нильссона

...