106.基于线程的管理者/工人并行模型一般将耗时的或阻塞的操作分配给工人子任务, 从而维护中心任务的响应性.
107.基于进程的管理者/工人并行模型一般用来重用现有的程序, 或用定义良好的接口组织和分离粗粒度的系统模块.
108.基于流水线的并行处理中, 每个任务都接收到一些输入, 对它们进行一些处理, 并将生成的输出传递给下一个任务, 进行不同的处理.
109.竞争条件很难捉摸, 相关的代码常常会将竞争条件扩散到多个函数或模块; 因而, 很难隔离由于竞争条件导致的问题.
110.对于出现在信号处理器中的数据结构操作代码和库调用要保持高度警惕.
111.在阅读包含宏的代码时, 要注意, 宏既非函数, 也非语句.
112.do…while(0)块中的宏等同于控制块中的语句.
113.宏可以访问在它的使用点可见的所有局部变量.
114.宏调用可改变参数的值
115.基于宏的标记拼接能够创建新的标记符. +++++++++++++++++
第六章: 应对大型项目
+++++++++++++++++
116.我们可以通过浏览项目的源代码树—包含项目源代码的层次目录结构, 来分析一个项目的组织方式. 源码树常常能够反映出项目在构架和软件过程上的结构.
117.应用程序的源代码树经常是该应用程序的部署结构的镜像.
118.不要被庞大的源代码集合吓倒; 它们一般比小型的专门项目组织得更出色.
119.当您首次接触一个大型项目时, 要花一些时间来熟悉项目的目录树结构.
120.项目的源代码远不只是编译后可以获得可执行程序的计算机语言指令; 一个项目的源码树一般还包括规格说明|最终用户和开发人员文档|
测试脚本|多媒体资源|编译工具|例子|本地化文件|修订历史|安装过程和许可信息.
121.大型项目的编译过程一般声明性地借助依赖关系来说明. 依赖关系由工具程序, 如make及其派生程序, 转换成具体的编译行动.
122.大型项目中, 制作文件常常由配置步骤动态地生成; 在分析制作文件之前, 需要先执行项目特定的配置.
123.检查大型编译过程的各个步骤时, 可以使用make程序的-n开关进行预演.
124.修订控制系统提供从储存库中获取源代码最新版本的方式.
125.可以使用相关的命令, 显示可执行文件中的修订标识关键字, 从而将可执行文件与它的源代码匹配起来.
126.使用修订日志中出现的bug跟踪系统内的编号, 可以在bug跟踪系统的数据库中找到有关的问题的说明.
127.可以使用修订控制系统的版本储存库, 找出特定的变更是如何实现的.
128.定制编译工具用在软件开发过程的许多方面, 包括配置|编译过程管理|代码的生成|测试和文档编制.
129.程序的调试输出可以帮助我们理解程序控制流程和数据元素的关键部分.
130.跟踪语句所在的地点一般也是算法运行的重要部分.
131.可以用断言来检验算法运作的步骤|函数接收的参数|程序的控制流程|底层硬件的属性和测试用例的结果.
132.可以使用对算法进行检验的断言来证实您对算法运作的理解, 或将它作为推理的起点.
133.对函数参数和结果的断言经常记录了函数的前置条件和后置条件.
134.我们可以将测试整个函数的断言作为每个给定函数的规格说明.
135.测试用例可以部分地代替函数规格说明.
136.可以使用测试用例的输入数据对源代码序列进行预演.
+++++++++++++++++++
第七章: 编码规范和约定
+++++++++++++++++++
137.了解了给定代码库所遵循的文件组织方式后, 就能更有效率地浏览它的源代码.
138.阅读代码时, 首先要确保您的编辑器或优美打印程序的tab设置, 与代码遵循的风格规范一致.
139.可以使用代码块的缩进, 快速地掌握代码的总体结构.
140.对编排不一致的代码, 应该立即给予足够的警惕.
141.分析代码时, 对标记为XXX, FIXME和TODO的代码序列要格外注意: 错误可能就潜伏在其中.
142.常量使用大写字母命名, 单词用下划线分隔.
143.在遵循Java编码规范的程序中, 包名(package name)总是从一个顶级的域名开始(例如, org, com), 类名和接口名由大写字母开始, 方法和变量名由小写字母开始.
144.用户界面控件名称之前的匈牙利记法的前缀类型标记可以帮助我们确定它的作用.
145.不同的编程规范对可移植构造的构成有不同的主张.
146.在审查代码的可移植性, 或以某种给定的编码规范作为指南时, 要注意了解规范对可移植性需求的界定与限制.
147.如果GUI功能都使用相应的编程结构来实现, 则通过代码审查可以轻易地验证给定用户界面的规格说明是否被正确地采用.
148.了解项目编译过程的组织方式与自动化方式之后, 我们就能够快速地阅读与理解对应的编译规则.
149.当检查系统的发布过程时, 常常可以将相应发行格式的需求作为基准. ++++++++++++
第八章: 文档 ++++++++++++
150.阅读代码时, 应该尽可能地利用任何能够得到的文档.
151.阅读一小时代码所得到的信息只不过相当于阅读一分钟文档.
152.使用系统的规格说明文档, 了解所阅读代码的运行环境.
153.软件需求规格说明是阅读和评估代码的基准.
154.可以将系统的设计规格说明作为认知代码结构的路线图, 阅读具体代码的指引.
155.测试规格说明文档为我们提供可以用来对代码进行预演的数据.
156.在接触一个未知系统时, 功能性的描述和用户指南可以提供重要的背景信息,从而更好地理解阅读的代码所处的上下文.
157.从用户参考手册中, 我们可以快速地获取, 应用程序在外观与逻辑上的背景知识, 从管理员手册中可以得知代码的接口|文件格式和错误消息的详细信息.
158.利用文档可以快捷地获取系统的概况, 了解提供特定特性的代码.
159.文档经常能够反映和提示出系统的底层结构.
160.文档有助于理解复杂的算法和数据结构.
161.算法的文字描述能够使不透明(晦涩, 难以理解)的代码变得可以理解.
162.文档常常能够阐明源代码中标识符的含义.
163.文档能够提供非功能性需求背后的理论基础.
164.文档还会说明内部编程接口.
165.由于文档很少像实际的程序代码那样进行测试, 并受人关注, 所以它常常可能存在错误|不完整或过时.
166.文档也提供测试用例, 以及实际应用的例子.
167.文档常常还会包括已知的实现问题或bug.
168.环境中已知的缺点一般都会记录在源代码中.
169.文档的变更能够标出那些故障点.
170.对同一段源代码重复或互相冲突的更改, 常常表示存在根本性的设计缺陷, 从而使得维护人员需要用一系列的修补程序来修复.
171.相似的修复应用到源代码的不同部分, 常常表示一种易犯的错误或疏忽, 它
们同样可能会在其他地方存在.
172.文档常常会提供不恰当的信息, 误导我们对源代码的理解.
173.要警惕那些未归档的特性: 将每个实例归类为合理|疏忽或有害, 相应地决定是否应该修复代码或文档.
174.有时, 文档在描述系统时, 并非按照已完成的实现, 而是系统应该的样子或将来的实现.
175.在源代码文档中, 单词gork的意思一般是指”理解”.
176.如果未知的或特殊用法的单词阻碍了对代码的理解, 可以试着在文档的术语表(如果存在的话)|New Hacker’s Dictionary[Ray96]|或在
Web搜索引擎中查找它们.
177.总是要以批判的态度来看待文档, 注意非传统的来源, 比如注释|标准|出版物|测试用例|邮件列表|新闻组|修订日志|问题跟踪数据库|营销材料|源代码本身.
178.总是要以批判的态度来看待文档; 由于文档永远不会执行, 对文档的测试和正式复查也很少达到对代码的同样水平, 所以文档常常会误导读者, 或者完全错误.
179.对于那些有缺陷的代码, 我们可以从中推断出它的真实意图.
180.在阅读大型系统的文档时, 首先要熟悉文档的总体结构和约定.
181.在对付体积庞大的文档时, 可以使用工具, 或将文本输出到高品质输出设备上, 比如激光打印机, 来提高阅读的效率.
++++++++++++++
第九章: 系统构架
++++++++++++++
182.一个系统可以(在重大的系统中也确实如此)同时出多种不同的构架类型. 以不同的方式检查同一系统|分析系统的不同部分|或使用不同级别的分解, 都有可能发现不同的构架类型.
183.协同式的应用程序, 或者需要协同访问共享信息或资源的半自治进程, 一般