DDD: Где хранить доменные интерфейсы, инфраструктуру? - PullRequest
21 голосов
/ 28 марта 2009

Имеет ли смысл группировать все интерфейсы вашего доменного уровня (модули, модели, объекты, доменные службы и т. Д.) На уровне инфраструктуры? Если нет, имеет ли смысл создавать «общий» проект / компонент, который группирует все это в общую библиотеку? В конце концов, определение «Уровень инфраструктуры» включает в себя «общие библиотеки для уровней домена, приложений и пользовательского интерфейса».

Я думаю о разработке своей кодовой базы вокруг слоев DDD: пользовательский интерфейс, приложение, домен, инфраструктура. Это создаст 4 проекта с уважением. Я хочу сказать, что вы ссылаетесь на уровень инфраструктуры из уровня домена. Но если вы определите интерфейсы в проекте Domain Layer, скажем для IPost, то у вас будет круговая ссылка, когда вам нужно будет ссылаться на проект Domain Layer из проекта Infrastructure, когда вы определяете метод IPostRepository.Save (IPost post) , Следовательно, идея «определить все интерфейсы в общей библиотеке».

Возможно, в репозиториях не следует ожидать сохранения объекта (IPostRepository.Save (публикация IPost); вместо этого следует ожидать, что параметры объекта будут (хотя это может быть длинный набор параметров в Save ()). это может быть идеальной ситуацией, которая показывает, когда объект становится слишком сложным, и для этого нужно искать дополнительные объекты значения.

Мысли

Ответы [ 3 ]

28 голосов
/ 01 апреля 2009

Эрик, Я отсутствовал на пару, так что прости меня за ответ так поздно. Что касается места размещения репозиториев, лично я всегда помещаю репозитории в выделенный уровень инфраструктуры (например, MyApp.Data.Oracle), но объявляю интерфейсы, которым репозитории должны соответствовать на уровне домена.
В моих проектах прикладному уровню необходим доступ к уровню домена и инфраструктуры, поскольку он отвечает за настройку уровня домена и инфраструктуры.
Прикладной уровень отвечает за внедрение надлежащей инфраструктуры в домен. Домен не знает, с какой инфраструктурой он общается, он знает только, как его вызвать. Конечно, я использую контейнеры IOC, такие как Structuremap, чтобы внедрить зависимости в домен. Опять же, я не утверждаю, что именно так DDD рекомендует структурировать ваши проекты, я просто проектирую свои приложения. Приветствия.

3 голосов
/ 01 апреля 2009

Я бы посоветовал вам рассмотреть Луковую архитектуру . Это прекрасно сочетается с DDD. Идея состоит в том, что ваши интерфейсы хранилища находятся в слое сразу за доменом и напрямую ссылаются на сущности:

IPostRepository.Save(Post post)

Домен вообще не должен знать о репозиториях.

Уровень инфраструктуры не упоминается ни Доменом, ни кем-либо еще и содержит конкретные реализации репозиториев среди других вещей, связанных с вводом / выводом. В этом случае общая библиотека с различными помощниками называется Application Core, и на нее может ссылаться кто угодно.

3 голосов
/ 30 марта 2009

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

Лично я не понимаю, почему вы должны ссылаться на уровень инфраструктуры из вашего домена. На мой взгляд, домен не должен зависеть от инфраструктуры. Объекты Домена должны полностью не знать, в какой базе данных они работают или какой тип почтового сервера используется для отправки почты. Абстрагируя домен от инфраструктуры, его проще использовать повторно; потому что домен не знает, на какой инфраструктуре он работает.

То, что я делаю в своем коде, ссылается на уровень домена из моего уровня инфраструктуры (но не наоборот). Репозитории знают объекты домена, потому что их роль заключается в сохранении состояния домена. Мои репозитории содержат мои основные операции CRUD для моих корневых агрегатов (get (id), getall (), save (object), delete (object) и вызываются из моих контроллеров.

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

Корневой агрегат должен был создаваться через репозиторий с помощью метода Get (ID) или Create () из репозитория. Конкретный репозиторий, создающий объект, прошел сам, так что агрегат мог сохранить его состояние и состояние его дочерних объектов, но ничего не зная о конкретной реализации репозитория. e.g.:

public class PostRepository:IPostRepository
{
     ...
    public Post Create()
    {
        Post post=new Post(this);
        dbContext.PostTable.Insert(post);
        return post;
     }
     public  Save(post)
     {
         Post exitingPost=GetPost(post.ID);
         existingPost = post;
         dbContext.SubmitChanges();
     }
}

public class Post
{

     private IPostRepository _repository
     internal  Post(IPostRepository repository)
     {
        _repository = repository;
     }
     ...
    Public Save()
    {
        _repository.Save(this);
     }

}
...