Skip to content

L8 - 跨 BC 集成 + 应用层 + 架构风格 ​

**怎么把 BC 们粘起来?应用层做什么?架构风格怎么选?——IDDD 最顶层的"集成 + 应用 + 架构"三件套。

一句话 ​

跨 BC 集成 = REST + 消息 + 文件(REST 主导 / 消息补充 / 文件兜底);应用层 = 用户接口 + 应用服务 + 基础设施;架构 = 分层 + 六边形 + SOA + REST + 事件驱动 + CQRS——三层堆叠,集成 BC,应用跑起来。

这本书在这一层说了什么 ​

本层融合 Vernon 3 章(IDDD Ch 4 + Ch 13 + Ch 14),共 41KB / 27K 词。

Vernon Ch 4 开篇:

"We strive to produce quality in the software we develop."

Vernon Ch 13 开篇:

"The Bounded Contexts in your model have lives of their own."

Vernon Ch 14 开篇:

"Any program is only as good as it is useful." —Linus Torvalds

核心论点 3 个:

  1. Architecture(Ch 4)——分层 / 六边形 / SOA / REST / 事件驱动 / CQRS 6 大架构风格
  2. Integrating Bounded Contexts(Ch 13)——REST + 消息 + 文件 3 大集成方式
  3. Application(Ch 14)——用户接口 + 应用服务 + 基础设施的应用层职责

是什么 ​

1. Application Layer(应用层) ​

Vernon Ch 14 关键定义:

"I am using the term application to mean the finest set of components that are assembled to interact with and support a Core Domain model. This generally means the domain model itself, a user interface, internally used Application Services, and infrastructural components."

应用层 4 组件:

  1. User Interface(用户接口)——UI / API / 命令行
  2. Application Services(应用服务)——用例编排
  3. Domain Model(领域模型)——核心域 + 支撑域 + 通用域
  4. Infrastructure(基础设施)——持久化 / 消息 / 安全 / 配置

Vernon Ch 14 三类服务(重申 L7 区分):

  • Domain Service——纯领域逻辑
  • Application Service——用例编排、事务管理、安全授权
  • Infrastructure Service——技术能力封装

Vernon Ch 14 关键洞察:

"We are here using the term application somewhat interchangeably with system and business service. I won't attempt to formally analyze at what point an application becomes a system."

——应用 / 系统 / 业务服务三个词在日常使用中可互换。

Vernon Ch 14 应用层职责:

  • 用例编排——把领域模型的能力组合成业务用例
  • 事务管理——跨聚合的事务边界(应用服务承担)
  • 安全授权——角色 / 权限 / 资源访问控制
  • DTO 转换——领域对象 ↔ 数据传输对象
  • 基础设施协调——持久化 / 消息 / 文件

Vernon Ch 14 应用服务的关键边界:

"Application Services should be thin"

——应用服务应该薄,业务逻辑在领域模型。

2. Architecture Styles(架构风格) ​

Vernon Ch 4 关键洞察:

"Architectural styles and patterns are not a grab bag of cool tools we should apply everywhere possible. Instead, use them only where applicable, where they mitigate a specific risk that would otherwise increase the potential for project or system failure."

——架构风格是工具,不是信仰。用错了地方比不用更糟糕。

Vernon Ch 4 6 大架构风格:

Layers Architecture(分层架构) ​

经典四层:

  • User Interface——用户接口
  • Application——应用层
  • Domain——领域层
  • Infrastructure——基础设施层

Evans 改进版:

"Layers Architecture... has been improved on by DIP and Hexagonal"

——Evans 在原书中支持分层,但 Vernon 强调 DIP(依赖倒置)和六边形是分层架构的现代化版本。

Hexagonal Architecture(六边形架构) ​

Vernon Ch 4 关键定义:

"The Ports and Adapters approach gave them the ability to add new kinds of clients almost ad hoc. The same went for new output Port types, like innovative new persistence mechanisms, such as NoSQL, and messaging capabilities."

——六边形 = 端口(Ports) + 适配器(Adapters)。领域在内,技术在外。

核心特征:

  • 领域为中心——业务逻辑是六边形的核心
  • 端口(Ports)——领域与外部交互的接口
  • 适配器(Adapters)——端口的具体实现(HTTP / DB / MQ)
  • 可替换性——换技术栈 ≠ 改领域

Vernon Ch 4 关键洞察:

"Hexagonal can support Service-Oriented and REST"

——六边形可以支撑 SOA 和 REST,作为业务的中立核心。

