Domain driven design 领域驱动的设计混乱

Domain driven design 领域驱动的设计混乱,domain-driven-design,Domain Driven Design,我正在学习DDD的概念,为了加强我的理解,我正在研究一些真实世界的例子 我知道聚合应该只有一个通过根实体的入口点,聚合应该只有一个存储库(如果我完全理解错了,请纠正我) 现在假设有特定类型的耗材,这些耗材是从配送中心发送的。发送特定类型的消耗品取决于其数量,我的意思是,如果其中一个消费者的a类和B类消耗品的临界数量为10,并且这些物品的数量低于10,则配送中心发送a类和B类消耗品。在这里,发送者和消费者都希望跟踪发送的包在哪里,或者它是否已交付或发送 因此,在这里,作为实体,我们有: 消耗品 消

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

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

现在假设有特定类型的耗材,这些耗材是从配送中心发送的。发送特定类型的消耗品取决于其数量,我的意思是,如果其中一个消费者的a类和B类消耗品的临界数量为10,并且这些物品的数量低于10,则配送中心发送a类和B类消耗品。在这里,发送者和消费者都希望跟踪发送的包在哪里,或者它是否已交付或发送

因此,在这里,作为实体,我们有:

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

  • 中心创建“A型”10
  • 中心创建“B型”20
  • 中心发送“类型A”5=25
  • 中心发送“类型B”15=25
  • ConsumerId=25接收“A型”5
  • ConsumerId=25接收“类型B”15
  • ConsumerId=25消耗“A类”3
  • ConsumerId=25消耗“B型”1
  • ConsumerId=25消耗“A类”2
  • 在这里,我们可以得出目前有5种A类和B类耗材位于中心,0种A类和14种B类耗材位于id为25的消费者处

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

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

    有谁能给我一些关于这个设计的改进建议,或者进一步阅读不限于客户产品订单的建议吗


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

    编辑2:考虑产品实体及其类别实体。产品似乎是根实体,但我们知道,没有类别,产品就不可能存在。那么,类别实体是根吗?如果是这样,根据DDD规则,我们只能通过遍历来访问产品。但在我们的环境中,产品是我们的重点。然后假设我们有两个集合:产品集合和类别集合。但是这次我们违反了数据完整性,因为一个类别可能会被删除,而不会删除具有该类别的产品。所以我很困惑,找不到合适的解决办法

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

    我要说的是,最有可能的情况是,您的聚合是包,即使这个示例有可能被拆分为两个或多个独立的有界上下文。(创建和订单履行是自然边界)

    消耗品和消费类型之间有什么关系

    这取决于您的上下文。除了由“A”或“B”指定之外,我不知道任何关于ConsumableType的信息,我不得不说它很可能是一个ConsumableType的价值对象

    如果我想在ConsumableType上执行CRUD操作(使 用户可以添加新类型、更改或删除它们),但根实体是 消耗品

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

    [不同示例]

    那么,类别实体是根吗

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

    [另一个例子]

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

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

    有人能给我一些改进建议吗