《代码大全第二版》学习笔记(四)

来源:互联网 发布:php get 编辑:程序博客网 时间:2024/06/01 10:01

第六部分 系统考虑

第二十七章 程序规模对构建的影响

如果你习惯于开发小项目,那么你的第一个中大型项目有可能严重失控,它不会像你憧憬的那样成功,而会变成一头无法控制的野兽本章将告诉你会遇到些什么野兽,以及到哪里去找鞭子和铁链来驯服它。

27.1 交流和规模

人多时,改善交流效率的常用方法是采用正式的文档。

27.3 项目规模对错误的影响

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

放大轻量级的方法论要好于缩小重量级的方法论。最有效的办法是使用“适量级”方法论。

第二十八章 管理构建

28.6 管理你的管理者

第二十九章 集成

集成:将一些独立的软件组件组合为一个完整系统。

29.2 集成频率——阶段式集成还是增量集成

阶段式集成(大爆炸集成)

1.      设计、编码、测试、调试各个类。这一步称为单元开发

2.      将这些类组合为一个庞大的系统(系统集成/system integration”)。

3.      测试并调试整个系统。这称为系统瓦解/system dis-integration”

问题:出现问题的位置的不确定性 + 所有问题都是一下子出现。

增量集成Incremental Integration

一小块一小块地编写并测试你的程序,然后一次一块地将它拼凑起来。

1.      开发一个小的系统功能部件。可能是最小的功能部件、最难的部件、关键部件、或者以上的某种组合。对它彻底地测试并调试。将它作为骨架,稍后附着肌肉、神经、皮肤等系统的其余部件。

2.      设计、编码、测试、调试某个类。

3.      将这个新的类集成到系统骨架上。测试并调试骨架和新类的结合体。在进一步添加任何新类之前,确保该结合体能工作。如果做完了剩余的所有工作,回到步骤2重复这一过程。

29.3 增量集成的策略

三明治集成

纯粹的自顶向下或自底向上都有很多问题。于是:

首先集成继承体系顶部的高层业务对象(business-object)类。然后集成底部的鱼设备接口的类和广泛使用的工具类。

稍后开始集成中间层的类。

先集成通常比较棘手的类,而且具有能让项目所需的脚手架数目最少这一潜在优势。

推荐:风险导向的集成

困难部件优先集成法。

首先鉴别各个类对应的风险级别。确定哪些部件实现起来是最有挑战的,然后先实现这些部件。

经验表明顶层的接口是有风险的,因此它通常位于风险清单的顶部。系统接口,通常位于继承体系的底层,也是有风险的,因此它也在风险清单的顶部。中间层或许有些类,实现了未被透彻理解的算法,或者具有雄心勃勃的性能目标,也应及早集成。

功能导向的集成

一次集成一项功能。feature特征,系统中一项可确认的功能。

通常首先需要搭好一个骨架,选择骨架的标准是它能支撑其他功能。在交互式系统中,首要的功能多半是交互式的菜单系统。你可以把其他功能挂在这个首先集成的功能上。

三个优点:

1.      基本不用脚手架(底层的程序库类除外)。把各个功能挂在骨架上之后,就无需脚手架了。

2.      每个新集成的功能都增加了系统的功能性。证明了项目正在坚定不移地前进

3.      功能导向的集成与面向对象设计能很好地协同工作。对象通常能很好地映射为功能。

T型集成

选中某个特定的“竖直块”,对它及早开发并集成。这个功能块应当能从头到尾地演练系统,而且这个演练过程应该能找出系统设计所做的假设中的全部主要问题。一旦实现了这个“竖直块”——并纠正了所有相关问题——那么就可以开发系统的挑大梁部件(例如桌面应用程序中的菜单系统)。常与风险导向的集成或功能导向的集成结合使用。

29.4 Daily Build与冒烟测试

1.         每日构建。

2.         检查失败的build

3.         每天进行冒烟测试。

4.         让冒烟测试与时俱进。

5.         daily build和冒烟测试自动化。