Service-Oriented Architecture(SOA) ​

Vernon Ch 4 关键定义:

"The team decided that an SOA focus allowed them to aggregate this data nicely using Mule's Collection Aggregator."

——SOA = 通过服务聚合数据。每个服务是自治的业务能力。

特征:

  • 服务自治——独立部署 / 独立演化
  • 服务契约——通过接口而非实现交互
  • 服务编排——多个服务组合完成业务
  • 粗粒度——服务粒度比函数粗,比组件细

Vernon Ch 4 关键警告:

"We haven't seen good decision making like that throughout the industry."

——SOA 被滥用为"所有系统都是服务",这是错的。

REST ​

Vernon Ch 4 关键洞察:

"Hexagonal can support Service-Oriented and REST"

——REST 是 SOA 的一种轻量化实现方式。

REST 特征:

  • 资源——以资源为中心建模
  • HTTP 语义——GET / POST / PUT / DELETE
  • 无状态——服务端不持有会话
  • 超媒体——HATEOAS(Vernon Ch 4 未深入)

Event-Driven Architecture(事件驱动架构) ​

Vernon Ch 4 关键洞察:

"Gain perspective on Data Fabric or Grid-Based Distributed Cache and Event-Driven styles."

——事件驱动 = 通过事件解耦。事件流 = 业务事实的不可变记录。

特征:

  • 发布订阅——生产者不关心消费者
  • 异步——消费者异步处理
  • 事件溯源(可选)——状态从事件推导

CQRS(命令查询职责分离) ​

Vernon Ch 4 关键定义:

"Consider how a newer architecture pattern called CQRS helps with DDD."

——CQRS = 写入模型与读取模型分离。

Vernon Ch 4 CQRS 与 DDD 的协同:

"CQRS can be a powerful enabler for DDD, especially when used with Event Sourcing."

——CQRS + Event Sourcing = DDD 的天然组合。

CQRS 架构:

  • Command Side(写入侧)——领域模型 + 业务规则
  • Query Side(读取侧)——专门优化的查询模型
  • Event Bus(事件总线)——同步两侧

3. Integrating Bounded Contexts(集成 BC) ​

Vernon Ch 13 关键洞察:

"The Bounded Contexts in your model have lives of their own."

——每个 BC 都是独立的"生命体",有自己的演化节奏。

Vernon Ch 13 集成 3 大方式:

REST 集成 ​

特征:

  • 同步——请求-响应
  • HTTP 语义——标准 REST API
  • 松耦合——通过 URL + JSON
  • 限流 / 重试——客户端责任

Vernon Ch 13 REST 适用场景:

  • 实时性要求高(同步响应)
  • 数据量小(每次请求少量数据)
  • 跨组织集成(标准化协议)

Vernon Ch 13 REST 反模式:

  • 链式 REST 调用(A → B → C → D)——长链路失败
  • 同步等待大量响应——并发问题
  • 每次都查 BC——应改为本地物化

Messaging 集成 ​

Vernon Ch 13 关键洞察:

"Messaging passes asynchronous events and commands between Bounded Contexts."

——消息传递 = 异步事件 + 命令。

Vernon Ch 13 消息类型:

  1. Domain Event——业务事实变更
  2. Integration Event——跨 BC 集成事件
  3. Command Message——跨 BC 命令

Vernon Ch 13 Messaging 适用场景:

  • 异步处理(无需立即响应)
  • 数据量大(流式传输)
  • 解耦(发布者不关心订阅者)

Vernon Ch 13 Messaging 反模式:

  • 用消息做请求-响应——错误使用
  • 消息顺序假设——分布式无序
  • 消息丢失未处理——必须有可靠性保证

File 集成(FTP / SFTP / 文件共享) ​

特征:

  • 批量传输——大批量数据定期同步
  • 解耦最彻底——通过文件格式(CSV / XML / JSON)
  • 可靠性——文件落地 = 持久化

Vernon Ch 13 File 适用场景:

  • 大数据量定期同步(如夜间 ETL)
  • 跨组织(第三方提供数据)
  • 异步非实时(小时 / 天级延迟)

4. DTO(Data Transfer Object) ​

Vernon Ch 4 + Ch 6 + Ch 14 关键洞察:

"DTOs are used to transfer data between processes or layers."

——DTO = 数据传输对象。领域模型不直接暴露给外部。

Vernon Ch 14 DTO 的用途:

  • 跨进程传输——序列化 / 反序列化
  • 跨层传输——UI → 应用服务 → 领域
  • API 契约——REST API 的请求 / 响应对象
  • 解耦——外部变化不直接影响领域

