重读《Unix编程艺术》笔记 作者: nbboy 时间: 2021-10-01 分类: 软件架构,软件工程,设计模式,C,Golang 1 条评论 第一次记不清什么时候读的了,大概是在刚毕业那会,也没读懂多少,但是印象中只记得一句话:**一种是设计的极为简洁,以至于无法看到明显的缺陷;另外一种是设计的极为复杂,以至于有缺陷也看不出来。**作者引用这句的意思是尽量把软件设计得简洁,这样才能尽量减少BUG。 作者水平非常牛,可以看下参考资料里的链接,作者写过大量的开源软件,所以他说的有一定的参考意义。对书中我比较感兴趣的是设计原则部分和软件复杂度部分,就针对这两块记录下我的总结和理解。 ### Unix软件设计原则 1. 简洁原则:其实就是我们常说的KISS原则(Keep It Simple, Stupid) 2. 模块原则,组合原则:作者提倡用清晰的接口+简单的模块组合成复杂的软件 3. 清晰原则:有时候,尽量写一些很轻松就可以阅读的代码,而不是过度优化的代码,即使性能比前者好 4. 分离原则:容易变的和不容易变的需要分离 5. 透明原则:给模块或者程序预留测试,统计,监控接口,一切都在掌控之中。 6. 表示原则:尽量用数据结构去驱动,而不是逻辑 7. 通俗原则,默认原则:现在流行的说法就是约定优于配置,Java的SpringBoot就是把这种思想推到了极致,让新手入门比较简单 8. 补救原则:常说的Fail-Fast思想,作者还说了我们应该遵循宽容地收,谨慎地发的思想,这个想法不单单用在网络程序上,我们平时写方法也可以把它作为准则之一。 9. 经济原则:类似清晰原则,不要去写晦涩的优化代码,除非在性能严格场景,或者可以封装复杂度 10. 生成原则:尽量利用自动代码生成来代替手工代码 11. 优化原则:先设计一个简单的可以实现的原型,然后再去优化代码性能 12. 多样原则:更加包容的心态去接受新事物 13. 扩展原则:为将来可能的扩展预留接口 ### 好的程序特征 - **首先应该为程序选择恰当的数据结构,其次是算法,因为数据结构比算法更有表现力。** - 不需要过早的优化。 - 数据结构和算法应该尽量简单,拿不准就用枚举法。 - 紧凑性:减少冗余设计,可靠精简的核心算法,可以避免出现一些边界情况。 - 正交性:只做一件事情,减少副作用。 - SPOT原则:更具体了紧凑原则,对于数据模型尽量要简化,抽象/模型尽量和现实/需求一一对应。 - 分层原则:好的软件是分层设计的,编程习惯上一般可以分为自顶向下和自底向上方式。 - **衡量是否一个好程序,不在无可增加,而在无可删减** - 一个模块不应该暴露过多的API/全局变量,也需要控制函数的体积 - 透明原则:添加过度的抽象层/过度保护底层细节会让实现变得不透明,保持简单是实行透明性的一个方法 ### 复杂度来源 全书说得最多的是简洁性,那对于软件复杂性的来源可以归结为3类: - 接口(可以理解为用户界面)的复杂性 - 实现(代码的实现细节)的复杂性 - 代码行数带来的复杂性 ### 复杂度种类 作者主要认为复杂度主要分为3种,即**偶然复杂度,选择复杂度,本质复杂度**:  偶然复杂度也是最好控制的,属于代码层面的复杂度,利用重构能一定程度减轻偶然复杂度。选择性复杂度主要产生于需要做的功能,比如对于财务报表功能和对于飞机自动化控制程序的功能显然是完全不是一个等级的。本质性复杂度主要根据开发工具,选取的核心数据结构,和真正的功能本身逻辑复杂度都可能影响到。 那这些复杂度怎么破?作者也只是给出了一些指导性建议: - 对于偶然性复杂度,通过设计更加简单的程序(其实之前讲的一些原则都是可以用来消除本类复杂度的)能够带来一些帮助。 - 对于选择性复杂度,通过选择要做哪些功能来权衡功能和复杂度之间的利弊。 - 对于本质性复杂度,只有对要解决的程序问题进行深入思考,设计合适的数据结构才能降低此类复杂度。 ### 总结 编程属于实践性活动,作者的大量经验教训也是在爬了很多坑才总结出来的,即使到现在也在提交代码。所以以上的编程原则,以及对复杂度的讨论,都需要笔者和读者去实践中应用和领悟才行。 ### 参考 [作者简介](https://zh.wikipedia.org/wiki/%E5%9F%83%E9%87%8C%E5%85%8B%C2%B7%E9%9B%B7%E8%92%99 "作者简介") [知乎上的评价](https://zhuanlan.zhihu.com/p/25040637 "知乎上的评价") [作者维护的软件](http://www.catb.org/~esr/software.html "作者维护的软件")