6.         成立build小组。

7.         仅当有意义时,才将revisions加入build中。

8.         但是别等太久才将修订加入进来。

9.         要求开发人员在把他的代码添加到系统之前,进行冒烟测试。

10.     为即将添加到build的代码准备一块暂存区。

11.     惩罚破坏build的人。

12.     在早上发布build

13.     即使有压力,也要进行daily build和冒烟测试。

第三十章 编程工具

30.1 设计工具

能创建设计图表的图形化工具。

30.2 源代码工具

编辑

1.         集成开发环境IDE

2.         针对多个文件的字符串查找和替换。

3.         diff工具。比较两个文件。

4.         Merge工具。多人同时对文件进行修改,并在check-in时将这些改动合并merge到一起。

5.         源代码美化器。格式。

6.         生成接口文档的工具。从源代码中提取详细的接口文档。

7.         模板。VA

8.         交叉引用工具。列出所有的变量和子程序,以及使用这些变量和子程序的所有位置——通常放在Web页面上。

9.         类的继承体系生成器。

分析代码质量

本类工具对源代码进行静态检查,评定其质量。

1.         吹毛求疵的语法/语义检查器。如Lint,会提醒:未初始化的变量、完全没有用到的变量、赋了值却没有用过的变量、没有对子程序的传出参数赋值、可疑的指针运算、可疑的逻辑比较、不可达的代码等等。

2.         尺度报告器Metrics Reporters。如统计代码行、数据声明行、注释行、空行的行数。

重构源代码

帮你把源代码从一种格式转换为另一种格式。

1.         重构器Refactorers。改变类名、添加子程序等。

2.         结构改组工具Restructurers

3.         代码翻译器Code Translators。从一种语言翻译为另一种语言。

Version Control

使用版本控制工具进行:

1.         源代码控制。

2.         依赖关系控制,类似UNIX下提供的make工具。

3.         项目文档的版本管理。

4.         将项目的工件artifacts(如需求、代码、测试用例等)关联到一起,这样当发生需求变更时,能找出受影响的代码和test cases

数据字典

描述项目中所有重要数据的数据库。

30.3 可执行码工具

产生目标码

1.         编译器与链接器。

2.         Build工具。

3.         程序库。不要全部自己编写,而去找一个开源的版本。

4.         代码生成向导。

5.         安装。

6.         预处理器。

调试

下列工具有助于程序调试:

1.         编译器的警告信息。

2.         测试用的脚手架。

3.         Diff工具。

4.         执行剖测器。

5.         追踪监视器。

6.         交互式调试器——软件版和硬件版。

测试

下列功能特性和工具有助于你进行有效的测试:

1.         自动测试框架,如JUnit/NUnit/CppUnit等。

2.         自动化的测试生成器。

3.         测试用例的记录和回放工具。

4.         覆盖率监视器(逻辑分析器和执行剖测器)。

5.         符号调试器。

6.         系统扰动器(内存填充工具、内存“抖动”工具、选择性的内存失效的工具、内存访问检查器)。

7.         Diff工具(比较数据文件、截获的输出、屏幕图像等)。

8.         脚手架。

9.         缺陷注入工具。

10.     缺陷跟踪软件。

代码调整

1.         执行剖测器Execution Profilers。观察运行中的代码,并报告每条语句执行了多少次,或者程序在每条语句(或每条执行路径)上花费了多少时间。

2.         汇编代码清单和反汇编。

30.4 工具导向的环境

UNIXC++配合。

30.5 打造你自己的编程工具

1.         项目特有的工具。

2.         脚本。

30.6 工具幻境

即便有很好的工具,也不可能完全消除对编程的需要。

第七部分软件工艺

第三十一章 布局与风格

31.1 基本原则

格式化的基本原理:好的布局凸显程序的逻辑结构。

良好布局的目标:

1.         准确表现代码的逻辑结构。

2.         始终如一地表现代码的逻辑结构。

3.         改善可读性。

4.         经得起修改。

