领域驱动设计 101- 上下文与持续集成
前面我们已经讨论了领域、模型、通用语言以及分层设计这些领域驱动设计中的基础概念。现在,让我们来认识领域驱动设计中战略设计相关的概念。
Bounded Context
%Thoughts%
在几乎所有领域驱动的中文材料中,将 Bounded Context 都翻译为限界上下文。首先,“限界”这一词语在汉语中并不常见,能够搜索到的材料也是在铁路专业领域中,虽然仔细研究一下这个词汇并不难理解其最基本的意思,但由于不常见,用起来总是显得不那么顺畅。其次,一个上下文作为上下文本身就决定了是有边界的,也就是有限定的边界的,所以 Bounded 似乎稍显多余。
我想 Eric 在创造这个概念时,之所以加上了 Bounded,是为了强调 Context 应该边界应该是清晰、明确的这一点。翻译过来之后,如果不加修饰简单称为上下文,似乎又不妥当。但同时,我也想不出更理想的翻译,所以只能暂且接受这个叫法。只是需要明确的是,限界上下文,核心在于上下文。
作为公共系统的负责人,我参与过的一些项目中,出现了“外汇”这个概念,而且不同同事和我沟通的时候说的似乎是两种东西,这让人非常迷惑,经过自己研究之后,我终于搞明白了在不同的语境下面,大家说“外汇”的时候到底在讲什么。
结售汇产品:更接近在一般语境中的外汇概念,例如常说的国家外汇储备等。在银行系统中,结售汇主要是面向企业或者个人客户提供人民币与外币之间的兑换业务。
双向外汇:从货币组成关系上看,结售汇是人民币(本币)与外币之间的,而双向外汇是两种外币之间的汇率关系,客户可以通过买卖双向外汇产品来获取收益。
在搞清楚这两种称呼在不同语境下的所指以后,后来再有同事与我提到外汇而语境不甚清晰的时候,我都会和他先确认,你说的“外汇”是指“结售汇”还是“外汇交易”(实际上我会更直接地说是两种外币构成的产品,还是人民币和外币构成的产品)。
这看起来是一个混用通用语言的例子,在不同的业务领域里面,同一个词汇表达了不同的概念。但与此同时,考虑一下负责结售汇系统的开发人员和负责外汇交易系统的开发人员,当他们在各自的项目环境中工作时,同事之间的沟通肯定是顺畅的,因为大家对于这个概念的理解都是一致的,不会像我一样搞不清楚到底在说哪种产品。而我之所以产生了对两种概念的混淆,是因为我负责的系统刚好位于两个项目的重叠区域。
为了解开自己的疑惑,我通过了解相关概念掌握了同事口中的“外汇”在不同场景下所表达的不同意思,当我与结售汇系统的开发人员沟通时,我会把外汇等价于结售汇产品,另一种情况下,我将外汇等价于外汇交易产品。
上面我做等价转化时所处的不同场景,实际上就体现了限界上下文的概念。
限界上下文
在同一个上下文中使用同一个或一致的模型,在不同的上下文中使用不同的模型。一个限界上下文有明确、清晰的边界,在这个边界之内每个概念都有确定的含义,开发人员无需进行额外的解释或者转换。
通过规定明确的范围和边界,可以简化开发设计人员在之间的沟通,团队成员对于模型有着共同的、一致的理解。通过规定范围和边界,也限定了模型的应用范围,在边界之内,模型是一致、明确的;在边界之外,模型不可用,边界之外的模型团队成员也无需关心。
我们再从反面看看,假设没有明确边界的上下文,会有什么问题:
由于边界不清晰,模型和模型中的概念会出现模糊不清的情况。当我向同事明确“外汇”到底指什么的时候就是出现了边界不清晰的情况。
在大型项目中,使用一个模型统一一切不切实际。假设“结售汇”和“外汇交易”没有分为两个系统,那么很可能团队成员很可能一直处在混乱之中,这不仅是概念上的混淆,还会出现由于模型其他方面重叠导致的混乱。
由于边界不清晰,范围将无法控制。假设一个项目在一开始没有明确自己的范围,那么很可能随着项目的进行,会实施一些超出项目边界的内容,这要么引起重复工作,要么体现为无效工作。
总之,需要有一个明确边界的上下文用于限定软件设计开发的范围,这就是限界上下文。
Context Map
上面已经提到,在大型项目或者企业当中,不可能将所有的对象都纳入到一个模型中考虑,这无论从复杂度或者可行性上都是不切实际的。
抛开日渐兴起的微服务将应用划分为更加小的独立模块的现状,在传统应用系统的开发中,还是会将关联程度高的功能放到一个系统中,如果一个系统过大,那么可能会将系统划分为如果模块,这些模块可能会有一些联系,但也不会是非常紧密的联系。
对于上下文来说,需要与其他的上下文之间进行协作交互,必然涉及到模型知识的传递。在较为原始的实践中,系统之间可能需要通过分享编译前或者编译后的代码来实现系统之间的交互,这种程度不同的代码复用会提高系统的耦合程度。DDD 倡导采用更低耦合的系统间通信方式,例如 REST 或者消息队列,降低系统之间的耦合程度。
在领域驱动设计中,当我们划分完限界上下文之后,和其他软件工程的设计方法一样,需要找到不同的上下文之间的关系及其关联方式。这就体现为 Context Map。
Context Map
定义系统不同上下文之间的关系
以全局视图的形式体现所有上下文间的连接关系
明确所有系统间通信需要进行的转换
突出任何系统间共享的内容
如何规划 Context Map,在软件工程中同时涉及到了项目管理以及软件设计两个领域,因为这涉及到:
组织的划分与组织间关系:负责不同的 Context 的组很可能位于不同的团队中,他们之间的组织关系决定他们的协作方式和便捷性。
组织与模型设计间的关系:Context 的划分体现了组织的划分,将一个 Context 交给两个开发组共同负责是不太可能的,两个交互频繁的 Context 开发组位于两个异地的部门也会引入巨大的沟通开销。
模型与模型间的关系:这是 Context Map 体现的最显著的内容。
所以,如何划分 Context Map 需要综合考虑组织结构、项目管理方式以及软件设计原则,单纯考虑某一个方面最终的划分都将难以落地。
最后,Context Map 无需拘泥于任何文档形式,可以为文字描述、正式非正式的图形、或者文字与图形的混合等等,甚至还可以是设计者之间的非书面讨论,只要最终 Context Map 被所有设计人员所理解、接受即可。
版权声明: 本文为 InfoQ 作者【luojiahu】的原创文章。
原文链接:【http://xie.infoq.cn/article/6eaf90a0206dcb00cd0a3f787】。文章转载请联系作者。
评论