设计一个接口
本技能源自《A Philosophy of Software Design》中的“Design It Twice”:你的第一个想法很可能不是最好的。先生成多个截然不同的设计,再进行比较。
工作流
- 收集需求
设计之前需要理解:
这个模块解决什么问题?
谁调用它?(其他模块、外部用户、测试)
关键操作有哪些?
有哪些约束?(性能、兼容性、既有模式)
哪些应该隐藏在内、哪些应该对外暴露?
可以询问:“这个模块需要做什么?谁会使用它?”
- 生成设计(并行子代理)
使用 Task 工具同时启动 3 个以上子代理。每个子代理都必须产出截然不同的方案。
每个子代理的提示模板:
Design an interface for: [module description]
Requirements: [gathered requirements]
Constraints for this design: [assign a different constraint to each agent]
- Agent 1: "Minimize method count - aim for 1-3 methods max"
- Agent 2: "Maximize flexibility - support many use cases"
- Agent 3: "Optimize for the most common case"
- Agent 4: "Take inspiration from [specific paradigm/library]"
Output format:
-
Interface signature (types/methods)
-
Usage example (how caller uses it)
-
What this design hides internally
-
Trade-offs of this approach
-
展示设计
展示每个设计,包括:
接口签名——类型、方法、参数
使用示例——调用方实际如何用它
内部隐藏了什么——保持在内不暴露的复杂度
依次呈现各个设计,让用户能在比较之前先吸收每种方案。
- 比较设计
展示完所有设计之后,从以下方面进行比较:
接口简洁性:更少的方法、更简单的参数
通用还是专用:灵活性还是聚焦
实现效率:接口形态是否允许高效的内部实现?
深度:小接口隐藏大量复杂度(好)对比大接口搭配薄实现(差)
正确使用的容易程度对比误用的容易程度
用散文而非表格讨论权衡,突出设计之间分歧最大的地方。
- 综合
最好的设计往往综合了多个方案的洞见。可以询问:
“哪个设计最契合你的主要用例?”
“有没有其他设计中的要素值得吸收?”
评价标准
来自《A Philosophy of Software Design》:
接口简洁性:更少的方法、更简单的参数 = 更容易学习和正确使用。
通用性:能否在不修改的情况下处理未来的用例。但要警惕过度通用化。
实现效率:接口形态是否允许高效实现?还是会迫使内部实现变得别扭?
深度:小接口隐藏大量复杂度 = 深模块(好)。大接口搭配薄实现 = 浅模块(避免)。
反模式
不要让子代理产出相似的设计——必须强制拉开差异
不要跳过比较——价值就在于对比
不要实现——这里纯粹只关乎接口形态
不要基于实现工作量来评估