无论你选择做什么,总有人说你是错误的,又总有这样那样的困难诱使你相信批评你的人是对的。要找到一条正确之路并坚持到最后,你需要勇气。

一个项目的上下文映射图(Context Map)可以用两种方式来表示。

  • 简单的框图来表示两个或多个限界上下文之间的映射关系

该框图表示了不同的限界上下文在解决方案空间中是如何通过集成相互关联的。

  • 通过限界上下文集成的源代码实现来表示

上下文映射图为什么重要

在开始采用DDD时,首先你应该为你当前的项目绘制一个上下文映射图,其中应该包含你项目中当前的限界上下文和它们之间的集成关系。

图3.1表示一个抽象的上下文映射图,我们将不断地向里面添加细节内容。
image.png
以上这个简单的框图便可以作为你团队的上下文映射图。其他团队在实施DDD时应该创建它们自己的上下文映射图。上下文映射图主要帮助我们从解决方案空间看待问题。

绘制上下文映射图

上下文映射图表现的是项目当前的状态,如果项目会在将来发生变化,你可以到那时才对上下文映射图做相应的更新。关注啊于当前的项目状态可以帮助你了解你正处的出位,并帮助你决定如何走出下一步。

绘制一个上下文映射图并不复杂。通常,首选在白板上手绘映射图,此时不可以采用【Brandolini】的风格。如果你打算使用一个绘图工具来绘制上下文映射图,请注意不要把图画的太正式了。

回到图3.1中,途中限界上下文的名字和彼此之间的继承关系只是占位符而已,在真实的上下文映射图中,我们将代之以实际的名字。同时还展示了上游(upstream)和下游(downstream)两种集成关系。

为你的项目绘制一个简单的框图,其中包含不同的限界上下文、它们之间的关系,各个上下文的团队,上下文之间的集成和必要的翻译等。

当人们需要使用CollabOvation的功能时,他们扮演的是参与这、作者和主持者等角色。有了这样的角色分离,我们便可以绘制出一个更高层次的上下文映射图,如图3.4所示。团队使用了分离内核【Evans】对系统进行重构。
image.png

限界上下文之间的关系

这些限界上下文之间的关系如何,不同开发团队之间的关系又如何?在DDD中,存在多种组织模式和集成模式,其中,有一种模式存在于任意两个限界上下文之间。

合作关系(ParentShip)

如果两个限界上下文的团队要么一起成功,要么一起失败,此时他们需要建立起一种合作关系。他们需要一起协调开发计划和集成管理。两个团队应该在接口的演化上进行合作以同时满足两个系统的需求。应该为相互关联的软件功能制定好计划表,这样可以确保这些功能在同一个发布中完成。

共享内核(Shared Kernel)

对模型和代码的共享将产生一种紧密的依赖性,对于设计来说,这种依赖性可好可坏。我们需要为共享的部分模型指定一个显式边界,并保持共享内核的小型化。共享内核具有特殊的状态,在没有与另一个团队协商的情况下,这种状态是不能改变的。我们应该引入一种持续集成过程来保证共享内核与通用语言的一致性。

客户方-供应方开发(Customer-Supplier Development)

当两个团队处于一种上游-下游关系时,上游团队可能独立于下游团队完成开发,此时下游团队的开发可能受到很大影响。因此,在上游团队的计划中,我们应该顾及到下游团队的需求。

遵奉者(Conformist)

在存在上游-下游关系关系的两个团队中,如果上游团队已经没有动力提供下游团队之所需,下游团队便孤军无助了。出于利他主义,上游团队可能向下游团队做出种种承诺,但是有很大可能时:这些承诺是无法实现的。下游团队只能盲目地使用上游团队的模型。

防腐层(Anticorruption Layer)

在集成两个设计良好的限界上下文时,翻译曾可能很简单,甚至可以很优雅地实现。但是共享内核、合作关系或客户方-供应方关系无法顺利实现时,此时的翻译将变得复杂。对于下游客户来说,你需要根据自己的领域模型创建一个单独的层,该层作为上游系统的委派向你的系统提供的功能。防腐层通过已有的接口与其他系统交互,而其他系统只需要做很小的修改,甚至无须修改。在防腐层内部,它在你自己的模型和他方模型之间进行翻译转换。

开放主机服务(Open Host Service)

定义一种协议,让你的子系统通过该协议来访问你的服务。你需要将该协议公开,这样任何想与你集成的人都可以使用该协议。在有新的集成需求时,你应该对协议进行改进或者扩展。对于一些特殊的需求,你可以采用一次性的翻译予以处理,这样可以保持协议的简单性和连贯性。

发布语言(Published language)

在两个限界上下文之间翻译模型需要一种公用的语言。此时你应该发布出来的共享语言来完成集成交流。发布语言通常与开放主机服务一起使用。

另谋他路(SeparateWay)

在确定需求时,我们应该做到坚决彻底。如果两套功能没有显著的关系,那么他们是可以完全解耦的。集成总是昂贵的,有时带给你的好处也不大,声明两个限界上下文之间不存在任何关系,这样使得开发这去领来寻找简单的、专门的方法来解决问题。

大泥球(Big Ball of Mud)

当我们检查已有系统时,经常会发现系统中存在混杂在一起的模型,它们之间的边界非常模糊的。此时你应该为整个系统绘制一个边界,然后将其归纳在大泥球范围之列。在这个边界之内,不要试图使用复杂的建模手段化解问题。同时,这样的系统有可能会向其他系统蔓延,你应该对此保持警觉。