最近这段时间比较忙,利用业余时间看完了这本书。虽然书中讲到的很多例子都是上古文物,我没有用过,不过原理都是相通的,对我的启发很大。比如无所不在的KISS原则,实践中慢慢体会到的SPOT原则,无不产生共鸣。下面是这些原则的一些笔记和个人理解。
1. 模块原则
为什么要模块化?计算机编程的本质就是控制复杂度。而模块化可以降低整体复杂度,即使出现问题也只是局限于局部,方便维护。
紧凑性和正交性是模块化的两个重要特性。对于现代项目来说,跨度一般都很大,完全达到紧凑性是非常困难的,只能尽量采用。
正交性是指程序中每个动作有且只有一个方法,正交性的程序不但会减少程序中的副作用,而且从另一个方面达到紧凑性。SPOT(single point of truth)是指任何知识点在系统内应当只有一个唯一明确权威的表述。不要重复自身。重复会导致前后矛盾。重构的原则性目标就是提高正交性。
2. 清晰原则
所谓大巧不工,重剑无锋。程序的清晰性比奇技淫巧更重要。选择算法和实现时应考虑可扩展性和可维护性,复杂的bug容易产生bug,难以阅读维护。同时在项目中养成注释代码的良好习惯。
3. 分离原则:
策略同机制分离,接口同引擎分离。策略是易变的,灵活的;机制是稳定的。策略与机制混在一起会有两个负面作用:1.使策略死板,难以适应用户需求变化。2.任何策略的改变都极有可能动摇机制。而分离开来可以在探索新策略时不去改变已有机制。
实现策略与机制分离的常用方法就是用脚本语言驱动的c语言实现机制,打包成库。整个应用程序的控制流程则有脚本语言来控制,这就是策略。比如我们公司的产品就是策略机制分离的典型应用。底层引擎由c和c++实现,lua做接口,上层流程用lua脚本实现,用户可以在一定范围内自己设计流程。
不过上层策略和下层机制分离并没有那么容易,不管是从上到下还是从下到上的设计方向都有弊端。当上层的策略与下层的机制产生冲突时就可能需要中间胶合层来匹配。胶合层应该尽可能薄,薄胶合层是分离原则的升华。C语言是薄胶合层的典型范例,而面向对象语言则属于厚胶合层,特别是继承层数太多时,会严重增加复杂度。
4. 简洁原则
出现越复杂,产生bug的概率就越高,排错也越困难。以简洁为美,拒绝花哨臃肿的程序。Keep it simple, stupid!
5. 透明性原则
透明性是针对程序的行为而言的,如果程序行为在一定程度上可以预测,那么程序就是透明的。可显性指的是程序的功能很清楚,容易明白做了什么,怎么做的。比如Linux内核具有透明性,我们知道具有什么行为,但是不具有可显性,因为源码太复杂难懂了。
6. 健壮原则
健壮性指程序不仅在正常情况下运行良好,而且在超出设计者设想的意外条件下也能运行良好。尽量让程序的内部逻辑更易于理解,使其透明化和简洁化,最好避免程序出现过多特例和边界条件。
7. 表示原则
数据比代码逻辑更清楚明了,设计时主动将代码的复杂度转移到数据中去,选择偏于维护和操作的数据。数据驱动编程是unix编程的重要组成部分。
8. 通俗原则
接口设计避免标新立异。最易用的程序就是用户需要学习东西最少的程序,一定避免表面相似但内部却不同的情况,比如重载函数内部行为变化太大。
9. 缄默原则
设计良好的程序将用户的注意力视为有限的宝贵资源。信息内容应该符合最大惊奇原则,只对确实是异常的情况加以说明。如果调试需要,可以添加多级开关,发布时启用最高级别开关。
10. 补救原则
出现异常时,马上退出并给出足量错误信息。软件在发生错误时如果没有及时发现,将会埋下严重的隐患。软件应该能够从容应付各种错误,如果做不到,就应该明确终止。有些时候程序不应该去容错,比如输入为空时最好直接退出并保留恢复机制和错误信息,处理输入后再重启,而不是检查输入是否为空,当数据出现问题却恰好不为空时将会产生非常隐晦的错误。
11. 优化原则
过早优化是万恶之源。先制作原型,再精雕细琢,优化之前先确保能用,不要为蝇头小利投入过量时间。