第三十二章 自说明代码

32.1 外部文档

1.         单元开发文件夹UDF。提供在其他地方没有说明的设计决策踪迹,比如相关需求的复本、某个单元实现的顶层设计的组成部分、开发标准的复本、当前代码清单、单元开发者的设计记录。

2.         详细设计文档。描述在类层或子程序层的设计决定,曾考虑过得其他方案,以及采用所选方案的理由。

32.2 编程风格作文档

32.4 高效注释之关键

对于完工的代码,只允许有的三种注释类型:代码无法表述的信息、目的性注释、概述性注释。

高效注释

写注释所占用的时间其实都用在了更好地理解程序上面。

1.         采用不会打断或抑制修改的注释风格。不要跟画画一样弄那么花哨的装饰啊对齐啊。

2.         用伪代码编程法减少注释时间。

3.         将注释集成到你的开发风格中。

4.         性能不是逃避注释的好借口。

最佳注释量:约每十条语句有一个注释。

32.5 注释技术

注释单行

1.         不要随意添加无关注释。

2.         不要对单行代码做行尾注释。

3.         不要对多行代码做行尾注释。

4.         行尾注释只用于三种情况:行尾注释用于数据声明;用行尾注释标记块尾。

注释代码段

1.         注释应表达代码意图。

2.         代码本身应尽力做好说明。

3.         注释代码段时应注重“为何做why”而不是“怎么做how”。

4.         用注释为后面的内容做铺垫。

5.         让每个注释都有用。

6.         说明非常规做法。

7.         别用缩略语。

8.         将主次注释区分开。

9.         错误或语言环境独特点都要加注释。

10.     给出违背良好编程风格的理由。

11.     不要注释投机取巧的代码,应重写之。

注释数据声明

1.         注释数值单位。

2.         对数值的允许范围给出注释。

3.         注释编码含义。

4.         注释对输入数据的限制。

5.         注释“位标志”。

6.         将与变量有关的注释通过变量名关联起来。

7.         注释全局数据。

注释控制结构

1.         应在每个ifcase、循环或者代码段前面加上注释。

2.         应在每个控制结构后加上注释。//if

3.         将循环结束处的注释看成是代码太复杂的征兆。

注释子程序

1.         注释应靠近其说明的代码。不应当有庞大的注释头。

2.         在子程序上部用一两句话说明之。

3.         在声明参数处注释这些参数。

4.         利用诸如Javadoc之类的代码说明工具。

5.         分清输入和输出数据。

6.         注释接口假设。

7.         对子程序的局限性作注释。

8.         说明子程序的全局效果。

9.         记录所用算法的来源。

10.     用注释标记程序的各部分。

注释类、文件和程序

标注类的一般原则

1.         说明该类的设计方法。

2.         说明局限性、用法假设等。

3.         注释类接口。

4.         不要在类接口处说明实现细节。

注释文件的一般原则

1.         说明各文件的意图和内容。

2.         将姓名、电子邮件及电话号码放到注释块中。

3.         包含版本控制标记。

4.         请在注释块中包含法律通告。

5.         将文件命名为与其内容相关的名字。

要点

第三十三章 个人性格

33.2 聪明和谦虚

1.         将系统分解,是为了使之易于理解。

2.         进行审查、评审和测试正是为了减少人为失误。

3.         将子程序编写得短小,以减轻大脑负荷。

4.         基于问题而不是低层实现细节来编程,从而减少工作量。

5.         通过各种各样的规范,将思路从相对繁琐的编程事务中解放出来。

33.3 求知欲

1.         在开发过程中建立自我意识。越了解软件开发过程,无论通过阅读还是通过自己对软件开发的观察,就越能理解变化,使团队朝着正确的方向发展。

2.         试验。小程序。

3.         阅读解决问题的有关方法。

4.         在行动之前做分析和计划。

5.         学习成功项目的开发经验。研究高手的程序。

6.         阅读文档。

7.         阅读其他书本期刊。

8.         同专业人士交往。

