当前位置: 首页 > 知识库问答 >
问题:

领域驱动的设计困惑

公冶森
2023-03-14

我正在学习DDD概念,为了加强我的理解,我正在研究一些现实世界的例子。

我知道一个聚合应该只有一个通过根实体的入口点,一个聚合应该只有一个存储库(如果我完全理解错了,请纠正我)

现在假设有特定类型的消耗品,并且这些消耗品是从配送中心发送的。发送特定类型的消耗品取决于它们的数量,我的意思是,如果其中一个消费者对A型和B型的临界数量为10,并且这些项目的数量低于10,那么配送中心发送A型和B型消耗品。在这里,发送者和消费者都希望跟踪发送的包裹在哪里,或者它是否被递送或发送。

因此,作为实体,我们有:

    < li >消耗品 < li >可消费类型 < li >可消费活动 < li >包装 < li>PackageItem < li >消费者

我对前三个实体感到困惑:哪一个应该是聚合根?在快速浏览中,消耗品似乎是一个强有力的候选者,但另一方面,我们不关心每一个消耗品,我们只对它们的数量感兴趣。我们不记录10种不同的A类消耗品,但只有一个A类记录,其数量根据活动而变化。在这一点上,消耗品实体似乎是多余的,通过查看活动,我们可以导出数量。例如从头开始:

  1. 居中创建“Type A”10
  2. 居中创建“Type B”20
  3. 中心发送“Type A”5 ConsumerId=25
  4. 中心发送“Type B”15 ConsumerId=25
  5. ConsumerId=25接收“Type A”5
  6. ConsumerId=25接收“Type B”15
  7. ConsumerId=25消费“Type A”3
  8. ConsumerId=25消费“B类”1
  9. ConsumerId=25消费“类型A”2

在这里,我们可以得出,目前在中心有5种A型和B型消耗品,在id为25的消费者处有0种A型和14种B型消耗品。

当然,这不是一个有效的方法,因为在有更多的活动之后,需要一些时间来推导消耗品数量,所以对于消费者和分销中心来说,每种消耗品类型都应该有一个静态数量字段,我们可以在其中立即读取当前数量。

我希望你明白我为什么感到困惑,可消耗实体看起来像一个根实体,但实际上它不适合成为根实体,如果不是实体的话。

有人能给我一些关于这个设计的改进建议吗?或者进一步阅读不仅限于客户-产品-订单-订单线噩梦的建议。

编辑:消耗品和消耗品类型有什么关系?如果我想在ConsumerableType上执行CRUD操作(让用户添加新类型,更改或删除它们),但根实体是Consumerable,该怎么办。为了DDD保持数据完整性,我们不应加载除根实体存储库之外的任何存储库。

编辑2:想想一个产品实体和它的类别实体。产品似乎是根实体,但我们知道产品不能没有类别而存在。那么类别实体是根吗?如果是这样,根据DDD规则,我们只能通过遍历来访问产品。但是在我们的上下文中,产品是我们的焦点。那么我们应该有两个聚合:产品聚合和类别聚合。但是这次我们违反了数据完整性,因为一个类别可能会被删除,而不会删除具有该类别的产品。所以我很困惑,找不到合适的解决方案。

共有1个答案

邵献
2023-03-14

我对前三个实体感到困惑:哪一个应该是聚合根?

我想说的是,最有可能的是,您的聚合是Package,尽管这个示例有可能被拆分为两个或多个单独的有界上下文。(创建和订单履行是自然的界限)

消费品和可消费型的关系是什么?

这取决于边界上下文。除了由“A”或“B”指定之外,我对 ConsumableType 一无所知,我不得不说它很可能是 Consumable 的值对象。

如果我想对ConsumableType进行CRUD操作(让用户添加新类型、更改或删除它们),但根实体是可消费的,该怎么办

这很可能是一个完全不同的有界上下文(某个经理的上下文或不属于我们正在建模的一般工作流的内容),建议对此上下文进行更多调查。

[不同的例子]

那么类别实体是根吗?

