代码大全(Code Complete)第二版读书笔记

通过阅读此书,理清了很多概念,学习到不少最佳实践。作者指出的很多问题,我都有切实的亲身经历,不仅如此,作者还提供了解决这些问题的方法,对于很多程序员来说,都是非常宝贵的,可以少走很多弯路。

我认为如果初学者来看这本书,因为编程经验比较少,可能体会不是太深。最好还是有些经验了再看,相当于作者已经帮你把你经常遇到的问题给总结罗列好了。

本书的目的:

如何编写高质量的代码,如何构建高质量的软件,如何成为一个优秀的程序员
为什么要写这本手册:在软件工程界,人们都清楚地认识到,应该把软件开发中行之有效的实践知识归纳、编撰成一本开发手册。

什么是构建:

建设的过程,也就是创建事物过程中动手的那些部分。
编码有一种“把已经存在的设计机械化地翻译成计算机语言”的意味。

第一部分 打好基础

第一章 欢迎进入软件构建的世界

“构建”是指建设的过程。就是创建事物过程中动手的那些部分。

1.1 什么是软件构建

软件开发过程中包含很多的活动:
定义问题
需求分析
规划建设
软件架构
详细设计
编码与调试
单元测试
集成测试
集成
系统测试
保障维护

“编码”有一种“把已经存在的设计机械化的翻译成计算机语言”的意味。而构建并不都是这么机械化的,需要客观的创造力和判断力。
本书大致包含规划建设、软件架构、详细设计、编码与调试、单元测试、集成测试和集成等活动。

1.2 软件构建为何如此重要

构建活动是软件开发的主要组成部分。
构建活动是软件开发中的核心活动。
把主要精力集中于构建活动,可以大大提高程序员的生产率。
构建活动的产物——源代码——往往是对软件的唯一精准描述。
构建活动是唯一一项确保会完成的工作。

第2章 用隐喻来更充分的理解软件开发

2.1 隐喻的重要性
2.2 如何使用软件隐喻
对于编程来说,最大的挑战还是将问题概念化。
2.3 常见的软件隐喻

1.3 如何阅读本书
第20章 软件质量概述

20.1 软件质量的特性
软件同时拥有外在的和内在的质量特性。
外在特性指的是该产品的用户所能感受到的部分,包括以下内容:
正确性
可用性
效率
可靠性
完整性
适应性
精准性
健壮性
内在特性包括以下内容:
可维护性
灵活性
可移植性
可重用性
可读性
可测试性
可理解性
20.2 改善软件质量的技术
改善软件质量的一种强有力的方法,就是根据前面章节所提到的各种内在特性和外在特性,明确定义出软件质量的目标。
将测试作为质量评估和质量改善的首要方法,这样的想法将使得测试不堪重负。
非正式技术复查,正式技术复查,外部审查
在开发过程中:
对变更进行控制
结果的量化
制作原型
程序员有很高的成就激励:他们会向明确的目标进发,但必须有人告诉他们目标是什么。不同目标之间是有冲突的,并且软件通常都不可能在所有方面都做得很好,这也符合我们的预期。
20.3 不同质量保障技术的相对效能
检查比测试的效率高,成本低很多。
质量保障技术推荐:
对所有需求、系统关键部分的设计以及架构进行正式检查
建模或者创建原型
代码阅读或者检查
执行测试
20.4 什么时候进行质量保证工作
在项目的早起阶段就开始强调质量保证工作,并且将其贯彻到项目的余下部分中。
20.5 软件质量的普遍原理
改善质量以降低开发成本
哪些花费时间不多不少的程序员编写的程序错误最多,而那些花费时间较多或较少的程序员编写的程序所含错误要明显少得多。

第21章 协同构建

21.1 协同开发实践概要
”协同构建“包括结对编程、正式检查、非正式技术复查和文档阅读等。协同构建是其他质量保证技术的补充,首要目的就是改善软件的质量。
Karl Wiegers指出:由人进行的复查能够发现不明显的错误信息、不恰当的注释、硬编码的变量值,以及重复出现的需要进行统一的代码模式,这些是测试发现不了的。
21.2 结对编程
什么是结对编程
成功运用结对编程的关键
结对编程的好处
21.3 正式检查
非常详细的介绍了如何进行正式检查,应该组织多少人员,每个人员的角色,会议的准备,开会时间,如何开会等等
21.4 其他类型的协同开发实践
走查,一种非常不值得推荐的检查方式。
还有代码阅读,公开演示等…