9.         向专业开发看齐。专业开发阶梯。

a)         入门级:会利用某语言的基本功能,能够编写类、子程序、循环和条件语句,会使用语言的许多特性。

b)         中级:利用多种语言的基本功能,并会得心应手地使用至少一种语言。

c)         熟练级:对语言或环境有着专业技能。

d)         技术带头人员:有第三级的才学,并明白如何与人打交道。为人写代码,而非为机器,可读性。

33.4 诚实

1.         不是高手时不假装是高手。

2.         乐于承认错误。

3.         力图理解编译器的警告,而非弃之不理。

4.         透彻理解自己的程序,而不是只是编译看看能否运行。

5.         提供实际的状况报告。

6.         提供现实的进度方案,在上司面前坚持自己的意见。

33.5 交流与合作

首先是与人交流,其次才是与计算机交流。可读性。

33.6 创造力和纪律

编程前主义分析需求和设计。

33.7 懒惰

懒惰表现在:

1.         拖延不喜欢的任务。×

2.         迅速做完不喜欢的任务,以摆脱之。—

3.         编写某个工具来完成不喜欢的任务,以便再也不用做这样的事情了。√

33.8 不如你想象中那样起作用的性格因素

1.         坚持。根据环境的不同,可能是财富,可能是负担。和计算机错误斗气是不明智的,更好的方法是避开它们。知道何时放弃很难,但这是必须面对的问题。“要是这种方法三十分钟之内还不解决问题,我就会花十分钟想些其他办法,再用一个钟头尝试最可行的办法。”

2.         经验。只有坚持不懈地学习,才能获取经验。如果不这样做,就得不到经验,无论工作多少年。

3.         编程狂人。热情不能代替熟练的能力,想明白什么更重要。

33.9 习惯

新习惯代替旧的坏习惯。

第三十四章 软件工艺的话题

34.1 征服复杂性

1.         在架构层将系统划分为多个子系统,以便让思绪在某段时间内能专注与系统的一小部分。

2.         仔细定义类接口,从而可以忽略类内部的工作机理。

3.         保持类接口的抽象性,从而不必记住不必要的细节。

4.         避免全局变量。

5.         避免深层次继承。深层次嵌套的任何东西。

6.         不要滥用不同的错误处理技术。

7.         不要让类过度膨胀。

8.         子程序应保持短小。

9.         命名清晰。

10.     参数尽量少。

11.     规范约定减少随意性偶然性。

34.2 精选开发过程

注重抽象与高层。

34.3 首先为人写程序,其次才是为机器

可读性。

34.4 深入一门语言去编程,不浮于表面

不要将编程思路局限到所用语言能自动支持的范围。杰出的程序员会考虑他们要干什么,然后才是怎样用手头的工具去实现他们的目标。

34.5 借助规范集中注意力

传达重要信息,免除各种风险,增加对低层工作的可预见性,弥补语言不足之处。

34.6 基于问题域编程

尽可能工作于最高的抽象层次。针对编程所要解决的问题来工作,而非针对计算机科学的解决方案。

将程序划分为不同层次的抽象:

1.         操作系统的操作和机器指令。

2.         编程语言结构和工具。

3.         低层实现结构。算法和数据结构。

4.         低层问题域。业务对象层或服务层。

5.         高层问题域。

34.7 当心落石

编程是一门手艺craft。关注警告。

34.8 迭代,反反复复,一次又一次

在早期开发阶段的迭代过程中,需要快速地构建尽量多的东西,之后丢弃之也不会花费多大代价。

34.9 汝当分离软件与信仰

“试图没有错误”是最大的错误。应保持开放的心态。

第三十五章 何处有更多信息

35.1 关于软件构建的信息

35.2 构建之外的话题

综述资料

软件工程综述

其他注释过的参考书目

35.4 软件开发者的阅读计划

入门级

熟练级

专业级

35.5 参加专业组织

IEEE计算机社区     www.conputer.org

美国计算机协会     www.acm.org

原创粉丝点击