berkly DB
建筑架构与软件架构之间有许多相通的地方, 但仍有一点关键区别。建筑师在其职业生涯要
研习成千上万的建筑, 而大多数软件开发者仅了解只手可数的几个大型程序, 多半还是他们
自己写的。他们从不看历史上伟大的程序,也不阅读有老手程序员写的程序设计评论。结果,
他们重复着别人的错误,而非站在别人的肩膀上
设计教训
- 极少存在“不重要的Bug”这样的事情。确实,不时会有一些笔误,但通常一个Bug意味着
有人没有完全理解他们在做的事情并实现错了。当你修复Bug时,不要仅看现象,要看底
层的原因。 如果你愿意的话, 还应该看看产生误解的原因, 因为这样可以更好的理解程序的
体系结构并发现设计本身更本质的缺陷。 - 威法则( Conway’s law):说明了设计反映了产生它的组织的结构。
- 对任何复杂的软件包的测试和维护来说,将其设计和构建成带有良好定义的 API边界的、
一组互相协作的模块至关重要。在有需求时,这些边界能够(而且必须!)移动,但是边界
总得存在。这些边界的存在可以防止软件变成一堆不可维护的意大利面条。
软件设计绝对是迫使你自己在试图解决问题前通盘考虑整个问题的几种方法之一。有经验的
程序员采用不同的技术来达到这个目的: 有些先写第一版然后扔掉, 有些写出大量的手册或
设计文档,其他的则设计出代码模板并识别出每个需求,分派到一个具体的函数或一段注释。
例如,在BerkeleyDB中,我们在写代码之前为存取方法和底层模块创建了一份完整的Unix
风格的手册。不管采用的具体技术如何,在代码调试开始后都很难想清楚程序的体系结构,
更不要说大的体系结构变化通常会浪费前期的调试努力。软件体系结构设计需要一种与代码
调试不同的思维方式,当你开始调试时的软件体系结构通常就是你在该版本中将会交付的结
构。
- 在函数库的设计中, 重视名字空间是至关重要的。用你的函数库的程序员应该不需要去记住
几十个函数、常量、结构、全局变量的保留名字以避免应用和函数库的命名冲突。
最 - 一, 如果一个功能出现了
多次, 那就写出共享的函数并使用它们, 因为对于任何特定功能而言, 两份拷贝的存在一定
说明其中一份实现得不正确。 其次, 当你开发一系列通用的例程时, 给这些例程写一个测试
集,这样你就可以分开调试它们。第三,代码越难以书写,单独书写并维护它就越重要。因
为基本上不可能防止外围代码感染和侵蚀一份代码 - 写日志是另一个提供封装和分层的例子, 即使是这个特性不会对其他的软件有用: 毕竟有
多少程序会关心缓存中的LSN?不管怎样,这个原则是有用的,而且使得软件容易维护、
测试、调试和扩展 - 你发现一个体系结构上的问题而又不想立即修复时, 你其实倾向于放过它。请记住被蚕食
而死和被大象踩住都一定会要你的命。别太犹豫而不去修改整个框架来改进软件结构, 而且
当你做出修改时,不要以为你以后会清理它而做出不完全的修改——一次做完并继续向前
进。 就像经常说的, “如果你现在没有时间去做, 以后也不会有时间去做”。 此外, 在你修改
框架时,同时也要写测试结构