Unix编程艺术读书笔记
linux
读书
Unix哲学,对软件设计和开发有着深远的影响,需要好好研读和体会。
- Unix哲学注重时效,立足于丰富的经验。
- 每个程序就做好一件事
- 尽早的设计和实现代码,并在重构中丢弃烂代码
- 优先使用工具
- 一个程序只做一件事,并做好。
- 程序要能协作,程序要能处理文本流,因为这是最通用的接口。
RobPick 的Unix哲学
- 你无法判定程序会在什么地方耗费运行时间。瓶颈往往出现在意想不到的地方,所以别急于胡乱找个地方改代码,除非你已经证明那是瓶颈所在。
- 估量。在你没有对代码进行估量之前,特别是没有找到最耗时的部分之前,别去优化速度。
- 花哨的算法在n很小的时候通常很慢,而n通常很小。花哨算法的常数复杂度很大。 除非你确定n总是很大,否则不要用花哨算法。
- 花哨的算法比简单的算法更容易出现bug,更难实现。尽量使用简单的算法配合简单的数据结构。
- 数据压倒一切,如果选择正确的数据结构并把一切组织的井井有条,正确的算法也就不言自明。编程的核心是数据结构,而不是算法。
原则
- 模块原则: 使用简单的接口拼合简单的部件
- 清晰原则: 清晰胜于机巧
- 组合原则:设计时候考虑拼接组合
- 分离原则: 策略同机制分离,接口同引擎分离
- 简洁原则:设计要简洁,复杂度能低就低
- 吝啬原则:除非没办法,不要编写庞大的程序
- 透明性原则:设计要可见,以便审查和调试
- 健壮原则:健壮源于透明和简洁
- 表示原则:把知识叠入数据以求质朴而健壮
- 通俗原则:接口设计避免标新立异
- 缄默原则:如果一个程序没有什么好说的,就保持沉默
- 补救原则:出现异常的时候,马上退出并给出足量的错误信息
- 经济原则:宁花机器一分,不花程序员一秒
- 生成原则:避免手工hack,尽量编写程序去生成程序
- 优化原则:雕琢前先得有原型,跑之前先学会走
多样原则:绝不相信所谓的 "不二门法" 的断言
拓展原则:设计着眼未来,未来总比预想的快
一句话 KISS (keep it simple, stupid!) 原则
- 协作式多任务和抢占式多任务在操作系统设计时候就会考虑到,所以协程的概念并不新鲜。
- 清晰的接口把简单的模块结合起来构成复杂的系统,这样一来即时出现问题,也是局部问题,不至于导致整体无法使用
- 模块设计
- 紧凑性 就是一个设计是否能装进人的大脑。 甚至不需要手册就能使用
- 正交性 操作无副作用,只做好一件事(利于开发和测试)
- STOP原则 真理的单点性类似于DRY原则 (例如代码生成器)
- 解决一个定义明确的问题
- 分离的价值 不要在意工具,在意是否适用
- 自顶向下设计和自下向上设计相结合,一般需要胶合层,胶合层要尽量的薄,尽量简单。C语言就是很好的例证。
- 完美之道,不在无可增加,而在无可删减
文本化:好协议产生好实践
- 如果可能,以新行符结束的每一行只存一个记录
- 如果可能,每行不超过80个字符
- 使用 "#" 来注释
- 支持反斜杠约定,主要是一些转义问题
- 不要过分区分tab和空白
- 优先使用16进制而不是8进制
- 节格式中支持连续行
- 要么包含一个版本号,要么将格式设置成相互独立的自描述字节块
- 注意浮点数取整问题
- 不要仅对文件的一部分进行压缩或者二进制编码
透明性 可显性
主要是说易用,代码可读性,以及代码的可理解性。
编写透明,可显的系统而节省的经历,将来可能完全就是自己的财富
多道程序设计
- 线程,共用统一存储地址空间的多个并发进程。不到万不得已,不使用线程。
- 对等进程间通信(和管道相比,可以双向通信)
- 临时文件(技巧,临时文件名中包含
$$
, 防止多个实例进程一起通信,数据混乱)古老的方式,但是也有用武之地
- 信号,经常用到的一个技巧是pidfile,方面pid获取和当文件锁来使用
- 套接字,适合分布式
- 共享内存 mmap
- 进程间的通信就是交换数据,只是在不同的场景和性能要求下才会出现那么多不同的方式。
微型语言 寻找歌唱的乐符
看到标题就想到了DSL,openresty的作者春哥经常提到这种解决问题的思路。
数据驱动编程
- 尽可能把设计的复杂度从程序代码转移到数据中是个好实践。
配置:迈出正确的第一步
- 对于能够可靠的进行自动检查的东西,就不要提供配置开关
- 能用脚本包装器或者简单管道完成的任务,就不要用配置开关实现
- 命令行选项常用的2中风格
-a
属于传统Unxi风格,--all
属于GUN风格
最小立异原则:如果有可能,尽量允许用户将接口功能委派给熟悉的程序来完成。 其实就是说最好使用那些设计良好并且用户已经熟悉的接口设计,或者接口程序,这样减少了使用者的学习成本,如果有更好的设计当然也要尝试。
发布: 频繁的发布的原因是为了缩短同用户和开发者间的反馈循环。 因此,精细工作,等一切完美了才发布的想法是要不得的。
开源协同的最佳实践
- 良好的修补实践,可以参照github大家pr的流程和规范
- 补丁中,或者补丁对应的文档需要不全
- 如果patch被拒绝,不要往心里去
- 不要依赖专有代码,也就是说不要随便引入第三方库,这样会给维护者带来更多的负担,软件会有更多的不确定性
- 先测试,在发布代码(测试用例一定要补全,而且自己测试通过)
- 良好的制作发行流程和规范
怎样写readme?
- 剪短的项目描述
- 指向项目站点的链接
- 开发者编译环境的注意事项以及潜在的可移植性性问题
- 描述重要文件和子目录的路标
- 安装指南
- 开发者列表
- 社区以及联系方式等
预测未来的最好方法就是创造未来