codebase-designlisted
Install: claude install-skill 988hj7tczd-oss/skill-tool
# Codebase Design — 深度模块设计
设计**深度模块**:大量行为放在小接口后面,放在干净的 seam 处,通过该接口可测试。在设计和重构代码时使��这套语言和原则。目标是:调用者的杠杆、维护者的局部性、每个人的可测试性。
## 词汇表
**Module** — 有接口和实现的东西。可以是函数、类、包、跨层切片。_Avoid_: unit, component, service
**Interface** — 调用者正确使用模块需要知道的一切:类型签名 + 不变量、顺序约束、错误模式、所需配置、性能特征。_Avoid_: API, signature
**Implementation** — 模块内部,它的代码主体。
**Depth** — 接口处的杠杆:调用者(或测试)每学习一个接口单元能获得的行为量。**深** = 小接口背后大量行为。**浅** = 接口和实现几乎一样复杂。
**Seam** (Michael Feathers) — 可以不编辑原处就能改变行为的位置;模块接口所在的位置。_Avoid_: boundary
**Adapter** — 在 seam 处满足接口的具体实现。描述角色(填什么槽),不是实质(里面有什么)。
**Leverage** — 调用者从深度获得的好处:更少的学习获得更多的能力。一个实现回馈 N 个调用点和 M 次测试。
**Locality** — 维护者从深度获得的好处:变更、bug、知识、验证集中在一处,不散布在调用者中。修一次,到处修。
## 深 vs 浅
**深模块** = 小接口 + 大量实现
**浅模块** = 大接口 + 少量实现(要避免)
设计接口时问:
- 能减少方法数吗?
- 能简化参数吗?
- 能把更多复杂性藏进内部吗?
## 原则
1. **深度是接口的属性,不是实现的属性**。深模块内部可以由可 mock 的可替换的小组件构成——它们只是不是接口的一部分。
2. **删除测试**。想象删除这个模块。如果复杂性消失了,它是透传。如果复杂性在 N 个调用者那里出现,它在挣饭碗。
3. **接口就是测试面**。调用者和测试跨同一个 seam。如果你想测试*绕过*接口,模块形状很可能不对。
4. **一个 adapter 意味着假设的 seam。两个 adapter 意味着真正的 seam**。不要让 seam 存在于没有实际变化的地方。
## 设计测试性
1. **接受依赖,不要创建它们**
- 好:`process_order(order, payment_gateway)`
- 差:`process_order(order)` 中 `new StripeGateway()`
2. **返回结果,不要产生副作用**
- 好:`def calculate_discount(cart) -> Discount`
- 差:`def apply_discount(cart) -> None` 改变内部状态
3. **小表面积**。更少的方法 = 更少的测试。更少的参数 = 更简单的 setup
## 深入
- **给定依赖深化模块** → 见 [deepening.md](deepening.md):依���分类、seam 纪律、替换不层叠测试
- **探索替代接口** → 见 [design-it-twice.md](design-it-twice.md):并行 sub-agent 设计多个不同接口,对比深度