Как общедоступные сайты, созданные с использованием DDD, не имеют одного основного совокупного корня - PullRequest
2 голосов
/ 23 мая 2011

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

Мой сайт, как и большинство общедоступных сайтов, не позволяет каждому пользователю видеть каждую информацию, хранящуюся на сайте. Вместо этого они могут видеть только информацию, которой они владеют. В случае моего сайта пользователи будут создавать «Проекты», которыми они также могут делиться с другими пользователями. Тем не менее, пользователи все еще могут видеть информацию только в проектах, которые они создали или были приглашены присоединиться. Все остальные объекты в моей модели существуют в проекте, и если проект удаляется, все содержащиеся в нем объекты также должны быть удалены.

Значит ли это, что у меня должен быть один основной корневой тип "Project" и один репозиторий "ProjectRepository"? Мне кажется неэффективным загружать весь проект каждый раз, когда запрашивается какая-либо страница на моем сайте. На самом деле это не такая большая проблема, потому что я использую NHibernate, который будет лениво загружать только те элементы в проекте, которые запрашиваются. Тем не менее, кажется плохим дизайном, чтобы эффективность сайта сильно зависела от использования ORM с отложенной загрузкой.


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

Сначала я пытаюсь понять, должен ли тип моего проекта быть совокупным корнем моей модели. Проект может существовать сам по себе, тогда как отчеты должны существовать в рамках проекта. Если проект удален, соответствующие отчеты должны быть удалены. Означает ли это, что Проект может быть или должен быть совокупным корнем? Это мне не очень понятно.

Если Project является агрегированным корнем, то Report не должен быть корректным? Как я понимаю, корни не должны быть вложены в DDD. Кроме того, разрешено извлекать только совокупные корни из репозиториев. Поэтому, если Report не является агрегированным корнем, у меня не должно быть ReportRepository, и вместо этого я должен получать доступ к отчету только через проект, полученный из ProjectsRepository. Таким образом, даже если страница требует данных только из одного отчета, ей потребуется загрузить весь проект из репозитория Project, чтобы получить отчет.

Кроме того, если Project является совокупным корнем, который содержит отчеты, то удаление проекта из репозитория Project может также быть настроено для удаления содержащихся в нем отчетов. Тем не менее, если и Project, и Report являются агрегатными корнями, то не позволят ли ProjectRepository удалять отчеты при удалении проекта, чтобы преодолеть границы между агрегатами? Разве совокупные корни и соответствующие им хранилища не должны действовать независимо друг от друга?

1 Ответ

1 голос
/ 20 июня 2011

Я думаю, что вы сбиваете с толку проблемы. Безопасность (кто что может просматривать) не является проблемой домена. Не позволяйте этому загрязнять ваш домен. Если пользователь не может просмотреть отчет в проекте, примените его в другом месте, кроме модели домена.

Кроме того, я думаю, что вы могли бы извлечь выгоду из отделения вашей ViewModel (которая используется для чтения) от модели вашего домена (которая в основном используется для записи). Они оба используют модель данных (потому что читают из одной схемы БД), но у них действительно разные цели.

На практике (в .NET) разделение вашей ViewModel будет иметь большинство или все следующие характеристики:

  • Ваши представления ASP.NET MVC связаны с одним классом, который представляет все данные на экране. Например, не только текущее выбранное значение в элементе <select>, но и свойство, представляющее все возможные значения <option> в элементе <select>.

Они находятся в пространстве имен MyProject.ViewModel:

public class ProjectLead // Note that this class is specifically designed for display.  This is not the domain object.
{
    public Guid Id;
    public string Name;
}

public class ProjectViewModel
{
    public Guid ProjectLeadId;
    public IEnumerable<ProjectLead> ProjectLeads;
}

Ваше действие контроллера Edit() будет вызывать что-то вроде:

new ProjectViewModelRepository.Load(id);

ProjectViewModelRepository отобразит вашу модель данных (классы nHibernate или строки данных ADO.NET или что-либо еще) на экземпляр ProjectViewModel.

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

    public ActionResult Edit(ProjectViewModel viewModel)
    {
        var repo = new ProjectRepository();
        var project = repo.Load(viewModel.Id);
        // Map the properties of the viewmodel to properties/methods of the Project domain class
        repo.Save(project);
    }

Основная идея здесь - это принцип единой ответственности . ProjectViewModel представляет, как проект отображается на экране. Класс домена Project представляет бизнес-логику и все, что связано с проектом, независимо от того, как эти данные отображаются на экране.

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

...