第22章 开发者测试

测试包括单元测试,组件测试,集成测试,回归测试,系统测试
黑盒测试指的是测试者无法了解测试对象内部工作机制的测试。
白盒测试指的是测试者清楚待测试对象内部工作机制的测试。
22.1 开发者测试在软件质量中的角色
对于任何软件质量规划来说,测试都是一个重要的组成部分,并且在许多情况下它是唯一的组成部分。
22.2 开发者测试的推荐方法
测试先行还是测试后行根据情况而定。应该先写测试用例
开发者测试的局限性:

  • 开发者测试倾向于”干净测试“,即开发人员往往去做一些检查代码能否正常工作的测试(干净测试,clean tests),而不是做所有可能让代码失效的测试(肮脏测试 dirty tests)。
  • 开发者测试对覆盖率有过于乐观的估计。
  • 开发者测试往往会忽略一些更复杂的测试覆盖率类型。
    22.3 测试技巧锦囊
  • 不完整的测试
    集中注意力挑选出那些能告诉你不同答案的测试用例,而不选出一堆总是告诉你相同答案的测试用例。
  • 机构化的基础测试
    需要测试程序中的每条语句至少一次。
    22.4 典型错误
    绝大多数错误往往与少数几个具有严重缺陷的子程序有关。
    错误的分类…
    大多数错误的影响相当有限
    许多错误发生在构建的范畴之外
    大多数的构建期错误是编程人员的失误造成的
    让你惊奇的是,笔误(拼写错误)是一个常见的问题根源
    错误理解设计这条会经常出现
    大多数错误都很容易修正
    测试本身的错误
    22.5 测试支持工具
    22.6 改善测试过程
    22.7 保留测试记录
第23章 调试

调试是确定错误根本原因并纠正此错误的过程。同测试不同,后者是检查错误的过程。
遇到的绝大多数问题都是一些微小的疏忽和拼写错误,这些很容易通过阅读源代码或在调试器中单步跟踪来发现。

调式概念

介绍了一些效率低下的调试方法。

寻找缺陷

科学的调试方法
寻找缺陷的一些小建议

修正缺陷

调试过程中最让人头疼的部分是寻找缺陷。修正缺陷则是较为简单的部分。正式因为它太过简单才让人们经常对它掉以轻心。调查发现程序员第一次对缺陷进行修正的时候,有超过50%的几率出错。下面给出一些如何减少出错几率的建议。

调试中的心里因素

调试是一种要求程序员花费大量脑力的工作。就算是已经看到了一个缺陷,你的自负还是会让你觉得自己的代码完美无缺。
接下来作者指出了几种心里因素并提供了一些改善的方式。

调试工具——明显的和不那么明显的
第24章 重构
软件演化的类型
重构简介

定义:在不改变软件外部行为的前提下,对其内部结构进行改变,使之更容易理解并便于修改。
有时,代码在维护过程中质量会降低,而有时代码在最初诞生的时候就先天不良,则就意味着程序需要重构。
重构的理由:

  • 代码重复
  • 冗长的子程序
  • 循环过长或嵌套过深
特定的重构

数据级的重构
语句级的重构
子程序级的重构
类实现的重构
类接口的重构
系统级的重构

安全的重构

如果使用不当,重构给你带来的麻烦会比它所带来的好处还多。下面一些简短的建议能够让你避免错误的使用重构。

重构策略

讲了在什么时候进行重构。

第25章 代码调整策略
性能概述

有时候需要考虑到底是应该更关注性能还是代码的质量,可读性和可维护行。

代码调整简介

介绍代码调整的几个误区和何时调整代码。
“行数越少程序就越快”的教条是错误的。

蜜糖和哥斯拉

常见的低效率之源。

性能测量

通过测试找出最耗性能的代码。

反复调整
代码调整方法总结
第26章 代码调整技术
逻辑

短路与及等价转换等一大堆可以优化的点。

循环

将判断外提,合并等

数据变换

尽可能使用整形而不是浮点数。
数据维度尽可能少。

表达式

使用代数恒等式,举个例子:
如果要判断sqrt(x) < sqrt(y),可以使用x<y来判断,这样可以节省90%以上的时间。

子程序

