# 限界上下文（Bounded Context）

URL: https://caijiao.org/ddd/chapter3/context-map
Source: docs/ddd/chapter3/context-map.md
Description: 介绍限界上下文（Bounded Context）在领域驱动设计中的作用与实践，帮助开发者划分和管理复杂的领域模型。

在领域驱动设计（DDD）中，**限界上下文（Bounded Context）** 是一个核心概念，它帮助开发者明确划分系统中不同的领域模型，避免不同子系统之间的领域知识冲突。限界上下文的主要目的是为复杂的系统建立清晰的边界，以便更好地管理系统中的领域模型。

## 限界上下文的定义

限界上下文是一个明确的边界，它定义了在某个特定上下文中，某个术语的意义和规则。在这个上下文内，特定领域模型的概念、术语、语言和规则都是一致的。然而，跨越限界上下文的边界时，某些概念和规则可能发生变化。

### 重要性

1. **避免冲突**：在大型系统中，不同模块可能会使用相同的术语，但其含义却不相同。通过明确的限界上下文，可以避免这种术语冲突。
2. **增强系统可维护性**：明确的上下文划分让系统更容易理解和维护。每个上下文都有自己独立的模型和规则，修改时不容易影响到其他部分。
3. **促进团队协作**：不同的团队可以在各自的限界上下文内工作，使用统一的语言和模型，减少沟通成本。

## 限界上下文的应用

在领域驱动设计中，限界上下文通常与系统的模块化设计相对应，每个上下文代表一个具体的子系统。每个上下文内都拥有自己独立的模型、服务和存储机制，确保内部的一致性。而跨越上下文的交互则通过明确定义的接口和协议来实现。

### 例子：电商系统的限界上下文

假设我们正在设计一个电商系统，其中可能包含以下几个限界上下文：

- **订单上下文**：负责处理订单的创建、支付、发货等操作，使用 `Order`、`OrderItem` 等实体。
- **库存上下文**：负责库存管理，使用 `Product`、`Stock` 等实体。
- **支付上下文**：处理支付的相关逻辑，使用 `Payment`、`Transaction` 等实体。

在这些上下文中，`Order` 在订单上下文中有它的定义，而在库存上下文中，`Product` 实体则是与库存相关的。它们各自定义自己的模型和规则，不会互相影响。

## 限界上下文与其他设计概念的关系

1. **子域（Subdomain）**：限界上下文与子域紧密相关。一个子域可以对应一个或多个限界上下文。子域用于描述领域的业务概念，而限界上下文则描述如何在系统中实现这些概念。

   - **核心子域**：业务的核心部分，往往对应一个限界上下文。
   - **支撑子域**：支持核心业务的子域，可能涉及多个上下文。
   - **通用子域**：提供通用服务的子域，可能跨越多个限界上下文。

2. **上下文映射（Context Mapping）**：当系统中存在多个限界上下文时，如何定义这些上下文之间的关系变得尤为重要。通过上下文映射，可以清晰地表示不同上下文之间的依赖、通信方式及共享资源。

## 限界上下文的划分原则

1. **业务逻辑驱动划分**：限界上下文的划分应该基于业务逻辑，而非技术架构。通常，可以通过与领域专家的讨论来确定如何划分不同的限界上下文。
2. **团队规模与协作**：每个限界上下文通常对应一个团队。团队规模较大的系统，可能会划分多个限界上下文，每个上下文由不同的团队负责。
3. **保持上下文独立性**：每个限界上下文内的模型应当是自足的，具有独立的业务逻辑和数据存储。限界上下文之间的耦合应该保持最低。

## 限界上下文与接口设计

当不同限界上下文之间需要交互时，必须通过清晰的接口进行通信。这些接口可能是 REST API、消息队列、事件驱动等方式。不同上下文之间的交互通常通过**防腐层（Anti-Corruption Layer）**来实现，防腐层的作用是防止外部系统或上下文影响当前上下文的模型。

### 示例：电商系统中的限界上下文通信

假设订单上下文需要与支付上下文进行通信，当订单需要支付时，订单上下文通过支付上下文暴露的接口发起支付请求。支付上下文通过防腐层提供一个清晰的接口，确保支付的业务逻辑不会直接影响订单上下文的模型。

```java
public class PaymentService {

    private final PaymentGateway paymentGateway;

    public PaymentService(PaymentGateway paymentGateway) {
        this.paymentGateway = paymentGateway;
    }

    public PaymentResponse processPayment(Order order) {
        // 调用支付上下文的支付接口
        return paymentGateway.initiatePayment(order);
    }
}
```

在这个例子中，支付上下文通过 `PaymentGateway` 接口与订单上下文进行通信。两者通过接口互相独立，防止彼此直接耦合。

## 限界上下文的总结

限界上下文是领域驱动设计中的关键概念，它帮助我们划分系统的边界，确保在各个子系统中使用统一的语言和规则。通过有效地划分限界上下文，能够增强系统的可维护性，减少领域模型之间的冲突，并提高开发团队的协作效率。
