《代码大全》精粹

《代码大全》可谓关于软件构件最经典,最权威的参考书,书中详尽描述了软件构件过程中一切几乎需要注意的问题,是每个程序员都应具备的一本手册,但本书因为内容详尽,通俗易懂,不免厚些,查找起来比较费劲,所以将其中的精华内容总结出来,单独成文以便后续查找核对之用。

下面分章总结,每章一文,先看第一章。

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

1.1 什么是软件创建

软件开发周期:

     · 问题定义
     · 需求分析
     · 实现计划
     · 总体设计
     · 详细设计
     · 创建即实现
     · 系统集成
     · 单元测试
     · 系统测试
     · 校正性的维护
     · 功能强化

软件创建包括的内容:

    · 验证基础工作已经完成,可以进行创建工作
    · 设计和编写子程序与模块 
    · 创立数据类型并命名变量
    · 选择控制结构并组织语句块
    · 找出并修正错误
    · 评审其它小组的细节设计和代码,同时接受其它小组评审
    · 通过仔细地格式化和征集意见改进编码
    · 对分别完成的软件单元进行综合
    · 调整编码使其更小、更快

1.2 软件创建的重要性

    创建活动是开发软件的重要组成部分。(30%-80%)

    创建活动在软件开发中处于枢纽地位。

    把主要精力集中于创建活动,可以极大地提高程序员的生产效率。

    创建活动的产品,源代码,往往是软件的唯一精确描述。

    创建活动是唯一一项必不可少的工作。

l.3 小结

    · 创建活动是总体设计和系统测试之间承上启下的工作。
    · 创建活动主要包括:详细设计、编码、调试和单元测试。
    · 关于创建活动的其它称谓有:实现、编程等。
    · 创建活动质量对软件质量有潜在影响。
    · 在最后的分析中,对创建活动理解的好坏,决定了一个程序员素质的高低,这将在本书其余部分论述。

第二章 利用隐喻对编程进行更深刻的理解

2.1 隐喻的重要性

很多伟大的科学发现都是从类比开始的,类比就是将不熟悉的事物和我们熟悉的事物进行比较,找到他们之间的功能点,然后通过我们的比较解释不熟悉的事物,这种方法称之为“模型化”。

模型的力量在于能提供生动形象的概念而易于被人接受。

但模型有好有坏,好的模型应该要简单,与其他模型关系密切,能解释大部分试验现象和观测现象。

2.2 如何使用软件隐喻

软件隐喻是启发式的方法,并不是公式,并不会给你提供直接的解决方法,它只是给你提供方向,但是方向正确与否还需要自己摸索,所有对模型理解的好坏便决定了你对软件开发理解的好坏。

2.3 通常的软件隐喻

下面我们来看一看对软件构建有哪些隐喻:
2.3.l  软件书写:写代码(Writing Code )

对于小项目来说还说的过去,但对现在的大多数项目是不合适的。

2.3.2  软件播种:生成系统(Growing a System )

很牵强。

2.3.3  软件珍珠培植法:系统积累(System Accretion )

是一种对增量开发的隐喻。

2.3.4  软件创建:建造软件(building software )

比较贴切,因为建造建筑与开发软件的很多步骤是相似的。

2.3.5  实用软件技术:智能工具箱(The Intellectual Toolbox )

对我们所掌握的方法和技术的类比。

2.3.6  复合隐喻(Combing Metaphors )

2.4 小结

    ·隐喻仅仅是启发,而不是公式,因此,它们更倾向于比较随便,无拘无束。
    · 隐喻通过把软件开发与你所熟知的事情联系在一起,从而使你对其有更深刻的理解。
    · 一些隐喻要好于其它隐喻。
    · 把软件创建与建造建筑物类比,表明开发软件前要精心准备,并表明了大规模项目与小规模项目之间的差别。
    · 认为软件开发实践是智能工具箱中的工具进一步表明,每个程序员都有许多自己的工具,没有任何一种工具    是万能的。为每件工作选择合适的工具,是成为一个优秀程序员的首要素质之一。

