我正在学习DDD概念并加强我的理解,我正在研究一些现实世界的例子。
我知道聚合应该只有一个通过根实体的入口点,聚合应该只有一个存储库(如果我完全错误,请纠正我)
现在假设有特定类型的消耗品,这些消耗品是从配送中心发送的。发送特定类型的消耗品取决于其数量,我的意思是,如果其中一个消费者对A型和B型具有批评数量10并且那些项目数量低于10,则配送中心发送A型和B型消耗品。在这里,发件人和消费者都希望跟踪发送的包裹的位置,或者是否已经发送或发送包裹。
所以在这里,作为实体,我们有:
我对前三个实体感到困惑:哪一个应该是聚合根?快速看来,消费品似乎是一个强有力的候选者,但另一方面,我们并不关心每一种消费品,我们只对它们的数量感兴趣。我们不记录10种不同的A类消耗品,但只有A型记录,其数量根据活动而变化。在这一点上,消耗品实体似乎是多余的,只需查看我们可以推导出数量的活动。例如从头开始:
在这里,我们可以推导出中心有5种A型和B型消耗品,而消费者现在有0种A型,14种B型消耗品,ID为25。
当然,这不是一种有效的方法,而在有更多的活动之后,需要一些时间来获得消耗品,因此对于消费者和我们所在的配送中心,每种消耗品都应该有一个静态数量字段。可以一次读取当前数量。
我希望你明白为什么我感到困惑,消耗品实体看起来像是一个根实体,但实际上它并不真正适合作为根实体,如果不是实体的话。
有人可以建议我对这个设计进行一些改进,还是进一步阅读建议,而不仅限于客户产品订单 - 订单线的噩梦?
编辑:与耗材和耗材类型的关系是什么?如果我想对ConsumableType进行CRUD操作(使用户添加新类型,更改或删除它们)但根实体是消耗品,该怎么办?为了使DDD保持数据完整性,我们不应加载除根实体存储库之外的任何存储库。
编辑2:考虑产品实体及其类别实体。产品似乎是根实体,但我们知道没有类别的产品不可能存在。那么类实体是根吗?如果是这样,根据DDD规则,我们只能通过遍历来访问产品。但在我们的背景下,产品是我们的重点。然后我们假设我们有两个聚合:Product Aggregate和Category Aggregate。但是这次我们违反了数据完整性,因为可以删除类别而不删除具有此类别的产品。所以我很困惑,无法找到合适的解决方案。
答案 0 :(得分:2)
我对前三个实体感到困惑:应该是哪一个 聚合根?
我要说的是,即使有可能将此示例拆分为两个或更多单独的有界上下文,但最有可能的是,您的聚合是Package。 (创造和订单履行是自然界限)
与耗材和耗材类型的关系是什么?
这取决于你有限的背景。除了被“A”或“B”指定之外,我不知道更多关于ConsumableType的消息,我不得不说它很可能是消耗品的价值对象。
如果我想对ConsumableType进行CRUD操作怎么办? 用户添加新类型,更改或删除它们,但根实体是 消耗品
这很可能是一个完全不同的有界背景(一些经理的背景或某些不属于我们正在建模的一般工作流程的内容),建议对此进行更多调查。
[不同的例子]
类别实体是根吗?
聚合根是上下文中的用户与之交互的内容。假设ALOT因为您没有完全解释此示例中的上下文,很可能产品是聚合根,因为这是用户最关心的。与上面的示例相同,Product会有一个存储库,可以将其分配的类别加载到它。在这种情况下,加载域类别或层次结构列表最好由域服务提供,因为它不属于任何特定的实体实例。
[另一个例子]
在您的第一种情况下,如何,例如系统管理员,列表 所有可用的字体颜色或添加新颜色?
同样,系统管理员的上下文与选择字体颜色的用户的上下文不同。请记住,每个上下文都是一个工作流程。在复杂的工作流程中,同一上下文中可能有多个用户,但对于简单的工作流程(如管理员可能执行的CRUD操作),此类工作流程通常只有一个角色。在系统管理员下,AvailableFontColor可能是Content Decoration Options Administration有界上下文中具有Color值属性的实体。
任何人都可以建议我对这个设计进行一些改进或者 进一步阅读建议,不限于此 客户 - 产品 - 订单 - 订单线噩梦?
我建议您了解有限上下文以及为什么它们是您在业务领域建模中最有用(也是最有阻碍的)工具之一。此外,不要指望在一周内完成科学研究。
我已经使用各种技术对软件进行了超过8年的建模,而且我仍然无法确定是否正确建模。我认为DDD的最大好处之一是它鼓励你接受这样一个事实,即你可能从一开始就不能正确建模,所以当你更多地了解你的领域时,你应该很容易改变模型和重构。而不是仅仅使用你拥有的东西,最后在原始模型周围使用15个不同的复杂的cludges,因为你从一开始就没有完全理解这个领域。