Berkeley DB -- 软件设计的十点经验
设计经验一:保持清晰的模块边界
It is vital for any complex software package’s testing and maintenance that the software be designed and built as a cooperating set of modules with well-defined API boundaries.
- 复杂系统要拆成职责清晰的协作模块,并通过稳定的 API 限定耦合面。
- 模块边界可以根据业务演进逐步调整,但“边界”本身必须存在。
- 允许同一接口背后挂载多种实现(多态/插件化),即使是 C 语言项目也能获得“面向对象”的灵活性。
行动建议:设计评审时先画模块边界图,再讨论具体实现;凡是跨模块直接访问内部状态的改动都要谨慎对待。
设计经验二:设计文档是强制深度思考的工具
Skilled programmers use different techniques to this end: some write a first version and throw it away, some write extensive manual pages or design documents…
- 设计稿、架构文档、第一版原型都是迫使自己在写代码前想清楚问题的手段。
- 进入调试阶段后再改架构成本巨大,往往会牺牲前期调试成果。
- Berkeley DB 团队在写代码前就编写了完整的 Unix 风格 man page,当作“可执行规格”。
行动建议:重要模块先写“架构草图 + 关键时序 + API 约定”,并在团队内走查;编码前至少完成一次模拟演练。
设计经验三:架构会随改动逐步腐化
Software architecture does not age gracefully. Bug fixes corrode the layering and new features stress design.
- 修 BUG 会打破分层,新功能会逼迫你绕过原有约束,架构因此必然老化。
- 需要在“继续维护旧架构”与“推倒重来”之间做判断,两端都是代价:
- 不重构 → 维护成本指数级上升,最终陷入“只有全量回归测试才能保证上线”的怪圈。
- 贸然重构 → 用户对兼容性、稳定性的抱怨会很猛烈。
行动建议:建立演进指标(如模块圈复杂度、架构债务列表、故障归因),当指标超过阈值时正式立项重构。
设计经验四:风格一致比风格优雅更重要
What does matter, and matters very much, is that naming and style be consistent.
- 命名、注释、代码风格的“统一性”比“漂亮与否”更关键。
- 开发者通过约定俗成的格式快速理解意图,不一致的风格会降低信息密度,甚至被视作团队协作的失败。
行动建议:
- 采用自动化格式化工具(Go fmt、clang-format、prettier 等)做最低限度的约束。
- 在 Code Review 中将命名/风格问题视为阻断项,避免“下不为例”。
设计经验五:区分“微调”和“推倒重来”的发布策略
Software architects must choose their upgrade battles carefully…
- 只要升级的体验是“编译期报错 → 按指南修改 → 通过”,用户通常可以接受。
- 如果要进行架构级大改,请坦诚告诉用户“这是新代码基线”,并准备迁移指南,否则“伪装成小升级”会失去信任。
行动建议:
- 在版本规划中提前标注破坏性变更,提供迁移工具或兼容层。
- 对于确实无法兼容的大改,预留足够长的双版本共存期,让用户循序渐进。
以上五条建议覆盖了 Berkeley DB 团队在长期维护中踩过的坑。剩余的设计经验涵盖 API 稳定、测试策略、用户沟通等方面,也值得结合自己的项目现状逐条对照。最关键的共性是:架构演进需要持续投入,只有把“思考-表达-验证”融入日常流程,才能避免系统不可维护的结局。