图 04 · 深度模块

设计师如何把行为转化成可维护的模块?

深度模块的反馈循环:以行为描述为起点,通过测试缝建立快速反馈,再围绕最小接口收敛实现。{code-review} 在循环中作为看门人,防止接口扩张。

深度模块反馈循环图 ── 实际调用者(Real Callers)── 模块边界(Module Boundary) 公共接口(Public Interface) activate(entity) · deactivate(entity) · onMount(cb) · onUnmount(cb) // 目标:接口小,实现深 隐藏实现(Hidden Implementation) EventEmitter registry 生命周期状态机 钩子执行顺序控制 // 调用者无需知道这些细节 测试缝(Test Seam) 注入 mock registry,不需要改接口 行为描述 「onMount 在 entity.activate() 之后同步执行」 来自:spec(/to-spec 产物) [Agent / 工程] {tdd} 红 → 绿 → 重构 先写测试,驱动接口 [Agent / 工程] {code-review} 接口是否仍然最小? 规范与 spec 的双轴检查 若接口扩张 → 退回重新设计 若发现接口扩张 → 退回 {tdd} 重新收敛 已审查 diff 深度实现 + 最小接口 可维护的模块

什么是「深度模块」?

深度模块 = 小接口 + 深实现。调用者只需要知道 4 个方法,但模块内部处理了事件系统、状态机和并发逻辑。接口扩张(「浅模块」)是可维护性问题的早期信号。

{code-review} 的防护作用

code-review 在这里不仅检查是否符合 spec,还检查接口是否发生了扩张。每多一个公共方法都是需要意识到的成本。如果接口扩张了,循环退回到 {tdd} 阶段重新收敛。

设计目标

接口:entity.onMount(cb) — 一个方法。实现:内部维护 WeakMap 存储回调,在 activate() 中顺序调用,支持异步取消注册。调用者不知道这些细节。

测试缝的作用

测试注入一个 mock 时钟,可以在不调用真实 DOM 的情况下验证 onMount 的调用时序。测试缝让这个隐藏实现在 CI 中可快速验证。

线性阅读顺序:从 spec 中的行为描述出发 → {tdd} 写失败的测试,驱动接口形状 → 实现深埋在模块边界内(隐藏细节)→ 测试缝允许快速注入 mock → {code-review} 检查接口是否仍最小、是否符合 spec → 若接口扩张则退回 {tdd} 收敛 → 产出深度模块:小接口 + 深实现。