codebase-design
Installation
SKILL.md
代码库设计
在动手写代码前把结构定对。讨论任何结构决策时套用下面的纪律。重构现有结构时,先写出新结构,迁移完所有调用方,再删旧路径。拿不准划分时,用 tracer bullets 先垂直打通一条调用链,验证结构再横向铺开。
模块划分
- 按变化原因聚合。 一个模块只因一种原因变:两个东西会因不同理由、在不同时间变化,就分进两个模块。哪个模块说不清“我因什么而变”,划分就没做完。
- 依赖单向。 依赖箭头全图朝一个方向,高层不直接依赖低层细节:业务策略不引用具体的存储、网络实现。低层要服务高层时,高层声明接口、低层实现(依赖倒置),让依赖从细节指向抽象。
- 循环依赖是拆分信号。 A 依赖 B、B 又依赖 A,说明两者共同依赖的第三个模块还没抽出来:先拆出共享部分消环,不要用延迟引用或运行时查找把环藏起来。
- 新增先归位。 新需求先找它属于哪个已有模块的变化原因。都套不进再新建。新建模块要有新的变化原因,不是图目录干净。
接口设计
- 最小暴露面。 只导出调用方需要的符号:每导出一个,就冻住一块内部实现。没有调用方的导出,降回私有。
- 公共类型收敛在少数入口。 调用方从一两个入口文件拿到全部公共面。类型散落在深层目录会逼调用方了解内部布局。
- 从使用者倒推形状。 先写调用方代码再定接口:写得别扭的调用现场就是接口的缺陷清单,调用方代码顺势成为接口的第一个测试。