短小,定义明确的子程序能够代替多处单独执行相同操作的代码,因而能够节省空间。这些子程序也使得优化更为简单,因为重构某子程序的代码就可以惠及各处。

用低级语言重写代码
变得越多,事情反而越没变

第6部分 系统考虑

第27章 程序规模对构建的影响

如果你习惯于开发小项目,那么你的第一个中大型项目有可能严重失控。如果你习惯于开发大型项目,那么你所用的方法可能对小项目来说太正规了。

交流和规模

交流路径的条数大致正比于人数的平方。当项目中的程序员的数量超过50名,其潜在的交流路径就至少有1200条。
改善交流效率的常用方法是采用正式的文档。

项目规模的范围
项目规模对错误的影响

项目的规模也会影响错误的类型。
随着项目规模的扩大,错误的密度也就越来越大。

项目规模对生产率的影响

项目越大,生产率越低,人均代码行数越少。

项目规模对开发活动的影响

随着项目规模越来越大,构建所占的工作量成线性增加,而其他活动的工作量增长将超过线性。比如:交流,计划,管理,需求分析等等

第28章 管理构建
鼓励良好的编程实践
配置管理

配置管理的另一种说法是“变更控制”,其中的技术包括评估所提交的更改,追踪更改,保留系统在不同时间点的各历史版本。比如使用git或svn进行代码管理。

评估构建进度表

评估项目的规模和完成项目所需的工作量是软件项目管理中最具挑战性的方面之一。
评估的方法。
如果你落后了该怎么办?

  • 不要指望着自己能赶得上进度
  • 扩充团队
  • 缩减项目范围
    以上的几种方案都是我在实际的项目发现我的领导运用过的。
    度量
    从一种简单的度量数据开始,比如缺陷数量、工作月数、总费用以及代码总行数据开始。
    把程序员当人看
    不同程序员之间的生产效率有差异。
    不同团队之间的生产效率也有差异。
    最好的工作环境比最差的工作环境中的生产效率高出近1倍。
    管理你的管理者
    如何用有效的方式管理你的管理者。
    第29章 集成
    将一些独立的软件组件组合为一个完整系统。
    集成方式的重要性
    从周到的集成中,你能预期获得某些下列的益处。
    集成频率——阶段式集成还是增量集成
    什么是增量集成
    增量集成的益处:
  • 易于定位错误
  • 及早在项目里取得系统级的成果
  • 改善对进度的监控
  • 增量集成的策略
  • 自顶向下集成:
    首先编写并集成位于层次体系顶部的类。
  • 自底向上集成:
    首先编写并集成位于层次体系底部的类。

  • 不要像教条一样遵循前面提到的任何过程,它更多的是启发。
    Daily Build与冒烟测试
    Daily Build就是把整个项目每天打一个完整的包。如果项目的大小没有超过Microsoft Window 2000,那么就可以做到。
  • 冒烟测试的对象是每一个新编译的需要正式测试的软件版本,目的是确认软件基本功能正常,可以进行后续的正式测试工作。冒烟测试的执行者是版本编译人员。
  • 回归测试是指修改了旧代码后,重新进行测试以确认修改没有引入新的错误或导致其他代码产生错误。
    第30章 编程工具
    设计工具
    目前的设计工具主要就是那些能”能创建设计图表”的图形化工具。
    源代码工具
    介绍了通常IDE所具有的功能。
可执行工具
工具导向的环境
打造你自己的编程工具
工具幻境

第7部分 软件工艺

第31章 布局与风格
基本原则
布局技术
布局风格
控制结构的布局
单条语句的布局
注释的布局
子程序的布局
类的布局
第32章 自说明代码
外部文档
编程风格作文档
注释或不注释
高效注释之关键
注释技术
IEEE标准
第33章 个人性格
个人性格是否和本书话题无关
聪明与谦虚
求知欲
诚实
交流与合作
创造力和纪律
懒惰
不如你想象中那样起作用的性格因素
习惯
第34章 软件工艺话题
征服复杂性
精选开发过程
首先为人写程序,其次才是为机器
深入一门语言去编程,不浮与表面
借助规范集中注意力
基于问题域编程
当心落石
迭代,反反复复,一次又一次
汝当分离软件与信仰
第35章 何处有更多信息
关于软件构建的信息
构建之外的话题
期刊
软件开发者的阅读计划
参加专业组织