领域驱动设计DDD入门3:子域
这一节继续讲下一个战略工具:子领域,也就是小领域,简称子域。子域能用于解决和遗留系统(就是老系统,会产生大泥球的系统)集成带来的复杂性问题。本节分三段:先介绍子域概念,然后是DDD项目中的子域类型,最后是使用子域解决大泥球系统。
前面说过,在DDD中一个项目中会有多个有界上下文:一个核心领域和其他支撑领域。下图中在中心是敏捷项目管理核心域的边界上下文,边上还有其他上下文,例如论坛、讨论和帖子、日历和日历条目。在身份和访问上下文中有“租户-用户”和“用户角色”,在另一个有界上下文中有“付款”。也许在产品支持有界上下文中,我们有支持计划和突发事件等等。总之我们在一个核心领域项目中总是有多个边界上下文。最佳的建模组合是每个子域只有一个边界上下文。子域是一个新概念,子域是业务域的子部分。因此,每个有界上下文也是一个子域,并且与它们所属的子域以一对一关系进行显式建模。

整个业务域太复杂而无法考虑,因此要将整个业务域划分为逻辑子域。那么从逻辑上讲,业务的最佳领域是什么,如何根据通用语言分隔边界上下文?现在,当我们谈论遗留系统时,经常会遇到很多与遗留系统相关联的泥潭,因此实际上不可能仅谈论那些遗留系统中的明显领域模型。单个遗留系统可能具有多个,甚至很多逻辑模型。这些逻辑模型中的每一个都可以称为子域,就好像它们是使用DDD开发的一样,但它们不是。因此,我们仅将它们称为子域。 当我们在特定的核心域上工作时,我们将仅考虑在特定问题空间中用到的子域。因此有一个团队来执行某些核心域的设计,并且在这样做时,该核心域将需要与其他边界上下文进行接口和集成。我们要做的是将我们的知识、理解和对软件开发的提交限于解决我们正在研究的特定核心域所必需的那些子域。这样,我们基本上可以将整个业务领域及其所有复杂性抛在一边,因为在此特定项目中并不需要。 将子域也视为专业概念,就像我们谈论有界上下文和通用语言一样。如果我们甚至将大泥球系统或应用程序都视为多个模型,那么这些多个逻辑模型中的每个逻辑模型本身就是专门知识领域。我们需要围绕核心模型的解决方案。团队中至少要有一位领域专家可以帮助我们理解组织的愿景以及我们正在开发的领域模型的目标。此人具有丰富的业务经验,足以提炼愿景并与整个开发团队互动和合作。 DDD设置中的子域总是有一个域专家参与。有一个干净的有界上下文将用作核心域,还有其他至少一个用于支持核心域的有界上下文。
那么DDD工具集中有哪些子域类型呢?以我们的敏捷项目管理工具为例,这个应用有待办、发布、冲刺、任务、志愿者、估时、负责人、团队人数等关键概念。核心域是你组织作出战略投资的地方,一般是有极高优先级的。这表明了你的公司在乎什么,也就是软件的目标。你的公司不会在每个方面都超前,所以选择性超前的地方就是核心方向。你不太可能同时开发出最好的敏捷项目管理软件和最好的用户访问控制软件。可能你想在协作工具上做到业界突出,那协作内容就是核心领域。但是对于敏捷项目,协作并不是核心领域,它只能是支持域。 这就是你的组织将通过此类子域将自己与所有其他组织区分开的方式。在我们的示例中,它是敏捷项目管理工具。协作环境也可能是一个核心领域,但是在项目上下文中,正在开发敏捷项目管理上下文的情况下,协作上下文不是核心领域。因此,必须有一个支持子域来支持核心域。对于我们的敏捷项目管理软件,绝对有必要提供支持的子域,否则我们将不支持比如线程讨论和日历条目的功能。它需要自定义开发,因为不存在现成的产品。但是,支持子域的开发可能不用获得核心领域获得的那种投资。 如果具有战略意义,例如与协作环境有关,那么你将在其中进行重大开发。如果支持子域对特定核心域没有战略意义,那么您可能要考虑将其开发外包,或者确保您不像核心域那样对它进行大量投资。通用子域呢?比如身份和访问子域。也不用像核心域那样将相同的投资投入通用子域。尽管没有身份和访问上下文,就无法拥有敏捷项目管理软件。但是,它仍然是通用域不是核心域。你不想在通用子域上投入大量资金。实际上,甚至可以直接购买这种特定类型的软件,也可以将其外包。如果决定不应该将其外包,或者如果找不到或买不起现成的解决方案,则应将通用子域分配给没有精英的开发人员团队。
在使用DDD时有时不可避免地会遇到大泥球。可能在开发核心域时使用了明确的有界上下文和通用语言来开发此核心域,但某个时候可能仍将不得不与大泥球系统集成。 如何处理与大泥球整合的复杂性?大泥球内部有可能有多个逻辑模型。如果使用DDD来开发遗留系统,可能会有多个有界上下文。我们必须找到一种方法来应对大泥球的复杂性。当我们在问题空间中工作时,为了理解大泥球,我们可以将大泥球中的每个逻辑模型当作它们自己的有界上下文来对待。例如,我们有一个订单子域、一个履约子域、一个帐户子域、一个目录子域和一个配送子域。当在问题空间中尝试通过命名每个子域来理解这个大难题时,我们希望的是单独的显式有界上下文。即使没有它们,我们仍然可以通过了解其中的子域来解决使用这个大泥潭的复杂性。 因此,当进行分析和高级战略设计时,请根据其中存在的逻辑模型来标记大泥球系统,这对处理复杂性大有帮助。 现在回到我们的核心领域:敏捷项目管理环境。这是它自己的子域,是敏捷项目管理子域。我们在子域和有界上下文之间存在一对一的关系。我们也有一个支持域和一个通用子域。支持子域是协作上下文,它是支持域是因为我们不能购买它来支持我们敏捷项目管理上下文的功能。因此,我们将内部开发协作上下文。这种协作环境可能值得和核心领域一样投入,但是它依然是一个支持子域。 另外我们有一个通用子域:身份和访问控制上下文。就像其他两个子域及其有界上下文一样,这个子域及其有界上下文也是一对一的。因此,它是DDD的理想建模组合。但是,再次请注意,这是一个通用子域,因此它的有界上下文不值得像核心域那样的战略投资。我们不想将这种投资投入其中。
