本文作者 VaughnVernon
一位经验丰富的软件工匠,也是追求简化软件设计和实现的思想领袖。他是畅销书《实现领域驱动设计》和《响应式架构:消息模式Actor实现与Scala,Akka应用集成》的作者。他在全球面向数百位开发者教授过IDDD课程,并经常在行业会议上发表演讲。他对分布式计算、消息机制、特别是Actor模型非常有兴趣。Vaughn擅长领域驱动设计和使用Scala、Akka实现DDD方面的咨询。

敏捷项目管理核心域
DDD项目中总会碰到很多限界上下文(Bounded Contexts)。这些上下文中一定有一个即将成为核心域(CoreDomain),而其他的限界上下文之中也会存在着许多不同的子域(Sub Domain)。图1中有六个限界上下文与六个子域。正是因为采用了DDD的战略设计,团队方能实现最佳的建模成果:限界上下文与子域之间一一对应。换句话说,敏捷项目管理核心即是一个清晰的限界上下文,也是一个清晰的子域。在某些情况下,一个限界上下文中有可能存在多个子域,但这并非是最理想的建模结果。
简单地说,子域是整个业务领域的一部分。你可以认为子域代表的是一个单一的、有逻辑的领域模型。通常,大多数的业务领域都过于庞大和复杂,难以作为整体来分析,因此我们一般只关心那些必须在单个项目中涉及的子域。子域可以用来逻辑地拆分整个业务领域,这样你才能理解存在于大型复杂项目中的问题空间。
你也可以认为子域是一个明确的专业领域,假设它负责为核心业务提供解决方案。这意味着特定的子域将会有一位或多位领域专家领衔,他们非常了解由这些特定子域促成的业务的方方面面。对你的业务而言,子域也有或多或少的战略意义。
如果通过DDD来创建子域,它将会被实现成一个清晰的限界上下文。特定业务的领域专家将会成为共建限界上下文的团队中的一员。虽然使用DDD来建立一个清晰的限界上下文是最佳选择,但有时这只是我们一厢情愿的想法。
项目中有三种主要的子域类型:
业务领域中的某些系统边界将非常可能是遗留系统,它们也许是由你的组织构建的,也许是通过购买软件许可的方式获得的。此时,你可能无法对这些遗留系统进行任何改造,但当它们对核心域产生影响时,仍旧需要我们认真对待。为此,子域可以作为讨论问题空间的工具。
不幸的是,事与愿违,有些遗留系统与强调限界上下文的DDD设计方式大相径庭,甚至可以称之为无边界遗留系统。这样的遗留系统就像是一个“大泥球”。事实上,“大泥球”内充满了多个错综复杂的模型,这些模型本应该被分别设计并实现,但当它们纠缠在一起时,整个系统会乱成一团。

换言之,当我们在讨论某个遗留系统时,其中可能会包含一些,甚至许多逻辑领域模型,我们要将每个逻辑域模型当作一个子域对待。图2中,无边界遗留单体大泥球中,每个逻辑子域都已经被虚线框标识出来。共有五个逻辑模型或子域。这样处理逻辑子域的方式有助于我们应对大型系统的复杂性。这很有意义,因为我们可以像使用DDD和多个限界上下文应对问题空间一样,为其提供解决方案。
如果使用独立的通用语言思考,可能遗留系统就不会成为单体大泥球,这至少也可以帮助我们理解如何与它进行集成。使用子域来思考和讨论此类遗留系统有助于我们应对大型错综复杂模型的残酷现实。当使用这类工具时,我们可以明确那些对业务更有价值、对项目更重要的子域,而其他子域可以降低到次要位置。
考虑到这一点,你甚至可以通过同样的简单图表展示团队正在或正准备构建的核心域。这将帮助你了解子域间的关联与依赖。

当使用DDD时,限界上下文应该与子域一一对应(1:1)。也就是说,如果存在一个限界上下文,那么它的目标就应该是对应且只对应一个子域模型。想要始终做到这一点很难,但在可能的前提下,尽量以这种方式去建模很重要。这样可以使限界上下文清晰并且始终专注于核心战略举措。
如果必须在同一个限界上下文(你的核心域之中)中创建第二个模型,应该使用一个完全独立的模块将该模型从核心域中分离出来。(DDD的模块基本上等同于Scala和Java中的包,或者是F#和C#的命名空间)。DDD通过清晰的语言声明了一个模型是核心,而另一个只是它的支撑。你可以在解决方案空间中使用分离子域这种特殊方法。
————
本文节选自《领域驱动精粹》(Domain-Driven DesignDistilled)一书,本书预计将于年中面世。本书适用于对快速学习 DDD 核心概念和主要工具感兴趣的人。最主要的读者是软件架构师和开发者,他们将在项目中实践 DDD。通常,软件开发者会很快发现 DDD 的美妙之处,并被其强大的工具深深地吸引。尽管如此,本书也可以帮助高管、领域专家、经理人、业务分析师、信息架构师和测试人员理解这一主题。阅读原文将带你领略DDD大师Vernon的成名作,它是国内众多DDD实践者的启蒙读物。