2

我正在尝试使用域驱动设计,同时创建一个可公开访问的网站。我遇到的一个问题是试图弄清楚我的模型的聚合根应该是什么。我非常清楚哪些对象是实体对象,哪些对象是值对象。

我的站点与大多数公共站点一样,不允许每个用户查看存储在站点中的每条信息。相反,他们只能看到自己拥有的信息。对于我的站点,用户将创建“项目”,他们也可以与其他用户共享。然而,用户仍然只能看到他们创建或受邀加入的项目中的信息。我的模型中的所有其他对象都存在于一个项目中,如果一个项目被删除,它包含的所有对象也应该被删除。

那么这是否意味着我应该拥有一个主要的“Project”聚合根类型和一个“ProjectRepository”存储库?每次请求我网站上的任何页面时,加载整个项目对我来说似乎效率低下。实际上,这不是什么大问题,因为我使用的是 NHibernate,它只会延迟加载项目中请求的项目。然而,让网站的效率如此依赖于使用延迟加载的 ORM 似乎是糟糕的设计。


这是一个更新,希望能让我的问题更清楚。

首先,我试图了解我的项目类型是否应该是我的模型的聚合根。项目可以单独存在,而报告必须存在于项目中。如果删除项目,则应删除相应的报告。这是否意味着 Project 可以或应该是聚合根?这个我不是很清楚。

如果 Project 是聚合根,那么 Report 应该不正确?据我了解,根不应嵌套在 DDD 中。此外,只允许从存储库中检索聚合根。因此,如果 Report 不是聚合根目录,那么我不应该有 ReportsRepository,而应该只通过从 ProjectsRepository 检索到的项目访问报告。因此,即使页面只需要来自单个报表的数据,它也需要从 ProjectRepository 加载整个项目才能获取报表。

此外,如果 Project 是包含 Reports 的聚合根,则也可以设置从 ProjectRepository 中删除 Project 以删除它包含的 Reports。但是,如果 Project 和 Report 都是聚合根,那么在删除 Project 时不允许 ProjectRepository 删除 Reports 会打破聚合之间的界限吗?聚合根及其相应的存储库不是应该相互独立吗?

4

1 回答 1

1

我认为你混淆了担忧。安全性(谁可以查看什么)不是域问题。不要让它污染您的域。如果用户无法查看项目中的报告,请在域模型以外的其他地方强制执行。

此外,我认为您可能会受益于将 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实例。

然后,通过在 UI 中提交表单调用的控制器操作如下所示:

    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。

于 2011-06-20T19:49:04.973 回答