我正在实现有界上下文之间的交互,我发现它“某种程度”削弱了开放封闭原则,我不确定它是设计BCs的自然结果,还是考虑到共同的权衡,还是我的设计失败。
考虑一下BC商店,您可以在那里用一些商品创建购物车外订单。创建的顺序由OrderItem
组成,每个顺序包含ProductSpecification
或FooServiceSpecification
等各种类型的ItemSpecification
值对象接口中的一种,保护不变量并包含一些数据。在创建Order时,发出任何其他BC都可以侦听的异步事件。
异步事件按顺序创建,并表示为(序列化的) OrderCreatedEvent对象,包含OrderDTO对象,所有对象都放在与每个BC共享的核心命名空间中,这样任何BC都可以依赖Core,而不是依赖其他方式。到目前为止一切都很好,几乎:
OrderItemDTO必须包含接口ItemSpecificationDTO
,这需要为每种类型的规范实现。我的ItemSpecification
VO (与其他所有VO/Entity有序的)一样,具有toCoreDTO()
方法,能够实现简单的翻译,同时也使得实现新的ItemSpecification
相对困难,而忘记了按DTO的实现。可能没什么关系。
但是,其他收听这一事件的不列颠哥伦比亚省呢?在每个BC中,这个事件都需要在它的AntiCorruption层中进行翻译,而BC可能只对某些类型的ItemSpecificationDTO
感兴趣,并将它们转换为各种值对象,这对于特定BC非常重要。
正如鲍勃叔叔在谈到OCP时所说的那样:
您应该能够扩展系统的行为,而不必修改该系统。
但是当我实现新类型的ItemSpecification
时,对于可能对这种新类型感兴趣的每一个BC,我都需要从CoreDTO中具体地翻译这个新类型(好的,我可以为每个BC中的翻译编写一些抽象,所以我仍然只是添加代码,而不改变添加if($x instanceof X)之类的东西)。但是,通过添加新类型的ItemSpecification
,我需要在其他BCs中进行适当的扩展(甚至修改一些东西,因为我们并不生活在理想的世界中)。
我不知道该怎么想。这就是整个DDD方法的缺点吗?或者可能确实具有这样的特性,因为在其他BCs中寻找需要进一步扩展的内容、位置和方式,是由域需求驱动的,而不是技术问题?这似乎是对的。最后,我试图做域驱动的设计:-),但在我看来,这似乎也是危险的。我担心有一天,我们会忘记更新一些其他的BC和一些不好的事情发生。但这可能是因为我在领域专家的角色中也扮演了很大的角色,在这个角色下,“恐惧”应该属于我。我的问题是坐在两把椅子上还是出了什么问题?
发布于 2017-05-12 08:46:47
关于这个主题有很多有趣的细节,但我将在这里集中讨论有限上下文的一个特定方面。
那就是他们被限制是有原因的。与之一样,在模型/对这些背景的理解之间应该有一个界限。两种情况,即使它们是相关的,也应该对系统有不同的看法,甚至对可能部分共享的数据也有不同的看法。
在我看来,您的“有限上下文”希望在相同的模型上工作。你甚至创建了一个“核心”模型,每个人都能看到,而且显然必须能够理解。如果是这样的话,我会说你失去了拥有不同环境的好处,你只是在用一个模型创建一个大应用程序。
要纠正这个问题,我认为您需要摆脱任何中央/核心模型,并在不同的上下文/服务中使用“本地”(有界)模型。当您需要与其他组件通信时,您需要为这两个组件定义一个协议,由任何一方或双方指定。
例如,购物车可能需要知道后端系统的产品id才能在那里创建订单。但是后端系统不需要知道购物车用来了解订单的模型(在自己的模型中)。
https://stackoverflow.com/questions/43927924
复制相似问题