领域驱动设计系列文章,点击上方合集↑
1. 开头
在DDD中,限界上下文与限界上下文之间需要相互集成,这种集成关系在DDD中称为上下文映射(Context Mapping),也就是子域与子域之间的集成关系。
所以首先我们应该为我们的项目绘制一个上下文映射图,其中应该包含你项目中当前的限界上下文和它们之间的集成关系。
- 上图来自《实现领域驱动》这本书
- U表示上游(Upstream), D表示下游(Downstream)
连接两个限界上下文之间的这条线段就代表了上下文映射。换句话说,这条线段表示这两个限界上下文之间存在着某种形式的映射,包括两个限界上下文之间的集成关系以及团队间的动态关系。(在某些情况下,团队间关系和集成映射会被混合在一起)。
2. 上下文映射类型
这些限界上下文之间的关系如何,不同开发团队之间的关系又如何?在DDD中,存在多种组织模式和集成模式:
-
合作关系(Partnership):如果两个限界上下文的团队要么一起成功,要么一起失败,此时他们需要建立起一种合作关系。他们需要一起协调开发计划和集成管理。两个团队应该在接口的演化上进行合作以同时满足两个系统的需求。应该为相互关联的软件功能制定好计划表,这样可以确保这些功能在同一个发布中完成。
-
共享内核(Shared Kernel):对模型和代码的共享将产生一种紧密的依赖性,对于设计来说,这种依赖性可好可坏。我们需要为共享的部分模型指定一个显式的边界,并保持共享内核的小型化。共享内核具有特殊的状态,在没有与另一个团队协商的情况下,这种状态是不能改变的。我们应该引入一种持续集成过程来保证共享内核与通用语言(1)的一致性。
-
客户方-供应方开发(Customer-Supplier Development):当两个团队处于一种上游-下游关系时,上游团队可能独立于下游团队完成开发,此时下游团队的开发可能会受到很大的影响。因此,在上游团队的计划中,我们应该顾及到下游团队的需求。
-
遵奉者(Conformist):在存在上游-下游关系的两个团队中,如果上游团队已经没有动力提供下游团队之所需,下游团队便孤军无助了。出于利他主义,上游团队可能向下游团队做出种种承诺,但是有很大的可能是:这些承诺是无法实现的。下游团队只能盲目地使用上游团队的模型。
-
防腐层(Anticorruption Layer):在集成两个设计良好的限界上下文时,翻译层可能很简单,甚至可以很优雅地实现。但是,当共享内核、合作关系或客户方-供应方关系无法顺利实现时,此时的翻译将变得复杂。对于下游客户来说,你需要根据自己的领域模型创建一个单独的层,该层作为上游系统的委派向你的系统提供功能。防腐层通过已有的接口与其他系统交互,而其他系统只需要做很小的修改,甚至无须修改。在防腐层内部,它在你自己的模型和他方模型之间进行翻译转换。
-
开放主机服务(Open Host Service):定义一种协议,让你的子系统通过该协议来访问你的服务。你需要将该协议公开,这样任何想与你集成的人都可以使用该协议。在有新的集成需求时,你应该对协议进行改进或者扩展。对于一些特殊的需求,你可以采用一次性的翻译予以处理,这样可以保持协议的简单性和连贯性。
-
发布语言(Published Language):在两个限界上下文之间翻译模型需要一种公用的语言。此时你应该使用一种发布出来的共享语言来完成集成交流。发布语言通常与开放主机服务一起使用。
· 另谋他路(SeparateWay):在确定需求时,我们应该做到坚决彻底。如果两套功能没有显著的关系,那么它们是可以被完全解耦的。集成总是昂贵的,有时带给你的好处也不大。声明两个限界上下文之间不存在任何关系,这样使得开发者去另外寻找简单的、专门的方法来解决问题。
-
大泥球(Big Ball of Mud):当我们检查已有系统时,经常会发现系统中存在混杂在一起的模型,它们之间的边界是非常模糊的。此时你应该为整个系统绘制一个边界,然后将其归纳在大泥球范围之列。在这个边界之内,不要试图使用复杂的建模手段来化解问题。同时,这样的系统有可能会向其他系统蔓延,你应该对此保持警觉。
事实上,我们很多系统都是大泥球,很多时候交到你手上的系统可能由很多人经手过,没有任何设计可言,其代码混乱甚至没有注释。但是你必须在这样的大泥球系统里加上领导安排给你的新的功能模块,这样的系统很难去拆分优化,可能牵一发而动全身。最好的方法就是先不要操刀动这样的大泥球,针对这样的大泥球也就是遗留系统,我们可以创建一个防腐层,保护自己的模型免受污染,否则会陷入难以理解的泥潭。
结语
了解这些上下文映射策略可以帮助我们更好地组织和管理不同领域之间的交互,使系统更加灵活和可维护。通过明确定义上下文的边界和交互规则,我们可以更好地设计和实现复杂的软件系统。
关注微信公众号:"小虎哥的技术博客",让我们一起成为更优秀的程序员❤️!