用途:在设计与重构代码时,用一套统一术语讨论模块接口,帮助识别“加深”机会、决定 seam 放在哪里,并以可测试性为导向设计模块。适用于任何正在设计或重构代码的场景。
主要能力与原则:
- 术语表:Module(任何有接口与实现的单位,刻意不分层次,可为函数、类、包等)、Interface(调用方正确使用所需知道的一切,含类型签名、不变量、顺序约束、错误模式、所需配置、性能特征)、Implementation(模块内部代码,与 Adapter 区分)、Depth(接口处的杠杆:调用方或测试每学习一单位接口所能驱动的行为量)、Seam(可在不编辑该处的情况下改变行为的位置,即接口所在处)、Adapter(在 seam 上满足接口的具体物)、Leverage(调用方从深度获得的收益)、Locality(维护者从深度获得的收益:变更、缺陷、知识与验证集中在一处)。
- 深与浅:深模块=小接口+大量实现;浅模块=大接口+少量实现,应避免。设计接口时自问:能否减少方法数?能否简化参数?能否把更多复杂度藏进去?
- 原则:深度是接口的属性而非实现的属性,内部可由小而可 mock、可替换的部分组成;删除测试(若删掉模块复杂度消失则是直通,若复杂度在 N 个调用方处重现则值得保留);接口即测试面,调用方与测试穿过同一 seam;只有一个 adapter 意味着假想 seam,两个才是真实 seam,不要为了变化而引入 seam。
- 可测试性:接受依赖而非创建依赖,如 processOrder(order, paymentGateway);返回结果而非产生副作用;缩小表面积,方法越少测试越少,参数越少测试搭建越简单。
- 关系:一个 Module 恰好有一个 Interface;Depth 是 Module 相对 Interface 的属性;Seam 是 Interface 所在处;Adapter 位于 Seam 并满足 Interface;Depth 为调用方产生 Leverage,为维护者产生 Locality。
- 拒绝的框架:不采用 Ousterhout 以实现行数与接口行数之比定义深度;不把 Interface 窄化为 TypeScript 的 interface 关键字或类的公有方法;不用被 DDD 限界上下文占用的 boundary 一词,而说 seam 或 interface。
进阶:给定依赖加深一组聚簇见 DEEPENING.md(依赖分类、seam 纪律、替换而非分层测试);探索替代接口见 DESIGN-IT-TWICE.md(并行子代理以多种截然不同的方式设计接口,再按深度、局部性与 seam 位置比较)。
限制:资料未提供具体安装命令、代码示例或平台信息。