聚合根是上下文中的用户与之交互的内容。假设ALOT,因为您没有在此示例中完全解释上下文,很可能产品是聚合根,因为这是用户最关心的。与上面的示例相同,产品将有一个存储库,该存储库将加载它分配给它的类别。在这种情况下,加载类别或层次结构列表最好由域服务提供服务,因为它不属于任何特定的实体实例。

[另一个例子]

在第一种情况下,例如,系统管理员如何列出所有可用的字体颜色或添加新的字体颜色?

同样,系统管理员的上下文与选择字体颜色的用户的上下文不同。请记住,每个上下文都是一个工作流。在复杂的工作流中,可以有多个用户在同一个上下文中,但是对于管理员可能执行的简单工作流(如CRUD操作),通常这种类型的工作流只有一个角色。在系统管理员下,可用性字体颜色可能是内容装饰选项管理有界上下文中具有颜色值属性的实体。

谁能建议我对此设计进行一些改进或进一步阅读建议,这些建议不仅限于客户-产品-订单-订单线的噩梦?

我建议你更多地了解有限上下文,以及为什么它们是商业领域建模中最有用(有时也是最阻碍)的工具之一。此外,不要期望在一周内把它完善成一门科学。

我已经使用各种技术建模软件超过8年了,仍然有一些时候我很难决定我是否正确建模了一些东西。我认为DDD最大的好处之一是它鼓励你接受这样一个事实,即你可能不会从一开始就正确建模,所以你应该很容易地更改模型和重构,当你了解更多关于你的领域的信息时,而不是仅仅按照你所拥有的去做,最终在你的原始模型周围有15个不同的卷曲集群,因为你从一开始就没有完全理解这个领域。

 类似资料:
  • 本文向大家介绍谈一下领域驱动设计相关面试题,主要包含被问及谈一下领域驱动设计时的应答技巧和注意事项,需要的朋友参考一下 主要关注核心领域逻辑。基于领域的模型检测复杂设计。这涉及与公司层面领域方面的专家定期合作,以解决与领域相关的问题并改进应用程序的模型。在回答这个微服务面试问题时,您还需要提及DDD的核心基础知识。他们是: DDD主要关注领域逻辑和领域本身。 复杂的设计完全基于领域的模型。 为了改

  • 本文向大家介绍什么是领域驱动设计(DDD)相关面试题,主要包含被问及什么是领域驱动设计(DDD)时的应答技巧和注意事项,需要的朋友参考一下 专注于核心领域逻辑 在模型上找到综合的设计 不断与领域专家合作,改进应用程序模型并解决与领域相关的问题

  • null 到目前为止,很容易。如果我们试图将规范应用到存储库,而又不破坏DDD模式或存在性能问题,那么问题就会出现。 应用规范的可能方法: 1)经典方法:在领域层使用领域模型进行规范 null null 3)与2)类似,但将规范作为持久层的一部分 这不起作用,因为域层需要参考规范。它仍将取决于持久层。 我们将在持久层中拥有业务逻辑。这也违反了DDD模式 4)与3类似,但使用抽象规范作为接口 nul

  • Eric Evans在DDD中谈了很多关于模型进化的话题,所以重构似乎对DDD是必不可少的。当一个人拥有世界的关系持久化状态时,可以通过迁移来处理模型更改,从而更改数据库模式。 使用事件源时,如何应对模型更改?如果对聚合有不兼容的更改,这将阻止事件的重播,是否有某种最佳实践?还是只是不要?

  • 每个域对象包含与特定有界上下文(X)中的特定对象相关联的业务逻辑。REST API包含将查询或命令的结果转换为通过网络发送的数据(例如JSON)的逻辑。当使用HATEOAS和超媒体时,我们希望使用链接来建模资源之间的关系。但是,为了确定REST API应该返回哪些链接,通常需要求助于业务逻辑/规则。问题是,这些“工作流规则”在DDD应用程序中属于哪里?它们可能在一个不同的有界上下文中只处理工作流规

  • 本文向大家介绍为什么需要域驱动设计(DDD)?相关面试题,主要包含被问及为什么需要域驱动设计(DDD)?时的应答技巧和注意事项,需要的朋友参考一下 映射领域 降低复杂性 可测试性 可维护性 知识丰富的设计 将业务和服务结合在一起 上下文集中 通用语言