ARC 4接入真实业务工程第 15–18 章

第 15 章 —— 通过领域适配器隔离 DSM 细节

本章目标: 本章完成后,开发者能够用领域端口封装 DSM 三类 typed handles,把 locator、生命周期和失败翻译集中在适配器边界内。

学习目标

  1. 识别 DSM API 泄漏进业务层的维护代价。
  2. 设计只使用业务语言的 FulfillmentCoordination 端口。
  3. 把 Register、Lease、CRDT handle 与 locator 集中到 composition root。
  4. 分开验证领域决策和真实 Runtime 行为。

前置条件

  • 已完成第 9 章的集合选择。
  • 已理解第 14 章的失败与业务承诺边界。
  • 能运行 examples/order-fulfillment-control-plane Maven 示例。

案例进度

前三篇直接操作集合是为了学习语义。现在履约服务要进入真实工程:业务用例只说「发布路由」「领取分片」「记录请求」,不再知道 shared/gateway/route-hints 或 LeaseAcquireOptions。

业务端口拥有语言,适配器拥有技术细节

领域端口与 DSM 适配器边界

书籍示例定义的端口很小:

public interface FulfillmentCoordination {
    void publishRoute(String serviceKey, String address);
    Optional<String> routeFor(String serviceKey);
    ShardClaim claimShard(String shardId);
    long incrementRequestCount();
}

端口不返回 DsmRegister、LeaseSnapshot、PnCounterState 或 CollectionLocator。业务层因此能用 fake 直接测试;DSM 适配器负责把结果翻译成 ShardClaim(granted, uncertain, fencingToken, reason)。

Composition root 是唯一装配点

DsmFulfillmentModule 集中拥有:

  • DsmRuntime 的创建、启动和关闭;
  • clusterId 与 serviceId;
  • 三个稳定 locator 与 schema id;
  • Register、Lease、CRDT 的 entity/codec/spec;
  • 三个 typed handles 到领域端口的映射。

这不是为了隐藏所有 DSM 概念。locator 与 schema 仍是重要合同,只是由适配器拥有,而不是散落到 controller、service 和 job 中。

失败翻译不能抹掉不确定性

Lease acquire 有 granted、uncertain、snapshot 和 reason。适配器若只返回 boolean,调用方无法区分明确拒绝与结果不确定。领域结果应保留业务决策实际需要的信息,同时阻止调用方任意操作底层 handle。

同样,fencing token 需要穿过端口进入受保护的下游写入;把 token 藏掉会让第 7 章的安全边界失效。示例当前返回 token,但没有实现真实下游 guard,因此验收卡明确不声称已完成外部 fencing。

两类测试,各自只证明一层

示例有两个测试:

  1. 用 RecordingCoordination 验证 FulfillmentService 只依赖领域端口。这是 E1。
  2. 用真实 DsmRuntime 和三类集合验证适配器。这是单进程 E2。

如果只写第二类测试,业务决策和 DSM 装配会粘在一起;如果只写第一类,fake 全绿也不能证明真实 spec、codec 或 Lease 能运行。

反例与故障注入

  • 把 locator 字符串复制到 FulfillmentService,然后改变 collectionId,观察需要修改多少业务文件。
  • 把 LeaseAcquireResult 压成 boolean,尝试表达 uncertain=true。
  • 忘记 runtime.start(),检查生命周期错误落在哪一层。
  • 让业务层直接调用 requestCounter.state(),观察领域测试如何被 CRDT 类型污染。

实验

cd examples/order-fulfillment-control-plane
mvn clean test

阅读 port-contract.json,确认每个业务动作都有领域输入、领域输出、DSM handle 和未被适配器承担的外部责任。

实验验收卡

字段 内容
运行命令 cd examples/order-fulfillment-control-plane && mvn clean test
输入或故障 fake 端口;真实单节点 Runtime;三类 typed handles
可观察结果 领域服务不导入 DSM 类型;真实适配器完成路由、租约与计数操作
证据等级 E1 领域单元测试 + E2 单进程 Runtime 行为
本实验未证明 多节点传播、repair、真实网络、下游 fencing 或生产装配

回顾

  • 领域端口拥有业务语言,适配器拥有 DSM 细节。
  • locator、schema、codec 和生命周期应集中在 composition root。
  • 失败翻译要保留不确定性和 fencing token。
  • fake 与真实 Runtime 测试分别回答不同问题。

下一步

第 16 章把手工 composition root 切换为 Spring Boot 属性和条件 bean,并验证实际上下文能启动。

证据链接