DDD领域驱动设计-上下文映射

上下文映射(Context Map)表示了一组不同的限界上下文在解决空间中如何通过集成所形成的相互关联和依赖关系。

上下文映射图的绘制

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

所绘制的所有映射图,包括文字,都可以装订在同一份参考文档中,只要这对团队是有价值的。在这个过程中,我们应该避免那些繁文缛节性的仪式,保持简单和敏捷。向框图中加人过多的细节对团队并无多大帮助,交流才是关键,我们应该将交流对话也加人到上下文映射图中。

上下文映射图并不是一种企业架构,也不是系统拓扑图。但是,它可以用于高层次的架构分析,指出诸如集成瓶颈之类的架构不足。上下文映射图展现了一种组织动态能力(organizational dynamic),它可以帮助我们识别出有碍项目进展的一些管理问题。

我们用Upstream的首字母U来标识“上游”,用Downstream的首字母D来标识“下游”。那怎么去判断“上游”还是“下游”呢?这里有一个原则:下游的模型依赖于上游的模型和服务

以上这个简单的框图便可以作为你团队的上下文映射图。其他团队在实施 DDD时应该创建他们自己的上下文映射图。上下文映射图主要帮助我们从解决方案空间的角度看待问题。

限界上下文之间的关系

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

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

  • 客户方-供应方开发(Customer-Supplier Development):当两个团队处于一种上游-下游关系时,上游团队可能独立于下游团队完成开发,此时下游团队的开发可能会受到很大的影响。因此,在上游团队的计划中,我们应该顾及到下游团队的需求。

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

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

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

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

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

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

在集成时,提倡使用开放主机服务和发布语言,有可能还会用到防腐层。虽然这两者都会在限界上下文之间创建开放的标准,但是它们并不矛盾。通过使用下游上下文中的基本原则,他们依然可以得到由独立翻译所带来的好处,并且不会像与大泥球集成时那样复杂。翻译层将变得简单、优雅。

这里所指的翻译,即通过建立一套标准的发布语言,使得上游和下游上下文之间解耦。独立的翻译层能够起到防腐的重要,一旦上游发生变化,不会直接影响到下游上下文。

在上下文映射图中,我们使用以下缩写来表示各种关系:

• ACL表示防腐层

• OHS表示开放主机服务

• PL表示发布语言

映射图中,请注意上游系统的连接框,它们都标以OHS/PL,分别表示开放主机服务和发布语言。所有下游系统的连接框都标以ACL,即防腐层。这些集成模式将采用以下技术:

  • 开放主机服务:该模式可以通过REST实现。通常来讲,我们可以将开放主机服务看成是远程过程调用(RemoteProcedureCall, RPC)的API。同时,它也可以通过消息机制实现。

  • 发布语言:发布语言可以通过多种方式实现,但最常见的是使用XML Schema。在使用REST服务时,发布语言用来表示领域概念,此时可以使用XML和JSON。发布语言也可以使用Google的协议缓冲(Protocol Buffer)来表示。如果你打算发布Web用户界面,你也可以使用HTML。使用REST的好处在于每个客户端都可以指明使用哪种发布语言,同时还可以指明资源的展现方法。REST的另一个优点是超媒体(Hypermedia)展现,即HATEOAS (Hypermedia As The Engine Of Application State)。超媒体赋予发布语言以动态性和可交互性,使得客户端可以访问一系列彼此链接的资源。发布语言既可以使用标准的媒体类型进行发布,也可以使用自定义类型。同时,发布语言还可以用于事件驱动架构(Event-Driven Architecture), 其中领域事件(Domain Event)以消息的形式发送到订阅方。

  • 防腐层:在下游上下文中,我们可以为每个防腐层定义相应的领域服务 (Domain Service,)。同时,你也可以将防腐层用于资源库接口。在使用REST时,客户端的领域服务将访问远程的开放主机服务,远程服务器以发布语言的形式返回,下游的防腐层将返回内容翻译成本地上下文的领域对象。比如,协作上下文向身份与访问上下文请求“具有Moderator角色的用户”。所返回的数据可能是XML格式或JSON格式,然后防腐层将这些数据翻译成协作上下文中的Moderator对象,该对象是一个值对象。这个Moderator实例反映的是下游模型中的概念,而不是上游模型。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

haoxin963

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值