第三章 软件创建的先决条件

3.1 先决条件重要性

任何只要是有步骤的事情,步骤之间就是有关系的,前面的步骤一定会对后面的步骤有或多或少的影响,软件开发也是一样。

问题定义影响需求分析,需求分析影响设计,设计影响编码。。。

一个高质量的程序员应该在创建过程的开始,中间和末尾都强调高质量。

3.2 问题定义先决条件

问题定义应该在需求分析之前进行。

问题定义应该从用户的角度进行,使用用户的语言进行定义,不应该使用计算机的术语来定义。因为有些问题用程序并不是最好的解决方法。

当然对于与计算机本身有关的问题就另当别论了,比如编程工具出问题。

3.3 需求分析先决条件

明确的需求可以保证是由用户而不是程序员决定系统的功能。

实际开发中,需求是不可能一成不变的,那么如何应对需求的变化呢:

    · 让每个人都知道由于变化需求所付出的代价

    · 建立一套更改控制过程

    · 用开发的方法来容纳变动(例如原型方法,渐进方法)

    · 放弃项目(不得已而为之)

书中还对需求分析是否成熟可靠提供了一份检查表,如下:

需求内容
   · 系统的所有输入都定义了吗?包括它们的来源、精度、取值范围和频率?
   · 系统所有的输出都定义了吗?包括它们的目标、精度、取值范围、频率和格式?
   · 所有的报告格式都定义了吗?
   · 所有的硬件与软件接口都定义了吗?
   · 所有的通信界面都定义了吗?包括握手、错误检查以及通信约定?
   · 是否从用户的观点出发,定义了所有必要操作的反应时间?
   · 是否定义了时间问题,如处理时间、数据传输率以及系统吞吐能力?
   · 是否对用户所要求完成的任务都作出了规定?
   · 每项任务所需用到和产生的数据都规定了吗?
   · 规定保密级别了吗?
   · 规定可靠性了吗?包括软件出错的后果、在出错时要保护的至关重要的信息、以及错误测试和恢复策略。
   · 规定所需最大内存了吗?
   · 所需最大存储容量规定了吗?
   · 对系统的维护性是否作出了规定?包括系统对运行环境、精度、性能以其与其它软件的接口等方面变化的适应能力规定了吗?
   · 是否规定了相互冲突的设计之间的折衷原则,例如,在坚固性与准确性之间如何进行折衷?
   · 是否制定了系统成败的标准?
 关于需求的完善性
   · 在开发开始前暂时得不到的信息是什么?是否规定了不够完善的区域?
   · 需求定义是否已经完善到了可以成为软件标准的地步?
   · 需求中是否有哪一部分令你感到不安?有没有根本不可能实现,而仅仅为了取悦老板和用户才加进来的内容?
关于需求的质量
   · 需求是否是用用户的语言制定的?用户也这样认为吗?
   · 需求中是否每一条之间都尽量避免冲突?
   · 需求中是否注意了避免规定设计工作?
   · 需求在详细程度方面是否保持了一致性;有没有应该更详细些的需求?有没有应该更简略些的?
   · 需求是否明确得可以分为一些独立的可执行部分,而每一部分又都很明了?
   · 是否每一条都与问题和答案相关?是否每一条都可以追溯到产生它的环境中?
   · 是否每一条需求都可以作为测试依据?是否可以针对每一条进行独立测试以确定是否满足需求?
   · 是否对可能的改动作出了规定?包括每一改动的可能性?

3.4 结构设计先决条件

3.4.1 典型的结构要素

    · 程序的组织形式

    · 变动策略

    · 购买而不是建造的决定

    · 主要的数据结构

    · 关键算法

    · 主要对象

    · 通用功能(用户界面,输入/输出,内存管理,字符串存储)

    · 错误处理
      错误处理很复杂,需要考虑如下问题:
          错误处理是纠正还是仅仅测试错误?
          错误测试是主动的还是被动的?
          程序是怎样对付错误的?
          处理错误信息的约定是什么呢
          在程序中,应该在哪一个层次上处理错误呢?
          每一个模块检验输入数据合法性的责任级别有多高?是每一模块仅检验它自己的数
         据,还是由一级模块来检验整个系统的数据?是否每个层次上的模块都可以假定输入其中的数据是合法的?

    · 坚固性
          裕度设计(over-engineering)
          断言(assertions)。
          容错性(fault tolerance)。

    · 性能(速度和内存)

