现实世界中领域和子域
领域中还同时存在问题空间(problem space)和解决方案空间(solution space)。在问题空间中,我们思考的是业务所面临的挑战,而在解决方案空间中,我们思考如何实现软件以解决这些业务挑战。以下是如何将这两者应用到我们已经学过的知识中:
- 问题空间是领域的一部分,对问题空间的开发将产生一个新的核心域。对问题空间的评估应该同时考虑已有子域和额外所需子域。因此,问题空间是核心域和其他子域的组合。问题空间中的子域通常随着项目的不同而不同,他们各自关注于当前的业务问题,这使得子域对于问题空间的评估非常有用。子域允许我们快速地浏览领域中的各个方面,这些方面对于解决特定的问题是必要的。
- 解决方案空间包括一个或多个限界上下文,即一组特定的软件模型。这是因为限界上下文即是一个特定的解决方案,它通过软件的方式来实现解决方案。
通常,我们希望将子域一对一地对应到限界上下文。这种做法显式地将领域模型分离到不同的业务板块中,并将问题空间和解决方案空间融合在一起。在实践中,这种做法并不总是可能的,但通过新的努力,我们是可以做到这一点的。让我们考虑一个遗留系统,它有可能是个大泥球,其中子域和限界上下文存在相交的地方,就像图2.1中所示一样。在一个大型的企业中,通过对问题空间的评估,我们可以减少错误,进而降低成本。我们可以在概念上使用两个或者多个子域来分解限界上下文,或者将多个限界上下文包含在同一个子域中。为了澄清问题空间和解决方案空间的区别,让我们来看一个例子。
让我们来看看一个大型的ERP系统。严格地讲,我们可以将一个ERP系统想象成一个单一的限界上下文。然而,由于ERP系统提供许多模块化的业务服务,将不同的模块看成不同的子域是有好处的。比如,我们可以将库存模块和采购模块拆分成不同的逻辑子域。我们将它们分别命名为库存子域(Inventory Subdomain)和采购子域(Purchasing Subdomain),在下文中,我们将讲到为什么这种划分是有用的。
图2.4表示一个ERP系统的领域,也是图2.2中所示模板的一个实例。该企业计划开发一个特定的领域模型来降低成本,该模型可以为采购人员提供决策工具。从多年人工处理过程中积累起来的算法将通过软件实现自动化。这个新的核心域可以大大地提高该企业的竞争优势。为了能准确地管理库存,可以借助图2.1中的预测系统。
在我们实施某个解决方案之前,我们需要对问题空间和解决方案空间进行评估。为了保证你的项目朝着正确的方向行进,你需要先回答以下问题:
- 这个战略核心域的名字是什么,它的目标是什么?
- 这个战略核心域中包含哪些概念?
- 这个核心域的支撑子域和通用子域是什么?
- 如何安排项目人员?
- 你能组建出一支合适的团队吗?
白板时间
看看你白板上的内容,然后想想:你的问题空间是什么?再回想一下:问题空间由战略核心域及其支撑子域组成。
在理解了问题空间之后,我们来看看解决方案空间。对于问题空间的评估也是有益于理解解决方案空间的。解决方案空间在很大程度上受到现有系统和技术的影响。这里,我们应该根据分离的限界上下文仔细地思考,考虑以下问题:
- 有哪些软件资产是已经存在的,它们可以重用吗?
- 哪些资产是需要创建的,或者从别处获得?
- 这些资产是如何集成在一起的?
- 还需要什么样的集成?
- 假设已经有了现有资产和那些需要被创建的资产,我们还需要做些什么?
- 核心域和那些支撑项目的成功几率如何?会不会出现由于其中一个失败而导致整个项目失败的可能?
- 在哪些地方我们使用了完全不同的术语?
- 限界上下文之间在哪些地方存在概念重叠?
- 这些重叠的概念在不同的限界上下文之间是如何映射和翻译的?
- 哪些限界上下文包含了核心域中的概念,其中使用了哪些[Evans]中的战术模式?
请记住,开发核心域的解决方案是一种关键性业务投入。
在图2.4中,用于捕获决策工具和算法的采购模型表示了核心域的解决方案。该领域模型将在最优获取上下文(Optimal Acquisitions Context)中实现,该上下文与最优获取核心域(Optimal Acquisitions Core Domain)存在着一对一的关系。由于只对应于一个子域,同时又拥有优秀的领域模型,这个最优获取上下文将会是业务领域中最好的限界上下文之一。
除了最优获取上下文,还有采购上下文(Purchasing Context)。该上下文用于辅助最优获取上下文,以改进釆购过程中的技术细节。这些改进并不显露最优采购上下文中的特定信息,只是简化了最优采购上下文和ERP的交互,也即是一个用于操作ERP接口的便捷模型。这个新的采购上下文和先前的ERP采购模块同属于采购(支撑)子域。
整个ERP采购模块是一个通用子域,你甚至可以购买另外的采购系统来替换该子域,只要它满足你的业务需求即可。然而,在采购子域中,我们将该采购模块与采购上下文共同使用,这使得该模块多少有些支撑子域的意味。
你所不能改变的
在一个典型的不健康的企业系统里,你通常会面临如图2.1和图2.4所示的情形。在设计欠佳的软件里,子域和限界上下文之间很难存在一对一的映射关系。这种劣质软件的大量存在已经成为事实,并且是你所不能改变的事实。你只能盼着在项目中通过合适的手段实施DDD,但最终你都需要和那些“不健康”的领域进行集成。因此,当你在分析某个“不健康”限界上下文中的多个隐式模型时,请好好温习一下本章前面所教给你的那些技能。
在图2.4中,最优获取上下文还需要和库存上下文(Inventory Context)进行交互。库存系统用于管理仓库中的物件,它使用ERP的库存模块,该模块位于库存(支撑)子域中。为了给货递合同方提供方便,库存上下文还采用了第三方的地图服务。对于库存上下文而言,地图服务并没有什么特别之处,你可以选择多种地图服务。地图服务本身只是一个通用子域,它被支撑子域所消费。
请记住这些从最优获取上下文的角度所看到的关键点。虽然在问题空间中地图服务是库存子域的一部分,但是在解决方案空间中,地图服务并不属于库存上下文。在解决方案空间中,即便地图服务由基于组件的API提供,它依然属于另外一个限界上下文。库存管理和地图服务所使用的通用语言是相互排斥的,这意味着它们属于两个不同的限界上下文。当库存上下文需要使用外部的地图上下文(Mapping Context)时,它们之间的数据交换需要一定程度的翻译才能完成。
另一方面,从地图服务提供商的角度来看,地图子域便是他们的核心域了。他们拥有自己的领域和业务模型,同时他们需要不断改进自己的领域模型以保持竞争力。如果你是某个地图服务提供商的CEO,你需要采取不同方法留住自己的客户。然而,对于库存系统来说,地图服务始终还是个通用子域,你完全可以转向另外的地图服务提供商。
白板时间
在你自己的解决方案空间中,限界上下文是什么?此时你可以参考先前所绘的框图。随着我们对限界上下文讲解的深入,你可能感到有些惊讶了。因此,你应该为有可能的改进做好准备,毕竟,我们采用的是敏捷方法。
为了平衡各个知识点,接下来我们将讲到在解决方案空间中,限界上下文作为一种建模工具的重要性。在上下文映射图(3)中,我们将主要讲解如何通过集成限界上下文的方式来完成不同通用语言间的映射。