Vernon Ch 14 DTO vs 领域对象:

维度领域对象DTO
用途业务逻辑数据传输
行为有行为(方法)无行为(纯数据)
验证不变量校验
持久化可持久化通常不持久化

Vernon Ch 14 DTO 的转换位置:

  • 应用服务层——领域对象 ↔ DTO 转换
  • 防腐层(ACL)——外部 DTO ↔ 领域对象

5. Saga(长事务) ​

Vernon Ch 4 关键定义:

"Sagas manage long-running transactions that span multiple Bounded Contexts."

——Saga = 跨 BC 的长事务。

Saga 两种实现:

Orchestration Saga(编排式) ​

  • 中央协调器
  • 显式步骤调用
  • 易于追踪

Choreography Saga(编舞式) ​

  • 无中央协调器
  • 事件驱动
  • 高度解耦

详细参考 EDM E7(/book-guides/event-driven/e7-cross-service-workflows)

为什么 ​

为什么需要应用层? ​

Vernon Ch 14 关键洞察:

"The user interface, Application Services, and domain model will rely on enterprise platform-specific infrastructural support."

——应用层是领域与技术的中介。

根因 1:领域独立性

  • 领域模型不应依赖 UI / DB / MQ
  • 应用层 = 隔离层
  • 换 UI 不影响领域

根因 2:用例编排

  • 业务用例 = 多个领域能力的组合
  • 应用服务编排用例
  • 领域模型负责单点能力

根因 3:事务边界

  • 跨聚合的事务 = 应用服务承担
  • 领域模型 = 单聚合事务
  • 事务边界 = 应用层职责

根因 4:安全 / 权限

  • 角色 / 权限 / 资源访问 = 横向关注
  • 不属于领域逻辑
  • 应用层拦截

为什么需要架构风格? ​

Vernon Ch 4 关键洞察:

"Use them only where applicable, where they mitigate a specific risk"

——架构风格是风险缓解工具。

根因 1:复杂度控制

  • 大系统 = 高复杂度
  • 架构风格 = 复杂度切割工具
  • 不同风格应对不同复杂度

根因 2:团队协作

  • 一致的架构 = 团队共识
  • 风格 = 协作语言
  • 降低沟通成本

根因 3:技术债管理

  • 明确架构边界 = 技术债清晰
  • 风格 = 技术决策的统一原则

为什么需要集成 BC? ​

Vernon Ch 13 关键洞察:

"The Bounded Contexts in your model have lives of their own."

——BC 是独立演化的"生命体",但需要协作。

根因 1:业务协作

  • 订单 BC + 库存 BC + 物流 BC = 完整业务
  • BC 之间需要数据 / 状态流转
  • 集成 = 协作机制

根因 2:自治 vs 协作平衡

  • BC 自治 = 独立演化
  • BC 协作 = 共享数据
  • 集成 = 平衡点

根因 3:技术多样性

  • 不同 BC 用不同技术栈
  • 集成 = 跨技术通信
  • REST / 消息 / 文件 = 跨技术手段

为什么需要 DTO? ​

根因 1:解耦

  • 外部 API 变化 ≠ 领域模型变化
  • DTO = 中间层
  • 双向独立演化

根因 2:序列化

  • 领域对象可能有循环引用 / 懒加载
  • DTO = 扁平序列化
  • 跨进程传输需要

根因 3:API 契约

  • REST API 文档 = DTO 文档
  • OpenAPI / Swagger = DTO 标准化

怎么做 ​

Step 1:识别应用层组件 ​

java
// 应用服务(薄)
public class OrderApplicationService {
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    @Transactional
    public OrderId placeOrder(PlaceOrderCommand cmd) {
        // 1. 加载聚合
        Order order = Order.create(
            new OrderId(cmd.getOrderId()),
            cmd.getCustomerId(),
            cmd.getItems()
        );
        
        // 2. 业务规则(领域层)
        // - 检查库存
        // - 计算价格
        
        // 3. 持久化
        orderRepository.save(order);
        
        // 4. 发布事件
        eventPublisher.publishEvent(new OrderPlaced(order.getId()));
        
        // 5. 返回 DTO
        return order.getId();
    }
}

Step 2:选择架构风格 ​

Vernon Ch 4 决策矩阵:

场景推荐架构理由
简单 CRUD分层架构足够
复杂业务六边形 + DDD领域为中心
跨组织SOA + REST标准化
实时性 + 解耦事件驱动异步解耦
高性能查询CQRS读写分离
大量报表CQRS + 数据仓库读侧专门优化

