menu XUJINKAI 的个人主页
create settings
home
主页
list
全部博文
  • Collection
  • About
  • assistant_photo
    个人项目
    person
    关于

    《Unix编程艺术》读书笔记

    Tags: 编程 📕

    Keep It Simple, Stuipid!

    此书写于2003年,里边有一些东西是过时的。
    比如版本控制系统一节,并没有提到git(2005年才发明),同样,文档格式也没有markdown的内容。

    而有些内容,比如说到vi和emacs,或说到Windows时,有些过于有偏向性了,就像译者序里说的像个“美国愤青”。

    不过抛开这部分内容,关于程序设计方面的讨论,确实是让人受益颇多。

    在第一章,书中提到了以下一些原则:

    模块原则:使用简洁的接口拼合简单的部件
    组合原则:设计时考虑拼接组合
    简洁原则:设计要简洁,复杂度能低则低
    吝啬原则:除非却无它法,不要编写庞大的程序
    
    清晰原则:清晰胜于机巧
    分离原则:策略同机制分离,接口同引擎分离
    表示原则:把知识叠入数据以求逻辑质朴而健壮
    生成原则:避免手工hack,尽量编写程序去生成程序
    
    通俗原则:接口设计避免标新立异
    透明性原则:设计要可见,以便审查和调试
    缄默原则:如果一个程序没什么好说的,就保持沉默
    补救原则:出现异常时,马上退出并给出足够错误信息
    
    优化原则:雕琢前先得有原型,跑之前先学会走
    多样原则:绝不相信所谓“不二法门”的断言(指软件作者无法预想到软件的所有用途)
    
    健壮原则:健壮源于透明和简洁
    经济原则:宁花机器一分,不花程序员一秒
    扩展原则:设计着眼于未来,未来总比预想快
    

    简单的分分类:

    模块、组合、简洁、吝啬,讲的是控制程序复杂度,就是我们现在说的模块化,高内聚低耦合;

    清晰原则,指出代码更是给人看的,所以清晰的代码更易于维护和减少bug;
    分离原则,指的就是表驱动法;
    表示原则,指出了数据比编程逻辑更加清晰,同样指向了分离数据;
    生成原则,指用代码生成完成重复劳动;

    通俗、透明性,指向程序接口设计;
    缄默、补救,指向程序行为设计;

    优化、多样,说出了那句名言:过早优化是万恶之源。

    健壮、经济、扩展,与程序设计时的理念相关。

    模块化

    软件设计的两种方式:一是明显没有bug,而是没有明显的bug。

    API作为模块之间的滞塞点(choke point),隔离了模块内部的细节,同时API也定义了整个体系(而不是具体实现代码)。

    API的设计需要考虑两个特性:紧凑性和正交性。
    紧凑指一个设计能否装进人脑,一眼能够看懂。(不一定小巧)
    正交指无副作用。

    SPOT原则(single point of truth);DRY原则(don’t repeat yourself);
    缓存可能是种过早优化,而且缓存是bug的温床;
    大量重复的代码,也许可以通过更高级的表现形式生成。

    甚用全局变量;
    每写一个函数原型,立即增加一行注释(可以用一句话描述函数功能及约定);
    参数/成员的最佳个数:7个以内;模块的最佳行数:200到400行以内。

    文本化

    这一章讲了文本化协议的优点,互用、透明、可扩展。

    除非需要紧凑及性能,否则文本化永远是个好选择。

    后边列举了一些常见的文本化格式:

    DSV风格

    Delimiter-Separated Values

    如Unix口令文件(/etc/passwd文件)以冒号分隔;或CSV逗号分隔。

    注意需要使用转义符号支持分隔符本身和换行;再就是使用空格而不是制表符(因为视觉上无法辨别)。

    作者这里抨击了Windows的CSV格式,CSV使用双引号而不是转义来处理字段值包含分隔符的情况,引入了过多的特殊情况,造成了格式和程序的复杂度上升。

    XML

    这个不多说了,结论是XML既可能简化问题,也可能使问题复杂化。

    INI格式

    两层组织结构更适合INI格式(section是第一层)。

    作者这里还不知道的是,git的配置文件就是ini格式的(哈哈)。

    JSON

    因为书是03年的,作者并没有提到JSON格式。这里我加上,是因为JSON格式现在太重要了,作为数据存储和通信协议都很不错。

    注意事项

    后边作者讲了一些文本化格式约定俗成的内容,如用井号#注释,使用反斜杠\转义,忽略LF和CRLF的区别,忽略空格和制表符的区别,包含一个版本号,注意浮点数取整的问题等。

    通信协议

    书中主要例举了SMTP、POP3、IMAP这些邮件协议,以及HTTP协议。

    邮件协议给我的启示是,在给机器读的状态码之后加入给人读的文本描述,让调试更容易。

    不过邮件协议应该是有状态的,作为对比,HTTP是无状态的。

    最后作者也讲到了XML-RPC、SOAP这样的RPC协议。

    容我最后再提到谷歌的protobuf和gRPC,让这一节更加完整。

    透明性

    透明性/可显性,就是将软件的行为展示出来,降低使用时的心智负担。

    作者例举的是音频编辑软件的波形图,大多数软件都有的–verbose选项,以及gcc可以将每个阶段的结果都输出出来。

    编码时也要注意透明性,如调用层次超过4层就要当心,注意API的正交性,少用magic number等。

    在做GUI设计时,也要暴露出一定的内部细节,避免过度保护。

    接口设计

    这里的接口指和用户打交道的接口,如GUI、CLI等。

    CLI设计时,注意数据要宽进严出,以方便其他程序将这些输出作为输入。不需要的信息不丢弃。以及不增加无用的输出(如将1.5写成150%)。

    配置

    Unix中的配置查找顺序:

    • /etc下的配置文件(即全局配置)
    • 系统环境变量
    • 用户主目录下的配置文件
    • 用户环境变量
    • 命令行参数

    以上按照顺序查找,一个例外是,通过命令行指定配置文件路径。

    书中也提到了常见的命令行单字母参数,如-l表示list,-a表示all,这里不再多说。设计时符合通俗原则,不要标新立异即可。

    更多

    书中内容不仅这些。

    第7章讲了通过各种IPC手段,如管道,socket等,分解任务,以不同的程序去实现目标。

    第8章讲了使用微型语言(如正则表达式,m4模板),第9章讲了代码生成以及数据驱动编程。

    第16章讲到另一句名言:不要重新发明轮子。

    最后一章,作者也少见的讲了Unix系统的各种缺陷。

    作为读书笔记,到这里就可以了。


    Disqus评论加载中。。。