代码质量
季奥米季斯·斯宾耐立思(Diomidis Spinellis),自1985年开始,在开发大量开创性的,并受到极高评价的商业和开源项目的过程中,一直在钻研、发展本书中所提及的各项技术,期间他编写和维护的代码行数超过25万行。他在英国伦敦帝国理工学院获得了软件工程方向的硕士学位及计算机科学博士学位。目前,他是希腊雅典经济与商业大学管理科学与技术系的教授。他曾撰写过多部畅销世界的计算机技术图书,包括《架构之美》、《代码质量》和《代码阅读》等。
左飞,技术作家、译者,著有《代码揭秘》、《数字图像处理原理与实践:基于VisualC++开发》、《大话TD-SCDMA》等书。2011年在国家示范软件学院成立10周年庆祝大会上,他被授予“全国十佳毕业生”荣称,以表彰其在专业领域所做出的突出成绩。
吴跃,国家公务员,开源软件爱好者。他在信息安全方面有丰富的实践…
查看完整
左飞,技术作家、译者,著有《代码揭秘》、《数字图像处理原理与实践:基于VisualC++开发》、《大话TD-SCDMA》等书。2011年在国家示范软件学院成立10周年庆祝大会上,他被授予“全国十佳毕业生”荣称,以表彰其在专业领域所做出的突出成绩。
吴跃,国家公务员,开源软件爱好者。他在信息安全方面有丰富的实践…
查看完整
Jolt大奖素有"软件业之奥斯卡"的美称,本丛书精选自Jolt历届获奖图书,以植根于开发实践中的独到工程思想与杰出方法论为主要甄选方向。Diomidis Spinellis首部著作《代码阅读》(Code Reading)旨在阐明程序员应如何理解与修改代码,与此不同的是,《代码质量》重点讨论代码的非功能特性,深入讲述代码如何满足重要的非功能性需求,如可靠性、安全性、可移植性和可维护性,以及时间效率和空间效率。本书从Apache Web应用服务器、BSD UNIX操作系统和HSQLDB Java数据库等开源项目中攫取数百个小例子,并以实例为基准点,辅以理论分析,从实用的角度讲述每个专业软件开发人员能立即运用的概念和技术。
《代码质量》荣获2007年Jolt大奖,适用于不同知识层次的软件工作、程序开发和研究人员。
《代码质量》荣获2007年Jolt大奖,适用于不同知识层次的软件工作、程序开发和研究人员。
表目录
图目录
原书序言
前言
第1章 导论
1.1 软件质量
1.1.1 用户、制造者和管理者眼中的质量
1.1.2 质量属性
1.1.3 紧张的世界
1.2 如何阅读本书
1.2.1 排版约定
1.2.2 图示
1.2.3 图表
1.2.4 汇编代码
1.2.5 练习
1.2.6 补充材料
1.2.7 工具
第2章 可靠性
2.1 输入问题
2.2 输出问题
2.2.1 不完整输出或输出缺失
2.2.2 错误时刻的正确结果
2.2.3 错误的格式
2.3 逻辑问题
2.3.1 偏差为一的错误与循环迭代
2.3.2 被忽视的极端情况
2.3.3 被遗漏的情况、条件测试或步骤
2.3.4 被遗漏的方法
2.3.5 多余的功能
2.3.6 误解
2.4 计算问题
2.4.1 不正确的算法或计算
2.4.2 表达式中错误的操作数
2.4.3 表达式中不正确的运算符
2.4.4 运算符优先级问题
2.4.5 溢出、下溢和符号转换错误
2.5 并行性与时序问题
2.6 接口问题
2.6.1 不正确的例程或参数
2.6.2 没有测试返回值
2.6.3 未做错误探查或恢复
2.6.4 资源泄漏
2.6.5 面向对象功能的误用
2.7 数据处理问题
2.7.1 不正确的数据初始化
2.7.2 引用错误的数据变量
2.7.3 越界引用
2.7.4 不正确的下标使用
2.7.5 不正确的比例或数据单位
2.7.6 错误的数据打包与解包
2.7.7 不一致的数据
2.8 容错
2.8.1 管理策略
2.8.2 空间冗余
2.8.3 时间冗余
2.8.4 可复原性
第3章 安全性
3.1 脆弱代码
3.2 缓冲区溢出
3.3 竞态条件
3.4 问题API
3.4.1 容易出现缓冲区溢出的函数
3.4.2 格式字符串漏洞
3.4.3 路径和命令行解释器元字符漏洞
3.4.4 临时文件
3.4.5 不适合做加密用途的函数
3.4.6 可篡改数据
3.5 不可信输入
3.6 结果验证
3.7 数据与特权泄漏
3.7.1 数据泄漏
3.7.2 特权泄漏
3.7.3 Java的方案
3.7.4 分离特权代码
3.8 特洛伊木马
3.9 工具
第4章 时间性能
4.1 测量技术
4.1.1 负载描述
4.1.2 受限于I/O的任务
4.1.3 受限于内核的任务
4.1.4 受限于CPU的任务和剖析工具
4.2 算法复杂性
4.3 独立的代码
4.4 与操作系统交互
4.5 与外设交互
4.6 非故意的交互
4.7 缓存
4.7.1 一个简单的系统调用缓存
4.7.2 替换策略
4.7.3 预先计算结果
第5章 空间性能
5.1 数据
5.1.1 基本数据类型
5.1.2 聚合数据类型
5.1.3 对齐
5.1.4 对象
5.2 内存组织
5.3 内存层级结构
5.3.1 主存及其高速缓存
5.3.2 磁盘缓存和后备存储器
5.3.3 交换区和基于文件的磁盘存储
5.4 进程/操作系统接口
5.4.1 内存分配
5.4.2 内存映射
5.4.3 数据映射
5.4.4 代码映射
5.4.5 访问硬件资源
5.4.6 进程间通信
5.5 堆内存管理
5.5.1 堆碎片
5.5.2 堆剖析
5.5.3 内存泄漏
5.5.4 垃圾回收
5.6 栈内存管理
5.6.1 栈帧
5.6.2 栈空间
5.7 代码
5.7.1 设计期
5.7.2 编码期
5.7.3 构建期
第6章 可移植性
6.1 操作系统
6.2 硬件与处理器架构
6.2.1 数据类型的属性
6.2.2 数据存储
6.2.3 特定于机器的代码
6.3 编译器与语言扩展
6.3.1 编译器错误
6.4 图形用户界面(GUI)
6.5 国际化与本地化
6.5.1 字符集
6.5.2 区域
6.5.3 消息
第7章 可维护性
7.1 测量可维护性
7.1.1 可维护性指数
7.1.2 面向对象程序的度量
7.1.3 包的相关性度量
7.2 可分析性
7.2.1 一致性
7.2.2 表达式格式化
7.2.3 语句格式化
7.2.4 命名惯例
7.2.5 语句级注释
7.2.6 版本注释
7.2.7 视觉结构:块与缩进
7.2.8 表达式、函数以及方法的长度
7.2.9 控制结构
7.2.10 布尔表达式
7.2.11 可辨认性与内聚性
7.2.12 依赖和耦合
7.2.13 代码块注释
7.2.14 数据声明注释
7.2.15 恰当的标识符名字
7.2.16 依赖的位置
7.2.17 不确定性
7.2.18 可复查性
7.3 可变性
7.3.1 识别
7.3.2 分离
7.4 稳定性
7.4.1 封装与数据隐藏
7.4.2 数据抽象
7.4.3 类型检查
7.4.4 编译时断言
7.4.5 运行时检查和查看时断言
7.5 可测试性
7.5.1 单元测试
7.5.2 集成测试
7.5.3 系统测试
7.5.4 测试覆盖度分析
7.5.5 偶发性测试
7.6 开发环境的影响
7.6.1 增量构建
7.6.2 调整构建性能
第8章 浮点运算
8.1 浮点数表示
8.1.1 量度误差
8.1.2 舍入
8.1.3 内存格式
8.1.4 规格化和隐含的一位
8.1.5 阶码偏移
8.1.6 负数
8.1.7 反向规格化数
8.1.8 特殊值
8.2 舍入
8.3 溢出
8.4 下溢
8.5 消去
8.6 合并
8.7 无效运算
附录A 源代码致谢人员名单
参考文献
表 目 录
表2-1 测试极端情况
表2-2 测试一个不含尾端的非对称范围的例子
表2-3 整数量的范围
表2-4 在程序生命周期不同阶段所做的参数类型检查
表2-5 在C++中约束类的使用
表3-1 UNIX服务器开放网络端口列表
表3-2 Windows工作站开放网络端口列表
表3-3 进行ftpd缓冲区攻击时的栈
表3-4 展开栈(默认情况)
表3-5 在攻击过程中展开栈
表3-6 不安全的C函数及其安全的替代函数
表3-7 Java 2平台SE 5.0的许可
表4-1 用时剖析特征、诊断工具及解决方案
表4-2 由环境切换和进程间通信导致的开销
表4-3 低速外设导致的开销
表5-1 不同架构下基本数据类型的表示
表5-2 AMD64架构上结构体元素的对齐
表5-3 一个程序在不同架构和操作系统上的内存布局
表5-4 连续的地址空间限制及相应的解决方案
表5-5 构建选项对程序大小的影响
表6-1 各种开发平台的可移植性问题
表6-2 Java平台标准字符编码
表6-3 区域特定的字段
表7-1 可维护性指数的参数
表7-2 WebServerConnection方法与它们使用的字段
表7-3 WebServerConnection类的相似(内聚)方法与相异方法
表7-4 不同类型的访问控制下可以访问类成员的方法数
表8-1 不同舍入模型的例子
表8-2 不同浮点格式的关键属性
表8-3 导致异常的运算和操作数
图 目 录
图1-1 软件质量的各个方面的例子:使用中质量、
外部质量、内部质量及过程质量
图1-2 本书脉络:软件质量的要素
图1-3 质量特征间的冲突
图1-4 标注列表示例
图1-5 基于UML的图示符号
图2-1 使用评注,toString方法的反射式实现
图2-2 借助策略模式关联代码和数据
图2-3 使用接口实现创建处理器
图2-4 对象私有资源的显式管理
图2-5 邮件传送代理守护程序sendmail的调试代码
图2-6 通过静态分析探查null指针引用
图2-7 借助wait和notify管理资源的使用
图2-8 使用有瑕疵的双检锁模式
图2-9 内存泄漏与资源泄漏之间的关系
图2-10 在NetBSD内核中分配与释放文件描述符
图2-11 使用自动产生的源代码定义字体的轮廓
图2-12 NetBSD源代码中全局变量定义(左)和引用(右)的位置
图2-13 NetBSD内核全局变量所用的类型
图2-14 将字节串编码为改进过的UTF-8格式
图2-15 SCSI设备驱动程序中一个命令序列重传
图2-16 自有故障的磁盘上恢复数据
图3-1 FTP守护进程中的缓冲区溢出
图3-2 PPP守护代码中的一个竞态条件
图3-3 pppd漏洞的检查/使用时间差利用
图3-4 检查/使用时间差漏洞利用时序图
图3-5 strcpy和strcat的不安全用法
图3-6 strcpy和strcat正确应用在一个动态分配大小的缓冲区上
图3-7 不安全地清除环境变量
图3-8 安全地清除环境变量
图3-9 未正确检查traceroute实现中的错误返回值
图3-10 在TCP Wrappers程序中嵌入特洛伊木马代码
图4-1 专家对于优化代码的警告
图4-2 在HSQLDB代码中EJP对帕累托法则的阐述
图4-3 对于vfprintf函数的gprof输出的例子
图4-4 调用图中处理时间的传播
图4-5 某些常见算法类别的相对性能
图4-6 简单cat调用中的系统调用
图4-7 logger调用时本地进程间通信产生的系统调用
图4-8 ping名字查询的远程DNS进程间通信所产生的系统调用
图4-9 系统颠簸对运行时性能的影响
图4-10 使用用户ID来命名缓存代码
图4-11 缓存数据库行记录
图5-1 结构体的两种存储方式:填充以确保对齐(上),打包以节省内存(下)
图5-2 从大到小排列结构体元素,确保对齐且节省内存
图5-3 OpenCL算法继承树的UML类图
图5-4 三个OpenCL算法类的C++虚函数表
图5-5 指向实例数据的Java对象
图5-6 有着一个指向实例数据和类数据的句柄的Java对象
图5-7 内存资源的类型
图5-8 进程内存组织
图5-9 现代计算机的一个存储层次结构
图5-10 100万个分配对象的大小分布
图5-11 100万个分配对象的生命周期分布
图5-12 用于显示内存碎片的内存池快照
图5-13 外部内存碎片的一个例子
图5-14 内部内存碎片的一个例子
图5-15 Apache HTTP服务器内存分配剖析
图5-16 sed流编辑器的内存剖析
图5-17 valgrind内存泄漏测试工具的报告
图5-18 C正则表达式库中的内存泄漏
图5-20 一个栈帧的内容
图5-21 栈大小的快照
图5-22 数据和栈大小的关系
图5-23 源文件与目标文件大小之间的关系
图5-24 ACE地址类型中的继承
图6-1 使用隔离层来提供可移植性
图6-2 存储于小端与大端架构上的整数0x04030201
图6-3 GUI可移植性策略的例子
图6-4 使用catgets接口做消息处理
图6-5 使用gettext接口做消息处理
图6-6 使用GNU gettext工具的消息本地化流程
图6-7 在Java servlet中访问本地化消息
图7-1 测量扩展圈复杂度
图7-2 FreeBSD内核和用户程序的增长与可维护性指标随时间的变化
图7-3 所有FreeBSD模块的可维护性指数分布
图7-4 类的加权方法数度量:对所有的HSQLDB类(左);
不同的WMC值对应的Eclipse类个数(右)
图7-5 继承树深度度量:对于所有的HSQLDB类(左);
不同DIT值对应的Eclipse类的数量(右)
图7-6 HSQLDB:高DIT值的类的继承树度量和它们所定义的方法数
图7-7 Eclipse类的子类数度量
图7-8 对象类之间的耦合:对于每个HSQLDB类(左);
不同的CBO值对应的Eclipse类的数量(右)
图7-9 类的响应:对于所有的HSQLDB类(左);
不同的CBO值对应的Eclipse类的数量(右)
图7-10 方法的内聚缺乏度:对于所有的HSQLDB类(左);
对应于不同LCOM值的Eclipse类的个数(右)
图7-11 org.hsqldb包中的公有类和私有类
图7-12 Tomcat中一个不稳定的包
图7-13 Eclipse中一个稳定的包
图7-14 Eclipse的离心耦合与向心耦合之间的关系
图7-15 Eclipse包(左)和第三方包(右)的不稳定性分布
图7-16 junit包的稳定依赖
图7-17 MX4J包的不太稳定依赖
图7-18 Eclipse包的不稳定性与抽象度分布
图7-19 Xerces与Eclipse间的循环依赖
图7-20 所有的FreeBSD模块可维护性指数与模块大小的关系
图7-21 65000个C函数的函数长度分布
图7-22 在处理用户响应的过程中缺乏规则性
图7-23 用于处理用户响应的一个规则的控制结构
图7-24 在同一代码段里不同的break和continue范围
图7-25 ed的DES CBC实现中的公共耦合
图7-26 ed的DES CBC实现中的公共耦合关系
图7-27 在NetBSD内核中读取并使用磁盘分区内核
图7-28 低带宽X(LBX)扩展中增量缓存的设计
图7-29 低带宽X(LBX)扩展中增量缓存的实现
图7-30 servlet容器各元素间不必要的关系
图7-31 使用责任链设计模式来分离类
图7-32 两个不同的Catalina文件的公共代码行
图7-33 难以修改的格式化注释(左)与便于修改的格式化注释(右)
图7-34 在最内部的代码块中声明变量
图7-35 第7版UNIX中直接解释目录的数据
图7-36 Java 1.5之前的代码使用松散类型
图7-37 C库fomd实现中的特别单元测试
图7-38 JUnit测试框架中的单元测试
图7-39 Perl源代码测试覆盖度(左)和分支覆盖度(右)与测试用例执行数的关系
图7-40 正则表达式引擎中断言的使用
图7-41 包含文件依赖关系的简化图
图7-42 文档依赖
图8-1 二次方程消去误差以及对精度的影响
图8-2 计算远离原点的三角形面积时的合并误差
图8-3 验证浮点运算结果的代码
^ 收 起
图目录
原书序言
前言
第1章 导论
1.1 软件质量
1.1.1 用户、制造者和管理者眼中的质量
1.1.2 质量属性
1.1.3 紧张的世界
1.2 如何阅读本书
1.2.1 排版约定
1.2.2 图示
1.2.3 图表
1.2.4 汇编代码
1.2.5 练习
1.2.6 补充材料
1.2.7 工具
第2章 可靠性
2.1 输入问题
2.2 输出问题
2.2.1 不完整输出或输出缺失
2.2.2 错误时刻的正确结果
2.2.3 错误的格式
2.3 逻辑问题
2.3.1 偏差为一的错误与循环迭代
2.3.2 被忽视的极端情况
2.3.3 被遗漏的情况、条件测试或步骤
2.3.4 被遗漏的方法
2.3.5 多余的功能
2.3.6 误解
2.4 计算问题
2.4.1 不正确的算法或计算
2.4.2 表达式中错误的操作数
2.4.3 表达式中不正确的运算符
2.4.4 运算符优先级问题
2.4.5 溢出、下溢和符号转换错误
2.5 并行性与时序问题
2.6 接口问题
2.6.1 不正确的例程或参数
2.6.2 没有测试返回值
2.6.3 未做错误探查或恢复
2.6.4 资源泄漏
2.6.5 面向对象功能的误用
2.7 数据处理问题
2.7.1 不正确的数据初始化
2.7.2 引用错误的数据变量
2.7.3 越界引用
2.7.4 不正确的下标使用
2.7.5 不正确的比例或数据单位
2.7.6 错误的数据打包与解包
2.7.7 不一致的数据
2.8 容错
2.8.1 管理策略
2.8.2 空间冗余
2.8.3 时间冗余
2.8.4 可复原性
第3章 安全性
3.1 脆弱代码
3.2 缓冲区溢出
3.3 竞态条件
3.4 问题API
3.4.1 容易出现缓冲区溢出的函数
3.4.2 格式字符串漏洞
3.4.3 路径和命令行解释器元字符漏洞
3.4.4 临时文件
3.4.5 不适合做加密用途的函数
3.4.6 可篡改数据
3.5 不可信输入
3.6 结果验证
3.7 数据与特权泄漏
3.7.1 数据泄漏
3.7.2 特权泄漏
3.7.3 Java的方案
3.7.4 分离特权代码
3.8 特洛伊木马
3.9 工具
第4章 时间性能
4.1 测量技术
4.1.1 负载描述
4.1.2 受限于I/O的任务
4.1.3 受限于内核的任务
4.1.4 受限于CPU的任务和剖析工具
4.2 算法复杂性
4.3 独立的代码
4.4 与操作系统交互
4.5 与外设交互
4.6 非故意的交互
4.7 缓存
4.7.1 一个简单的系统调用缓存
4.7.2 替换策略
4.7.3 预先计算结果
第5章 空间性能
5.1 数据
5.1.1 基本数据类型
5.1.2 聚合数据类型
5.1.3 对齐
5.1.4 对象
5.2 内存组织
5.3 内存层级结构
5.3.1 主存及其高速缓存
5.3.2 磁盘缓存和后备存储器
5.3.3 交换区和基于文件的磁盘存储
5.4 进程/操作系统接口
5.4.1 内存分配
5.4.2 内存映射
5.4.3 数据映射
5.4.4 代码映射
5.4.5 访问硬件资源
5.4.6 进程间通信
5.5 堆内存管理
5.5.1 堆碎片
5.5.2 堆剖析
5.5.3 内存泄漏
5.5.4 垃圾回收
5.6 栈内存管理
5.6.1 栈帧
5.6.2 栈空间
5.7 代码
5.7.1 设计期
5.7.2 编码期
5.7.3 构建期
第6章 可移植性
6.1 操作系统
6.2 硬件与处理器架构
6.2.1 数据类型的属性
6.2.2 数据存储
6.2.3 特定于机器的代码
6.3 编译器与语言扩展
6.3.1 编译器错误
6.4 图形用户界面(GUI)
6.5 国际化与本地化
6.5.1 字符集
6.5.2 区域
6.5.3 消息
第7章 可维护性
7.1 测量可维护性
7.1.1 可维护性指数
7.1.2 面向对象程序的度量
7.1.3 包的相关性度量
7.2 可分析性
7.2.1 一致性
7.2.2 表达式格式化
7.2.3 语句格式化
7.2.4 命名惯例
7.2.5 语句级注释
7.2.6 版本注释
7.2.7 视觉结构:块与缩进
7.2.8 表达式、函数以及方法的长度
7.2.9 控制结构
7.2.10 布尔表达式
7.2.11 可辨认性与内聚性
7.2.12 依赖和耦合
7.2.13 代码块注释
7.2.14 数据声明注释
7.2.15 恰当的标识符名字
7.2.16 依赖的位置
7.2.17 不确定性
7.2.18 可复查性
7.3 可变性
7.3.1 识别
7.3.2 分离
7.4 稳定性
7.4.1 封装与数据隐藏
7.4.2 数据抽象
7.4.3 类型检查
7.4.4 编译时断言
7.4.5 运行时检查和查看时断言
7.5 可测试性
7.5.1 单元测试
7.5.2 集成测试
7.5.3 系统测试
7.5.4 测试覆盖度分析
7.5.5 偶发性测试
7.6 开发环境的影响
7.6.1 增量构建
7.6.2 调整构建性能
第8章 浮点运算
8.1 浮点数表示
8.1.1 量度误差
8.1.2 舍入
8.1.3 内存格式
8.1.4 规格化和隐含的一位
8.1.5 阶码偏移
8.1.6 负数
8.1.7 反向规格化数
8.1.8 特殊值
8.2 舍入
8.3 溢出
8.4 下溢
8.5 消去
8.6 合并
8.7 无效运算
附录A 源代码致谢人员名单
参考文献
表 目 录
表2-1 测试极端情况
表2-2 测试一个不含尾端的非对称范围的例子
表2-3 整数量的范围
表2-4 在程序生命周期不同阶段所做的参数类型检查
表2-5 在C++中约束类的使用
表3-1 UNIX服务器开放网络端口列表
表3-2 Windows工作站开放网络端口列表
表3-3 进行ftpd缓冲区攻击时的栈
表3-4 展开栈(默认情况)
表3-5 在攻击过程中展开栈
表3-6 不安全的C函数及其安全的替代函数
表3-7 Java 2平台SE 5.0的许可
表4-1 用时剖析特征、诊断工具及解决方案
表4-2 由环境切换和进程间通信导致的开销
表4-3 低速外设导致的开销
表5-1 不同架构下基本数据类型的表示
表5-2 AMD64架构上结构体元素的对齐
表5-3 一个程序在不同架构和操作系统上的内存布局
表5-4 连续的地址空间限制及相应的解决方案
表5-5 构建选项对程序大小的影响
表6-1 各种开发平台的可移植性问题
表6-2 Java平台标准字符编码
表6-3 区域特定的字段
表7-1 可维护性指数的参数
表7-2 WebServerConnection方法与它们使用的字段
表7-3 WebServerConnection类的相似(内聚)方法与相异方法
表7-4 不同类型的访问控制下可以访问类成员的方法数
表8-1 不同舍入模型的例子
表8-2 不同浮点格式的关键属性
表8-3 导致异常的运算和操作数
图 目 录
图1-1 软件质量的各个方面的例子:使用中质量、
外部质量、内部质量及过程质量
图1-2 本书脉络:软件质量的要素
图1-3 质量特征间的冲突
图1-4 标注列表示例
图1-5 基于UML的图示符号
图2-1 使用评注,toString方法的反射式实现
图2-2 借助策略模式关联代码和数据
图2-3 使用接口实现创建处理器
图2-4 对象私有资源的显式管理
图2-5 邮件传送代理守护程序sendmail的调试代码
图2-6 通过静态分析探查null指针引用
图2-7 借助wait和notify管理资源的使用
图2-8 使用有瑕疵的双检锁模式
图2-9 内存泄漏与资源泄漏之间的关系
图2-10 在NetBSD内核中分配与释放文件描述符
图2-11 使用自动产生的源代码定义字体的轮廓
图2-12 NetBSD源代码中全局变量定义(左)和引用(右)的位置
图2-13 NetBSD内核全局变量所用的类型
图2-14 将字节串编码为改进过的UTF-8格式
图2-15 SCSI设备驱动程序中一个命令序列重传
图2-16 自有故障的磁盘上恢复数据
图3-1 FTP守护进程中的缓冲区溢出
图3-2 PPP守护代码中的一个竞态条件
图3-3 pppd漏洞的检查/使用时间差利用
图3-4 检查/使用时间差漏洞利用时序图
图3-5 strcpy和strcat的不安全用法
图3-6 strcpy和strcat正确应用在一个动态分配大小的缓冲区上
图3-7 不安全地清除环境变量
图3-8 安全地清除环境变量
图3-9 未正确检查traceroute实现中的错误返回值
图3-10 在TCP Wrappers程序中嵌入特洛伊木马代码
图4-1 专家对于优化代码的警告
图4-2 在HSQLDB代码中EJP对帕累托法则的阐述
图4-3 对于vfprintf函数的gprof输出的例子
图4-4 调用图中处理时间的传播
图4-5 某些常见算法类别的相对性能
图4-6 简单cat调用中的系统调用
图4-7 logger调用时本地进程间通信产生的系统调用
图4-8 ping名字查询的远程DNS进程间通信所产生的系统调用
图4-9 系统颠簸对运行时性能的影响
图4-10 使用用户ID来命名缓存代码
图4-11 缓存数据库行记录
图5-1 结构体的两种存储方式:填充以确保对齐(上),打包以节省内存(下)
图5-2 从大到小排列结构体元素,确保对齐且节省内存
图5-3 OpenCL算法继承树的UML类图
图5-4 三个OpenCL算法类的C++虚函数表
图5-5 指向实例数据的Java对象
图5-6 有着一个指向实例数据和类数据的句柄的Java对象
图5-7 内存资源的类型
图5-8 进程内存组织
图5-9 现代计算机的一个存储层次结构
图5-10 100万个分配对象的大小分布
图5-11 100万个分配对象的生命周期分布
图5-12 用于显示内存碎片的内存池快照
图5-13 外部内存碎片的一个例子
图5-14 内部内存碎片的一个例子
图5-15 Apache HTTP服务器内存分配剖析
图5-16 sed流编辑器的内存剖析
图5-17 valgrind内存泄漏测试工具的报告
图5-18 C正则表达式库中的内存泄漏
图5-20 一个栈帧的内容
图5-21 栈大小的快照
图5-22 数据和栈大小的关系
图5-23 源文件与目标文件大小之间的关系
图5-24 ACE地址类型中的继承
图6-1 使用隔离层来提供可移植性
图6-2 存储于小端与大端架构上的整数0x04030201
图6-3 GUI可移植性策略的例子
图6-4 使用catgets接口做消息处理
图6-5 使用gettext接口做消息处理
图6-6 使用GNU gettext工具的消息本地化流程
图6-7 在Java servlet中访问本地化消息
图7-1 测量扩展圈复杂度
图7-2 FreeBSD内核和用户程序的增长与可维护性指标随时间的变化
图7-3 所有FreeBSD模块的可维护性指数分布
图7-4 类的加权方法数度量:对所有的HSQLDB类(左);
不同的WMC值对应的Eclipse类个数(右)
图7-5 继承树深度度量:对于所有的HSQLDB类(左);
不同DIT值对应的Eclipse类的数量(右)
图7-6 HSQLDB:高DIT值的类的继承树度量和它们所定义的方法数
图7-7 Eclipse类的子类数度量
图7-8 对象类之间的耦合:对于每个HSQLDB类(左);
不同的CBO值对应的Eclipse类的数量(右)
图7-9 类的响应:对于所有的HSQLDB类(左);
不同的CBO值对应的Eclipse类的数量(右)
图7-10 方法的内聚缺乏度:对于所有的HSQLDB类(左);
对应于不同LCOM值的Eclipse类的个数(右)
图7-11 org.hsqldb包中的公有类和私有类
图7-12 Tomcat中一个不稳定的包
图7-13 Eclipse中一个稳定的包
图7-14 Eclipse的离心耦合与向心耦合之间的关系
图7-15 Eclipse包(左)和第三方包(右)的不稳定性分布
图7-16 junit包的稳定依赖
图7-17 MX4J包的不太稳定依赖
图7-18 Eclipse包的不稳定性与抽象度分布
图7-19 Xerces与Eclipse间的循环依赖
图7-20 所有的FreeBSD模块可维护性指数与模块大小的关系
图7-21 65000个C函数的函数长度分布
图7-22 在处理用户响应的过程中缺乏规则性
图7-23 用于处理用户响应的一个规则的控制结构
图7-24 在同一代码段里不同的break和continue范围
图7-25 ed的DES CBC实现中的公共耦合
图7-26 ed的DES CBC实现中的公共耦合关系
图7-27 在NetBSD内核中读取并使用磁盘分区内核
图7-28 低带宽X(LBX)扩展中增量缓存的设计
图7-29 低带宽X(LBX)扩展中增量缓存的实现
图7-30 servlet容器各元素间不必要的关系
图7-31 使用责任链设计模式来分离类
图7-32 两个不同的Catalina文件的公共代码行
图7-33 难以修改的格式化注释(左)与便于修改的格式化注释(右)
图7-34 在最内部的代码块中声明变量
图7-35 第7版UNIX中直接解释目录的数据
图7-36 Java 1.5之前的代码使用松散类型
图7-37 C库fomd实现中的特别单元测试
图7-38 JUnit测试框架中的单元测试
图7-39 Perl源代码测试覆盖度(左)和分支覆盖度(右)与测试用例执行数的关系
图7-40 正则表达式引擎中断言的使用
图7-41 包含文件依赖关系的简化图
图7-42 文档依赖
图8-1 二次方程消去误差以及对精度的影响
图8-2 计算远离原点的三角形面积时的合并误差
图8-3 验证浮点运算结果的代码
^ 收 起
季奥米季斯·斯宾耐立思(Diomidis Spinellis),自1985年开始,在开发大量开创性的,并受到极高评价的商业和开源项目的过程中,一直在钻研、发展本书中所提及的各项技术,期间他编写和维护的代码行数超过25万行。他在英国伦敦帝国理工学院获得了软件工程方向的硕士学位及计算机科学博士学位。目前,他是希腊雅典经济与商业大学管理科学与技术系的教授。他曾撰写过多部畅销世界的计算机技术图书,包括《架构之美》、《代码质量》和《代码阅读》等。
左飞,技术作家、译者,著有《代码揭秘》、《数字图像处理原理与实践:基于VisualC++开发》、《大话TD-SCDMA》等书。2011年在国家示范软件学院成立10周年庆祝大会上,他被授予“全国十佳毕业生”荣称,以表彰其在专业领域所做出的突出成绩。
吴跃,国家公务员,开源软件爱好者。他在信息安全方面有丰富的实践经验。他长期同本书原作者保持密切的往来,深得Spinellis教授之意。除了本书之外,他还翻译了作者的另外一部著作《代码阅读》。
^ 收 起
左飞,技术作家、译者,著有《代码揭秘》、《数字图像处理原理与实践:基于VisualC++开发》、《大话TD-SCDMA》等书。2011年在国家示范软件学院成立10周年庆祝大会上,他被授予“全国十佳毕业生”荣称,以表彰其在专业领域所做出的突出成绩。
吴跃,国家公务员,开源软件爱好者。他在信息安全方面有丰富的实践经验。他长期同本书原作者保持密切的往来,深得Spinellis教授之意。除了本书之外,他还翻译了作者的另外一部著作《代码阅读》。
^ 收 起
Jolt大奖素有"软件业之奥斯卡"的美称,本丛书精选自Jolt历届获奖图书,以植根于开发实践中的独到工程思想与杰出方法论为主要甄选方向。Diomidis Spinellis首部著作《代码阅读》(Code Reading)旨在阐明程序员应如何理解与修改代码,与此不同的是,《代码质量》重点讨论代码的非功能特性,深入讲述代码如何满足重要的非功能性需求,如可靠性、安全性、可移植性和可维护性,以及时间效率和空间效率。本书从Apache Web应用服务器、BSD UNIX操作系统和HSQLDB Java数据库等开源项目中攫取数百个小例子,并以实例为基准点,辅以理论分析,从实用的角度讲述每个专业软件开发人员能立即运用的概念和技术。
《代码质量》荣获2007年Jolt大奖,适用于不同知识层次的软件工作、程序开发和研究人员。
《代码质量》荣获2007年Jolt大奖,适用于不同知识层次的软件工作、程序开发和研究人员。
比价列表
1人想要1人拥有
公众号、微信群
缺书网
微信公众号
微信公众号
扫码进群
实时获取购书优惠
实时获取购书优惠