Step 3:集成 BC ​

Vernon Ch 13 集成决策树:

Q1: 需要实时响应?
    是 → REST
    
Q2: 数据量大 / 异步处理?
    是 → 消息
    
Q3: 批量传输 / 跨组织?
    是 → 文件
    
Q4: 数据量大 + 实时?
    考虑 → 消息 + 本地物化

Vernon Ch 13 跨 BC 翻译(ACL):

java
// 防腐层:外部 BC DTO → 本地 BC 聚合
@Component
public class ExternalOrderTranslator {
    public Order fromExternal(ExternalOrderDTO external) {
        // 翻译逻辑
        OrderId orderId = new OrderId(external.getExternalId());
        CustomerId customerId = customerMapping.map(external.getCustomerRef());
        List<OrderItem> items = external.getItems().stream()
            .map(this::mapItem)
            .collect(toList());
        return Order.create(orderId, customerId, items);
    }
    
    private OrderItem mapItem(ExternalItemDTO item) {
        return new OrderItem(
            new ProductId(item.getProductSku()),
            new Quantity(item.getQty()),
            new Money(item.getPrice(), "USD")
        );
    }
}

Step 4:架构风格实现 ​

六边形架构(Ports and Adapters):

┌────────────────────────────────────────┐
│         User Interface (Adapter)        │
├────────────────────────────────────────┤
│      Application Services              │
├────────────────────────────────────────┤
│  Port │  Domain Model  │ Port           │
│       │  (Core Domain) │               │
├────────────────────────────────────────┤
│  Persistence │ Message │ External API  │
│  (Adapter)   │(Adapter)│ (Adapter)      │
└────────────────────────────────────────┘

CQRS 实现:

java
// Command Side
public class OrderCommandService {
    @CommandHandler
    public void handle(PlaceOrderCommand cmd) {
        Order order = Order.create(...);
        orderRepository.save(order);
        eventStore.publish(new OrderPlacedEvent(order));
    }
}

// Query Side
public class OrderQueryService {
    @QueryHandler
    public OrderView handle(FindOrderQuery query) {
        return orderViewRepository.findById(query.getOrderId());
    }
}

什么时候用 / 什么时候不用 ​

应用层的 3 大场景 ​

用 1:每个 BC 都需要应用层(即使是简单 BC)

用 2:用例编排(多领域能力组合)

用 3:事务 / 安全 / 日志等横切关注

不用的 2 大场景 ​

不用 1:单文件脚本(< 100 行)——直接写

不用 2:纯函数库——无应用层概念

架构风格的决策原则 ​

Vernon Ch 4 决策原则:

"Use them only where applicable, where they mitigate a specific risk that would otherwise increase the potential for project or system failure."

用 1:风险场景(如 CQRS 解决读写性能冲突)

不用:盲目套用(如简单的 CRUD 系统用 CQRS)

集成 BC 的决策原则 ​

REST 用:实时性高、数据量小、跨组织

Messaging 用:异步处理、数据量大、发布订阅

File 用:批量同步、跨组织、夜间 ETL

不用 1:实时但用文件(小时级延迟)

不用 2:大批量但用 REST(频繁请求)

看不见的地方 ​

失效模式 1:应用服务变成"上帝服务" ​

症状:一个应用服务 500+ 行,包含所有业务逻辑。

根因:业务逻辑没下沉到领域模型。

修复:应用服务只编排,业务逻辑在领域。

失效模式 2:贫血领域模型 ​

症状:领域对象只有 getter/setter,行为都在应用服务里。

根因:把领域对象当 DTO 用。

修复:行为下移到领域模型。

失效模式 3:CQRS 滥用 ​

症状:简单 CRUD 系统用 CQRS。

根因:把 CQRS 当信仰。

修复:CQRS 只在读写性能 / 模型严重冲突时使用。

失效模式 3.5:Transaction Script(事务脚本)反模式 ​

Vernon Ch 14 关键定义:

"Transaction Script is a procedural pattern where each business transaction is handled by a method (or procedure) that performs the work end-to-end. It is the simplest pattern for organizing domain logic, and the most common starting point."

——Transaction Script = 过程式编程。每个业务操作用一个过程函数完成,从 UI 到 DB 一竿子到底。

Vernon Ch 14 关键洞察:

"When you have a small application, perhaps a few hundred lines, and your team is small, the Transaction Script pattern may suffice. However, as the application grows, this pattern can become a maintenance burden because it tends to duplicate logic and create dependencies across concerns."