3.4.2 检查表

    · 软件的总体组织形式是否清晰明了?包括对于结构设计的总体评论与描述。
    · 模块定义是否清楚?包括它们的功能及其与其它模块的接口。
    · 需求定义中所提出的所有功能,是否有恰当数量的模块覆盖?
    · 结构设计是否考虑了可能的更改?
    · 是否包括了必要的购买?
    · 是否阐明了如何改进重新启用的代码来满足现在的结构设计需求?
    · 是否描述并验证了所有主要的数据结构?
    · 主要数据结构是否隐含在存取子程序中?
    · 规定数据库组织形式和其它内容了吗?
    · 是否说明并验证所有关键算法?
    · 是否说明验证所有主要目标?
    · 说明处理用户输入的策略了吗?
    · 说明并验证处理输入/输出的策略了吗?
    · 是否定义了用户界面的关键方面?
    · 用户界面是否进行了模块化,以使对它所作的改动不会影响程序其它部分?
    · 是否描述并验证了内存使用估算和内存管理?
    · 是否对每一模块给出了存储空间和速度限制?
    · 是否说明了字符串处理策略?是否提供了对字符串占用空间的估计?
    · 所提供的错误处理策略是不是一致的?
    · 是否对错误信息进行了成套化管理以提供一个整洁的用户界面?
    · 是否指定了坚固性级别?
    · 有没有哪一部分结构设计被过分定义或缺少定义了?它是否明确说明了?
    · 是否明确提出了系统目标?
    · 整个结构在概念上是否是一致的?
    · 机器和使用实现的语言是否顶层设计依赖?
    · 给出做出每个重要决定的动机了吗?
    · 你作为系统实现者的程序员,对结构设计满意吗?

 3.5 选择编程语言先决条件

          程序类型                                最好语言                                最差语言

          结构化数据                   Ada、 C++、 Pascal                 汇编、Basic

          快速而杂乱的项目                Basic                              Pascal、Ada、 汇编

          快速执行                                 汇编、C                            解释性语言如Basic

          数学计算                                  Fortran                                  Pascal

          易于维护的程序                 Pascal 、Ada                         C 、Fortran

          动态内存使用                         Pascal、C                              Basic

          在有限内存环境下运行        Basic、汇编、C                     Fortran

          实时程序                                Ada、汇编、C                   Basic 、Fortran

          串操作                                  Basic 、Pascal                             C

3.6 编程约定

主要用于提供软件的概念完整性。

3.7 应花在先决条件上的时间

一般用于问题定义,需求分析和总体设计的时间应为20%~30%。

3.8 改变先决条件以适应你的项目

根据项目的大小相应的调整用于先决条件的工作量和时间。

3.9 小结

    · 如果想开发一个高质量的软件,必须自始至终重视质量问题。在开始阶段强调质量往往比在最后强调质量更为有效。
    · 程序员的份内工作之一便是向老板和同事宣传软件的开发过程,包括在编程开始前从 事先决条件准备工作的重要性。
    · 如果问题定义工作做得不好,那么在创建阶段,所解决的问题可能并不是用户真正要 解决的问题。
    · 如果需求分析工作做得不好,很可能因此而漏掉要解决问题中的重要细节。在创建工作后更改需求,要比在需求分析阶段进行更改的成本高20 到100 倍。所以,在开始编程前一定要确认需求定义工作一切正常。
    · 在编程前规定好约定,在创建工作结束后再改变代码来满足约定几乎是不可能的。
    · 在创建活动开始之前如果无法完成准备工作,可以尝试在不太稳固的基础上进行创建活动。

END