战略领域驱动设计:优秀软件被遗忘的基石

本文深入探讨战略领域驱动设计的四大支柱:领域与子域定义、通用语言、限界上下文和上下文映射,揭示如何通过战略设计将软件与业务现实对齐,避免团队陷入纯技术实现的误区。

当团队谈论领域驱动设计(DDD)时,对话往往直接跳转到代码——实体、值对象和聚合。然而,这正是大多数项目开始偏离方向的地方。DDD的本质不在于战术实施,而在于其战略基础——即定义我们首先为何以及在何处应用模式的部分。

战略DDD经常被忽视,因为许多人没有认识到它的重要性。在应用DDD时,这是一个重大错误。战略设计为模型提供上下文,建立清晰的边界,并促进业务和技术之间的共享理解。没有这个基础,开发人员可能会专注于建模数据而非行为,创建不能准确代表领域的孤立微服务,或者在没有明确目的的情况下实施设计模式。

与软件架构一样,我们需要理解需要做什么,动机确实比如何做更为关键。战略DDD指导我们在这条道路上交付更好的软件。

尽管Eric Evans引入DDD已有二十多年,许多团队仍然犯同样的错误:他们将其视为技术配方而非思维方式。战略DDD是将DDD从一套模式转变为协作语言的关键。它将软件设计与业务愿景连接起来——没有它,即使是最优雅的代码也无法交付真正的价值。

战略DDD的四大支柱

战略领域驱动设计可以通过四个基本部分来理解:领域和子域定义通用语言限界上下文上下文映射。这些元素构成了将业务理解与软件设计对齐的基础,将复杂组织转变为可管理、有意义的模型。

1. 领域和子域定义

战略建模的第一步是定义您的领域,这指的是您的软件旨在处理的知识和活动范围。接下来,我们应用"分而治之"这一古老策略,这是罗马人使用过的原则,在现代软件开发中仍然适用。我们将更大的领域分解为更小、更专注的区域,称为子域

每个子域都有其自身的性质和战略重要性:

  • 核心子域——公司独有,定义其身份和竞争优势
  • 支撑子域——支持核心业务活动,但不直接创造差异化
  • 通用子域——跨组织通用,代表标准化或商品化流程

这些分类并非普遍适用;它们完全取决于业务背景。例如,在电子商务平台中,支付通常是支撑子域,通常通过第三方API集成。但对于像Stripe这样的支付提供商,支付代表核心子域——公司的本质。

识别哪些子域推动您组织的独特价值有助于确定在哪里投入最佳工程工作。核心子域值得关注、创新和最优秀的团队。

2. 通用语言

一旦子域清晰,下一个挑战是沟通。DDD强调共享理解——一种统一开发人员和领域专家的语言。

词语很重要,含义通常因说话者背景而异。以Ajax为例:它可以指清洁产品、足球俱乐部,或者曾经著名的网络技术。同一个词可能导致三种不同的对话。

构建通用语言意味着对齐术语,使每个概念在子域内具有一个含义——精确且一致。这种共享词汇成为清晰讨论、准确模型和有意义软件的基础。

3. 限界上下文

一旦语言对齐,下一步是定义限界上下文。这些是明确的边界,指示特定模型和语言适用的位置。每个限界上下文封装了通用语言的一个子集,并在含义和职责周围建立清晰的边界。

尽管这个术语在关于微服务的讨论中经常使用,但它实际上早于该运动。限界上下文有助于澄清代码中使用的术语含义,如"订单"、“客户"或"支付”,特别是在工程师和产品团队之间的沟通中。

4. 上下文映射

在定义每个限界上下文后,最后一步是理解它们如何交互。这就是上下文映射发挥作用的地方。它可视化上下文之间的关系——谁依赖谁、数据如何流动,以及在哪里需要模型之间的转换。

上下文映射帮助团队识别集成点、通信风格和所有权责任。这是防止团队间错位、重复和无休止协调问题的关键步骤。

战略DDD模式

该策略提供了一套七种模式来指导限界上下文之间的协作。这些模式定义了团队、系统和模型在组织边界之间如何交互。