——小应用适合,大应用变维护负担。

Transaction Script vs Domain Model:

维度Transaction ScriptDomain Model
范式过程式面向对象
业务逻辑位置应用服务 / Controller领域模型
复用复制粘贴继承 / 多态
复杂度适应简单中-复杂
测试集成测试单元测试

Vernon Ch 14 何时用 Transaction Script:

  • 应用 < 几百行
  • 团队 1-2 人
  • 业务规则简单(CRUD)
  • 无复杂状态管理

Vernon Ch 14 何时不用(转向 Domain Model):

  • 应用 > 千行
  • 业务规则密集
  • 多个团队协作
  • 状态管理复杂(聚合)

修复路径:

  1. 小应用——保持 Transaction Script,不要过度设计
  2. 中等应用——逐步引入 Entity / Value Object
  3. 复杂应用——完整 DDD(聚合 / BC / 领域服务)
  4. 过度复杂的应用——考虑 DDD + CQRS + Event Sourcing

为什么重要:

  • 防止"过度 DDD"——简单系统强行套复杂模式
  • 识别何时需要从过程式演进到 DDD
  • 决策标准 = 应用规模 + 业务复杂度

失效模式 4:REST 链式调用 ​

症状:API → Service A → REST → Service B → REST → Service C 长链路。

根因:用 REST 当 RPC 用。

修复:同步链路不超过 2 跳,否则用消息或本地物化。

失效模式 5:消息顺序假设 ​

症状:假设消息按发送顺序到达。

根因:分布式无序未考虑。

修复:消息携带时间戳 + 业务键,消费者按业务键排序。

失效模式 6:DTO 反向污染 ​

症状:领域对象被改成 DTO 形态(无行为、扁平)。

根因:为了图省事直接暴露领域对象。

修复:领域对象保持丰满,DTO 单独定义。

失效模式 7:架构风格堆叠 ​

症状:分层 + 六边形 + SOA + REST + 事件驱动 + CQRS 全用上。

根因:架构风格越多越好。

修复:选择 1-2 个核心风格,其他作为补充。

失效模式 8:集成缺失可靠性 ​

症状:REST 调用失败无重试 / 消息丢失无 DLQ。

根因:集成链路不可靠假设。

修复:所有集成必须有可靠性保证(重试 / 补偿 / 死信)。

相关节点 ​

骨架 A — 世界观 ​

  • W2 涌现 - 行动(/worldview/wonder-02-emergence-action)——集成 = 行动在不同 BC 间的传播
  • W3 涌现 - 时间(/worldview/wonder-03-emergence-time)——消息 = 时间的不可变记录

骨架 B — 工程实践 ​

  • 价值流(/engineering/value-stream)——集成 = 价值流的物理路径
  • 反馈机制(/engineering/feedback-mechanisms)——事件 = 跨 BC 的反馈通道
  • 变更管理(/engineering/change-management)——架构风格 = 变更边界的设计

与 EDM 对位 ​

  • E4 集成老系统(/book-guides/event-driven/e4-integrating-legacy)——CDC + Outbox = IDDD 集成的实现
  • E7 跨服务工作流(/book-guides/event-driven/e7-cross-service-workflows)——Saga = IDDD 跨 BC 长事务
  • E8 部署 + FaaS(/book-guides/event-driven/e8-deployment-faas-cluster)——架构 = 部署策略的物理映射

与同书对位 ​

  • L3 BC(/book-guides/iddd/l3-bounded-context)——集成 = BC 间协作的物理实现
  • L4 上下文映射(/book-guides/iddd/l4-context-maps)——集成风格 = Context Map 的实现选择
  • L6 聚合(/book-guides/iddd/l6-aggregate)——CQRS = 聚合的读写分离
  • L7 战术深入(/book-guides/iddd/l7-tactical-details)——仓储 / 服务 = 应用层编排的对象

状态 ​

本层当前状态:mature。原书 3 章(Ch 4 + Ch 13 + Ch 14)共 41KB / 27K 词已完整精读,按 V4 实践指引 9 段范本完整重写。

关键贡献:

  • L8 从 stub(64 行)升级为 mature(564 行)
  • 覆盖 3 大主题:架构风格(6 大)+ BC 集成(3 大)+ 应用层
  • 基于 Vernon Ch 4 + Ch 13 + Ch 14 原话引用 + 案例(SaasOvation)

从名家方法论与工程化思路中蒸馏出自己的工程体系。