DDD战略设计
DDD战略设计
上下文映射模式
上下文映射描述了限界上下文之间的关系和集成方式。
常见的上下文映射关系:
1. 共享内核(Shared Kernel)
┌─────────┐ ┌─────────┐
│ 上下文A │◄───►│ 上下文B │
└─────────┘ └─────────┘
│ │
└───────┬───────┘
▼
共享的领域模型
2. 客户-供应商(Customer-Supplier)
┌─────────┐ ┌─────────┐
│ 供应商 │────►│ 客户 │
└─────────┘ └─────────┘
3. 防腐层(Anti-Corruption Layer)
┌─────────┐ ┌─────────┐
│ 上下文A │────►│ ACL │───►│ 上下文B │
└─────────┘ └─────────┘
4. 开放主机服务(Open Host Service)
┌─────────┐
│ 上下文A │
└────┬────┘
│
▼
┌─────────────┐
│ 公开API │
└────┬────┬───┘
│ │
▼ ▼
┌────┴┐ ┌┴────┐
│客户1 │ │客户2 │
└─────┘ └─────┘
防腐层实现
防腐层(ACL)用于隔离外部模型,保护领域模型的纯洁性。
// 防腐层:将外部用户模型转换为内部领域模型
@Component
public class UserAntiCorruptionLayer {
private final ExternalUserService externalUserService;
public Customer toCustomer(ExternalUserId externalId) {
// 调用外部服务
ExternalUser externalUser = externalUserService.getUser(externalId.getValue());
// 转换为内部领域模型
return Customer.builder()
.id(new CustomerId(externalUser.getId()))
.name(new UserName(externalUser.getFirstName(), externalUser.getLastName()))
.email(new Email(externalUser.getEmailAddress()))
.phone(new Phone(externalUser.getMobileNumber()))
.build();
}
public ExternalUserId toExternalId(CustomerId customerId) {
return new ExternalUserId(customerId.getValue());
}
}
// 使用防腐层
@Service
public class OrderService {
private final UserAntiCorruptionLayer userACL;
private final OrderRepository orderRepository;
public Order createOrder(CustomerId customerId, List<OrderItemRequest> items) {
// 通过 ACL 获取客户信息,不直接依赖外部模型
Customer customer = userACL.toCustomer(customerId);
Order order = OrderFactory.create(customer.getId(), items);
orderRepository.save(order);
return order;
}
}
上下文映射实现
// 共享内核:多个上下文共享的部分领域模型
@SharedKernel
public class ProductId {
private final String value;
}
// 客户-供应商关系实现
// 供应商(订单上下文)提供接口
@RestController
@RequestMapping("/api/orders")
public class OrderSupplierController {
@GetMapping("/{orderId}/summary")
public OrderSummary getOrderSummary(@PathVariable String orderId) {
Order order = orderService.findById(new OrderId(orderId));
return new OrderSummary(
order.getId().getValue(),
order.getStatus().name(),
order.calculateTotal()
);
}
}
// 客户(支付上下文)使用防腐层调用
@Component
public class OrderAntiCorruptionLayer {
private final RestTemplate restTemplate;
public OrderInfo getOrderInfo(String orderId) {
OrderSummary summary = restTemplate.getForObject(
"http://order-service/api/orders/" + orderId + "/summary",
OrderSummary.class
);
// 转换为支付上下文的模型
return new OrderInfo(
new OrderId(summary.getOrderId()),
Money.of(summary.getTotal()),
OrderStatus.valueOf(summary.getStatus())
);
}
}
上下文关系决策
选择上下文映射模式需要考虑:
- 耦合程度:共享内核耦合最高,ACL 耦合最低
- 团队结构:同一团队可用共享内核,不同团队推荐 ACL
- 变更频率:外部依赖变化频繁时使用 ACL
- 性能要求:性能敏感场景可考虑直接集成
战略设计的目标是管理限界上下文之间的复杂性,保持每个上下文的内聚性。