领域驱动设计 - 创建通用实体与特定于上下文的实体

时间:2016-01-16 18:17:45

标签: oop entity domain-driven-design aggregate aggregateroot

场合

假设您的应用程序中有Orders和Clients作为实体。在一个聚合中,Order实体被视为根,但您也希望将Client实体用于简单的事物。在另一个中,客户端是根实体,订单实体被轻易触及。

示例:

假设在订单聚合中,我仅使用客户端来读取名称,地址,构建顺序历史等详细信息,而不是让客户端执行客户端特定的业务逻辑。 (比如持久性,密码重置和反向翻转......)。

另一方面,在客户端聚合中,我使用Order实体来报告客户的购买习惯,订单总数,订单计数,而不需要订单处理,更新,状态更改等高级订单功能。

可能的解决方案

我认为更好的解决方案是为特定于聚合上下文的每个聚合创建实体,因为使它们具有完整特征(通用)并且可以用于任何情况和使用似乎过度杀伤并且可能成为维护噩梦。 (并且可能存储密集型)

问题

DDD推荐的处理这种情况的方法是什么? 你对此事有何看法?

2 个答案:

答案 0 :(得分:1)

你是一个正确的轨道。在DDD中,实体不仅仅是封装与“主题”相关的所有属性的容器(例如:客户或订单)。这是一个非常重要的概念,躲过了很多人。 DDD中的实体表示操作边界,因此仅执行操作所需的数据被视为实体的一部分。确切地说,要包含在实体中的数据可能很难考虑,因为某些数据在不同的用例中是相关的。以下是分析数据时的一些提示:

  • 分析不变量,应用验证规则时必须考虑的事项以及不能不同步的事情应该在同一个聚合中。
  • 放弃数据库思考,规范化不是DDD的关注
  • 仅仅因为事情看起来一样,并不代表它们。例如:在客户上注册的当前送货地址与发送特定订单的送货地址不同。
  • 不要看读物。读取,如创建报告或填充av viewmodel / dto /与操作边界无关的任何内容,通常可以是数据的360度视图。事实上,在返回读取时,事件不会使用您的域模型,而是使用不同的架构堆栈。

答案 1 :(得分:1)

这些决策的基本驱动因素应该是无处不在的语言,因此也就是您正在建模的现实世界。如果两者都在特定领域中运作,那么出于可维护性原因,我赞成分离上帝类

除了将行为分成不同的聚合外,您还应该注意不要混合不同的有界上下文。根据您域的要求,将购买上下文报告上下文分开是有意义的(扩展您的示例)。

要决定上下文设计,上下文地图是一个有用的工具