有了这条清晰的道路,这些模式帮助您为每个上下文选择正确的关系——平衡自主性、信任和共享责任。

1. 共享内核——共同基础

有时,两个团队必须紧密合作,以至于共享其模型的一小部分。这个共享内核代表双方都依赖的领域部分,需要强大的沟通和相互信任。

示例:在金融系统中,合规交易上下文可能共享CustomerIdentity对象的定义,其中包含经过验证的用户信息。任何修改都需要这些团队之间的协调;您可以将其视为域之间共享的库。

2. 客户-供应商

在这种关系中,下游(客户)依赖于上游(供应商)。下游可以影响优先级或请求更改,但上游保留对其模型的控制权。

示例:在电子商务平台中,订单管理上下文(客户)依赖于库存上下文(供应商)来确认产品可用性。如果库存频繁变化,订单团队可以请求新的API功能——例如批量库存验证——影响供应商的路线图,同时保持独立的模型。

3. 遵奉者

遵奉者模式发生在下游不控制或影响上游模型,但经常发生的情况下。下游必须完全适应上游的设计,按原样接受其结构,有时与其他模式(如防腐层)结合使用。

示例:支付网关(如Stripe或PayPal)集成的在线市场通常充当遵奉者。电子商务平台必须符合支付提供商的API,不能在其设计或术语上发号施令。

4. 防腐层(ACL)

为避免其模型被外部概念污染,下游上下文可以使用防腐层在外部模型和自身模型之间进行转换。该层保护内部领域语言的完整性。您可以将其视为包装器或适配器层,以保护您的业务免受外部服务或方的影响。

**示例:**卡管理集成必须处理多个卡标志;不是将每个API的术语纳入系统,而是将这些转换为领域术语。

5. 发布语言

当多个团队需要集成时,他们可以约定发布语言——定义数据如何交换的正式共享合同或模式。它类似于双方都承诺遵守的API规范或消息模式。您可以将其视为规范,但在组织内部,例如,它涉及如何处理资金。

示例:在电子商务生态系统中,订单管理运输团队可能约定名为OrderDispatchedEvent的共享JSON模式。两个系统使用相同的数据结构进行集成。

6. 分离方式

对于某些领域,集成没有意义。在这种情况下,上下文可以单独发展,没有任何集成,每个都专注于自己的目标,无需直接协调。

**示例:**某些电子商务可能将核心与营销和社交媒体集成分开。

7. 开放主机服务

开放主机服务允许上游上下文暴露简单且可扩展的API或协议,许多下游系统可以在不紧密耦合的情况下使用。它是协作的明确定义的入口点。

示例:金融科技生态系统中的支付服务提供开放主机API,允许合作伙伴发起支付、检查交易状态和处理退款。每个下游系统(如发票、报告或商户仪表板)可以使用相同的API,无需一对一协调。

战略模式超越了简单的通信和集成。选择正确的模式决定了上下文如何相互依赖——无论它们是共享责任、松散协调还是独立发展。掌握这些关系是软件生态系统在增长过程中保持健康的关键。从架构角度来看,这也是非常有效的。

结论

当我们谈论领域驱动设计时,我们经常直接讨论代码,这是一个巨大的错误,因为我们忘记了关键部分:战略领域驱动设计不仅仅是架构练习——它关乎塑造协作、定义边界,并确保软件反映业务,而不是数据库。然而,它仍然是DDD中最被忽视的一面。许多团队直接跳入代码,跳过了赋予他们编写的每一行代码意义的对话、映射和模型。

当然,在像这样的文章中,不可能探索战略DDD的每一个细微差别——从上下文映射决策到通信模式在成长型组织中如何演变。这就是为什么我决定在我的新书《Domain-Driven Design with Java》中更深入地探讨这个主题。

在书中,我详细探讨了战略和战术设计如何连接,如何识别子域,定义清晰的限界上下文,以及在复杂系统中建模关系——所有这些都带有实用的Java示例。如果本文让您瞥见了为什么战略DDD很重要,那么这本书将带您完成完整的旅程。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计