如何在不同的有界上下文中将学说实体拆分为更多的域实体?

Tom*_*Tom 5 php domain-driven-design doctrine-orm

我正在尝试DDD(域驱动设计)领域的第一步.我喜欢明智的规则,你应该将你的实体分成许多较小的,特定于上下文的实体(例如,User实体往往在每个非ddd或设计不佳的应用程序中都会过度生长).但是在使用Doctrine的php中如何(有效地)实现它的常见选项是什么?

假设我有两个有界的上下文:StoreInvoicing

它们中的每一个都有两个域实体:对于Store BC而言FirstTimeCustomer,RecurrentCustomer 对于Invoicing BC它是VatCustomerNonVatCustomer

现在,在我的基础设施层中,我希望它们全部保存在同一个(至少是基础)表中,以便能够通用UserId(Uuid)引用它们.对我来说问题是,如何做到这一点,所以我可以利用我的存储库实现中的doctrine自动化.

我读到了可能是解决方案的单表继承或类表继承,但是:

我需要能够使用User相同的Uuid,因为它在每个上下文中都是不同的类型.

我需要能够在商店BC中返回一些AbstractStoreCustomeraka FirstTimeCustomerRecurrentCustomeron $storeCustomerRepository->find(1);.

并在发票BC中返回一些AbstractInvoicingCustomeraka VatCustomerNonVatCustomeron $invoicingCustomerRepository->find(1);.

但似乎我被迫在这里选择BC我想要的实体的特定身份.所以在DDD的背景下对我来说根本没有意义.

我还阅读了Mapped Superclasses,它看起来也像是选项,但是:

这意味着根本不可能在映射的超类上进行一对多关联.

而且我需要Customer与订单有关系,这两个实体应该是可用的(也可能不希望它可用于User新BC中的一些新类型的实体).

我得出结论,我应该怀疑我错过了什么,是吗?我应该如何将上帝实体打造成更小的特定背景?

Con*_*enu 6

我将从一些一般规则开始.在考虑DDD时,您必须拒绝任何关于持久性的想法(表和主键等).您必须设计聚合根和实体,就像将它们存储在文件中一样.当你设计模型时,如果想到关于表或ORM的想法你就不能做DDD; 退一步重新开始.

正如我所看到的,你通过有限的上下文分割你的模型开始了.如果你没有通过BC拆分它们,你最终会想到包含所有行为的巨大模型,然后持久性会影响性能,因为在DDD中,聚合会持久存储在一个事务中.另一件事,尽量避免继承和使用组合.

话虽这么说,让我们谈谈你的业务.在Authentication卑诗省,有一些Users可以通过一些凭证进行身份验证.在Store卑诗省有Customers买东西.在InvoiceBC,也有Customers一个不同的模型(如果你想要一个不同的类).在ShippingBC省也有Customers一个不同的模型.这些Customer模型在BC上共享一些属性,例如nameid.因此,您使用它id来识别现实生活中的人,但使用不同的模型根据上下文封装他们的行为.

我认为你不应该有一个AbstractStoreCustomer,你应该只有Customer并尝试隔离它们在抽象类/接口中区分它们,就像BuyingHistoryProfile2实现FirstTimeCustomerRecurrentCustomer.这个类应该只包含关于行为购买的个人资料,应该由每一个被引用CustomerStoreBC.类似地,尝试在InvoicingBC中提取一个类来计算价格.

现在我们已经创建了模型,我们可以考虑持久性.对于每个有界上下文,创建一个Customer表,其中包含共享属性(nameid)和特定属性(buyingHistoryProfile对于StoreBC,priceCalculationStrategy对于InvoicingBC等).

如果您想知道存在一定程度的数据重复,那么您是对的,但这是正常的,有必要将模型分离.当BC中的名称更改其名称时User,将同步此重复数据Authentication:然后更新所有其他模型.从这个角度来看,InvoiceStoreBC是向下的料流,它们使用来自数据AuthenticationBC; 这取决于您的业务何时启动更新.

作为事件驱动架构的粉丝,我建议您看看CQRS(甚至是事件采购).我认为这些架构非常适合这个应用程序.根据我的经验,CQRS可以让你的模型清洁10倍.通过事件采购,您很可能甚至不必使用ORM.你可以ORM在阅读方面使用,如果你真的喜欢它们,或者你不能离开它们.我个人不喜欢(并且不使用)ORMs.

  • @Tom-是的,可以使用多个实体经理。检查文档以获取详细信息。可能需要做自己的映射和模式生成。请记住,DDD适用于具有复杂业务逻辑的应用程序。这将需要您付出额外的精力,并且您不应该对基于CRUD的工具抱有太大的期望。 (2认同)