DDD:如何正确设计主细节屏幕的聚合?

时间:2016-12-28 16:09:09

标签: c# .net domain-driven-design aggregateroot

我有一个标题细节的屏幕, 标题是作业主要类别,详细信息是作业次要类别列表。我读了很多关于聚合物和它们的边界但是我发生了冲突。 我的要求: - 如何建模?

  • 我应该使用单一聚合(包含两个实体JobMajorCategory将是根聚合,而JobMinorCategory将是聚合内的实体),因为它们将保存在同一个事务中或
  • 两个聚合(一个用于JobMajorCategory,另一个用于JobMinorCategory),因为它们之间没有真正的不变量或业务角色

注意: - 屏幕上有一个保存按钮,可以在一个事务中将所有图形保存在一起(主文件+详细信息)。 此外,JobMinorCategory不能在没有父母的情况下生活。请告诉我如何正确设计这些聚合物?

1 个答案:

答案 0 :(得分:1)

您应该考虑设计一个满足您的UI考虑的视图模型或等效的DTO。这允许您将聚合关注于域,然后您可以通过转换聚合来加载表示。我知道您说您的业务用例是在谈论单一交易的方面,但这是一个技术细节。

当我们寻求应用域驱动设计时,它不是关于技术选择,也不是关于如何实现这一目标。相反,它是关于对实际业务领域进行建模。设计合理的域将不了解UI,也不会受到UI的影响。为此,我相信你说的是一个保存操作应该在一个操作中。这是完全没问题的,因为你的应用程序可能会在更高级别(如UI)更粗略,并且当你在堆栈中向下移动时更精细。

根据您的说法,您可能需要做的是在您的域和您的应用程序之间创建一个明确的边界。通常,这是通过应用程序服务完成的。这些"说"应用程序和域,以便他们可以与域通信,但只能表面DTO /模型。有效地隔离您的域可以防止域中的流失,然后更改为UI - 这肯定会比域本身更频繁地更改 - 具有隔离层。

更接近用户的代码和工件将更频繁地流失。该域名是关于"真理"与业务运作方式有关。为此,您的用户界面只是您所在域中的一个窗口 - 或者更恰当地说,它通常是对您域名抽象的视图。

编辑以专门解决问题的详细信息。

在您所描述的内容中,我对该域名不够了解,无法提供完整而准确的答案。但是,你走在正确的轨道上。由于JobMinorCategory在没有JobMajorCategory的情况下不能存在,因此可以公平地假设JobMinorCategory是实体或值对象(例如,如果它只是文本,并且对其他JobMinorCategories没有其他关系影响)。您仍然可以使用该前提来处理单个事务"。

为了论证,请说你有一个MVC应用程序。您的保存可以连接到通用"保存"行动。反过来,该控制器然后可以基于有效载荷确定要做什么。如果您将JobMinorCategory标记为排队等待删除,则在低于控制器的级别,您可以遍历这些项目,收集应删除的项目,并将其注册以删除您用于管理单位的任何内容工作

域名不会关心你在UI中如何做到这一点。但是,您的域可以公开删除JobMajorCategory的方法,这将删除所有JobMinorCategories。当你了解聚合本身时,那就是业务逻辑应该存在的地方。例如,您的JobMajorCategory应该具有DeleteJobMinorCategory()和AddJobMinorCategory()的方法。然后,一旦聚合的状态反映了您希望它处于的状态,您将从更高级别保留该聚合。根据您的整体架构,这可能来自域服务。

有几种方法可以做到这一点,复杂性各不相同。在不知道更多的情况下,我会假设在后端,您需要加载实际的Aggregate并根据用户操作应用更改。因此,如果您可以检查模型以查看用户是否删除了JobMinorCategory,您可以让您的域服务检索最新版本的Aggregate,调用RemoveJobMinorCategory()方法(这是您的业务逻辑将存在的位置),并且该方法已完成,您将使域服务保持更改的聚合。根据模型,您可能会检测到这种情况多次发生 - 即用户删除了多个JobMinorCategory。这也很好。你只需要多次调用RemoveJobMinorCategory()然后继续。

在正确实施的情况下,这是域驱动设计的优点之一。您将针对Aggregate进行多项操作,Aggregate将成为" gatekeeper"如果适用的业务逻辑允许更改,那么您将坚持它。由于持久性机制也是一个技术细节,我们希望将它保留在实际域对象之外的层上。就像应用程序服务充当UI /应用程序和域之间的桥梁一样,域服务可以充当域对象和技术细节之间的桥梁。

因此,如果您使用的是Entity Framework(其中包含一个工作单元,通过其上下文),您将加载您的实体,通过实体上的方法应用更改(部分类是执行此操作的一种方法),一旦完成,然后坚持回来。这允许您在单个事务中尽可能多地执行此操作。通常,您需要将事务限制为单个聚合,或至少限制一个有界上下文。

创作将以完全相同的方式运作。您可以创建JobMajorCategory聚合实例,并通过封装与添加它们相关的逻辑的方法添加JobMinorCategory实体。完成构建和/或修改后,即可提交这些更改。