瑞星卡卡安全论坛技术交流区系统软件 【转载】软件开发人员必备工具书 【代码大全】

12345678»   4  /  16  页   跳转

【转载】软件开发人员必备工具书 【代码大全】

3.5.2 语言选择快速参考表
表3-3 给出了关于不同语言适用范围的简略参考。它也可以帮你选择应该进一步了解的语
言。但是,不要试图用它来代替对你某一特定计划进行语言选择时的详细评估。以下的排序是
很粗略的,因此阅读时应仔细辨别,因为很可能会有许多例外。
表3-3 适于不同种类程序的最差和最好语言
            程序类型                      最好语言                      最差语言
            结构化数据                    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%的时间用于先决条件。这20~30%的时间中不包括进行详
细设计的时间,因为它是创建活动的一部分。
gototop
 

如果你正从事一个正式项目,而要求又是不稳定的,那么,你将不得不与需求分析员一道
解决要求定义问题,拿出你的一部分时间与需求分析员讨论,并给需求分析员一定时间以便让
他重新征求用户意见,可以使要求定义更适合项目需要。
如果你从事的是一个非正式项目,而要求是不稳定的,应该给需求分析留出足够的时间,
以免反复无常的要求定义影响你的创建工作。
如果要求对于任何项目——不管是正式还是非正式的,都是不稳定的,那你就该亲自从事
需求分析工作。当完成需求分析后,再估计从事项目其余部分所需要的时间。这是一个很明智
的办法,因为在你知道自己将作些什么之前,你是不可能知道需要多长时间来完成它的。打个
比方,假设你是一个建筑承包商,你的顾客问:“这项工程要花多少钱?”你则问他要干些什么,
而他却接着说:“我不能告诉你,我只想知道工程要花多少钱?”这时你最好对他说声谢谢,然
后吹着口哨回家吧。
在建筑中,在知道要建什么之前,就进行工程预算显然是荒谬的。在设计师完成草图之前,
老板是不会问要用多少水泥、钉子和木材的。但人们对于软件开发的理解往往不是如此清楚的,
所以你的老板可能一时还弄不明白为什么要把需求分析当作一个单独的项目,这时你就需要作
出解释。
3.8  改变先决条件以适应你的项目
先决条件随项目规模和正式性不同而变化。本章指出了大规模和小型项目之间先决条件的
判别,可以根据项目的特点对先决条件作出合适的调整。要想详细了解大项目与小项目之间的
不同,请参看第21 章“程序规模是如何影响创建活动的”。
3.9  小 结
· 如果想开发一个高质量的软件,必须自始至终重视质量问题。在开始阶段强调质量往
往比在最后强调质量更为有效。
· 程序员的份内工作之一便是向老板和同事宣传软件的开发过程,包括在编程开始前从
事先决条件准备工作的重要性。
· 如果问题定义工作做得不好,那么在创建阶段,所解决的问题可能并不是用户真正要
解决的问题。
· 如果需求分析工作做得不好,很可能因此而漏掉要解决问题中的重要细节。在创建工
作后更改要求,要比在需求分析阶段进行更改的成本高20 到100倍。所以,在开始编
程前一定要确认要求定义工作一切正常。
· 在编程前规定好约定,在创建工作结束后再改变代码来满足约定几乎是不可能的。
· 在创建活动开始之前如果无法完成准备工作,可以尝试在不太稳固的基础上进行创建
活动。
gototop
 

第四章建立子程序的步骤
目录
    4.1  建立程序步骤概述
    4.2  程序设计语言(PDL)
    4.3  设计子程序
    4.4  子程序编码
    4.5  检查子程序
4.6  小结
相关章节
    高质量程序的特点:见第5 章
    高层次设计;见第7 章
    注释方式:见第19 章
    创建工作先决条件:见第3 章

本章详细讲述了在建立一个子程序时的典型步骤。虽然从广义上讲,你可以把本书所有的
描述都当作是在讲如何建立程序,但本章把这些步骤放在同一背景下讲述。本章的中心内容是
如何编写小规模的程序,以及编写对各种规模项目都十分关键的程序的特定步骤。本章也描述
了从程序设计语言(PDL)到编码的转换过程,几乎没有哪些程序员充分利用了这一过程所带来
的方便,这部分论述会给大家以启迪。
4.1  建立程序步骤概述
    在建立程序过程中引入的许多低层次细节问题,并不需要按某一特点顺序来进行,但是一
些主要活动——设计程序、检查程序、子程序编码、检查代码,则应该按图41 的顺序来进行。
4.2  程序设计语言( PDL L)
    PDL(程序设计语言)是由Came,Father 和Gordon 共同开发的,在1975 年发表之后.曾
作过重大修改。因为PDL 是在模仿英语,所以认为任何像是英语的PDL,都可以正确表达思想
是很自然的。但是,事实上PDL 之间的好坏是有判别的。下面是有效使用PDL 的一些方针:
·  用模拟英语的语句来精确描述每一个特定操作。
·  避免使用最终程序语言的语句。PDL 使你比在代码稍高级的层次上进行设计工作。
    当使用程序语言进行创建时,就又回到了低层次上,从而得不到由于在高层次上
    进行设计的好处,而且会受到不必要的程序语言语法规则的限制。
·  在设计意向这一层次上写PDL。说明方法的意义,而不是描述如何用目标语言实现。
gototop
 


图4-1  创建子程序过程中主要活动顺序示意图
·  在足够低的层次上写出PDL,它几乎可以自动生成代码。如果PDL 写得太简略,可能
会在编码过程中忽略问题细节。应该精确地使用PDL 以方便编码。
    当PDL 写好之后,就可以根据它来编码,而PDL 则成为程序语言的注释。这可以省去大量
的注释工作。如果PDL 遵循了这一指导方针,那么注释将是非常完备而且富有意义的。
    以下则是一个几乎违背了上述所有原则的错误使用PDL 的例子:
    Increment resource number by l
allocate a dlg struct using malloc
if malloc() returns NULL then return l
invoke OSrsrc _init to initialize a resource for the operation system
* hRstcPtr=resource number
return 0
    这个PDL 的意图是什么?由于它写得很糟糕,因此很难说清楚。之所以称之为一个错误使
用 PDL 的典型,是为它使用了像*hRSrcPtr这种特定的 c语言指针标志和malloc( )这个特定的
语言函数,即它采用了代码语句。这段PDL 的中心是如何写代码,而不是说明设计意义。不管
子程序返回1 还是返回0,这段PDL 都引入了代码细节。如果从是否变为一个好的注释的观点
来看这段PDL,你就会发现它毫无意义。
    以下是对同一个操作的设计,使用的是大大改进了的PDL:
      Keep track of current number of resource in use
If another resource is available
Allocate a dialog box structure
If a dialog box structure could be allocated
Note that one more resource is in use
Initialize the resource
Store the resource number at the location provided by the caller
Endif
Endif
gototop
 

Reture TRUE if a new resource was created; else return FALSE
    这段PDL 要好于前一个。因为它完全是用自然语言写成的,没有使用任何目标程序语言语
句。在第一段PDL 中,它只能用C 语言来实现,而第二段却并没有限制所使用的语言。同时,
第二段PDL 也是在意图层次上写成的。第二段PDL 的意图是什么?其意图理解起来比前一个要
容易多了。
    尽管第二段PDL 是完全用自然语言写成的,但它却是非常详细和精确的,很容易作为用程
序语言编码的基础。如果把这段PDL 转为注释段,那它则可以非常明了地解释代码的意图。
    以下是你使用这种风格的PDL可以获得的益处:
·  PDL可以使评审工作变得更容易。不必检查源代码就可以评审详细设计。它可以使详
细评审变得很容易,并且减少了评审代码本身的工作。
·  PDL可以帮助实现逐步细化的思想。 从结构设计工作开始,再把结构设计细化为PDL,
最后把PDL 细化为源代码。这种逐步细化的方法,可以在每次细化之前都检查设计,
从而可以在每个层次上都可以发现当前层次的错误,从而避免名影响下一层次的工作。
·  PDL使得变动工作变得很容易。几行PDL 改起来要比一整页代码容易得多。你是愿意
在蓝图上改一条线还是在房屋中拆掉一堵墙?在软件开发中差异可能不是这样明显,
但是,在产品最容易改动的阶段进行修改,这条原则是相同的。项目成功的关键就是
在投资最少时找出错误,以降低改措成本。而在PDL 阶段的投资就比进行完编码、测
试、调试的阶段要低得多,所以尽早发现错误是很明智的。
·  PDL极大地减少了注释工作量。在典型的编码流程中,先写好代码,然后再加注释。
而在PDL到代码的编码流程中,PDL本身就是注释,而我们知道,从代码到注释的花
费要比从注释到代码高得多。
·  PDL比其它形式的设计文件容易维护。如果使用其它方式,设计与编码是分隔的,假
如其中一个有变化,那么两者就毫不相关了。在从PDL到代码的流程中,PDL语句则
是代码的注释,只要直接维护注释,那么关于设计的PDL文件就是精确的。
作为一种详细设计工具,PDL是无可比拟的。程序员们往往愿意用PDL而不愿使用缺陷表。
事实上程序员们愿意使用缺陷表以外的任何工具,调查表明,程序员们愿意使用PDL,是因为
它很容易用程序语言实现,而且PDL 可以帮助发现详细设计中的缺陷,并且PDL 也很容易写
成文件,改动也很方便,PDL 并不是详细设计的唯一工具,但是PDL 和PDL 到代码流程的确
是有用的工具。不妨试一下。在随后的几部分中,我们将告诉你如何使用它们。
4.3  设计子程序
    创建一个子程序的第一步是设计。假设想设计一个根据错误代码输出错误信息的子程序,
并且把这个子程序称为RecordErrorMessge(),以下是关干RecordErrorMessage()的要求定义:
    RecordErrorMessage()的输入变元是非法代码,输出是与这个非法代码相对应的错误信息,
它负责处理非法代码。如果程序运算方式是交互式,那么这个错误信息就打印给用户。如果运
行方式是批处理式的,那么这个信息就送入一个信息文件。在输出信息后,这个子程序应该能
返回到一种状态,指出程序是否成功。
gototop
 

在本章的其余部分,用这个子程序作为一个实际例子。这一部分的其余内容将论述如何设
计这个子程序,设计这个子程序所需要进行的活动见图4-2。
    检查先决条件。在进行与子程序有关的任何工作之前,首先检查是否定义了这个子程序的
工作任务,这项任务是否和整个结构设计融为一体?通过检查确定是否这个子程序被调用了?
至少,在项目的要求定义中就涉及到它。
    定义这个子程序将要解决的问题。应该足够详尽地规定它需要解决的问题,以便于创建。
如果结构设计是非常详尽的,那么这项工作可能已经完成了,结构设计应该至少指出以下这些
问题:
·  这个子程序将要隐含的信息。
·  这个子程序的输入。
·  这个子程序的输出,包括受到影响的全局变量。
·  这个子程序将如何处理错误?
 
图4-2  设计程序中的所有实现步骤     
    下面是在RecordErrorMessage()这个子程序中,上述考虑是如何得以阐明的。这个子程序隐
含了如下两个事实;错误信息与现存的处理方式(交互式或者批处理),子程序的输入是非法代
码,要求两种输出方式:第一是错误信息;第二是RecordErrorMessass()子程序返回到调用它的
程序时的状态。
    问题说明之后,并没有直接给出解决方案。假设以这个例子来说,程序约定是在发现错误
时立即报告。在这种情况下,这个子程序必须报告它所发现的每一个错误,假定其它错误都已
经报告过了。根据要求,这时子程序应把状态变量设置为失败。
    给子程序命名。给子程序命名似乎是小事一桩,但好的子程序名字往往是一个高质量软件
的标志之一,而且,命名并不是件容易的事情。一般来说,子程序应该有一清楚的、不容易引
起异义的名字。如果在给程序找一个好名字时感到困难,这往往意味着对程序的功能还不十分
清楚。一个模棱两可的名字就像是一个在进行竞选辩论的政治家,似乎他在说着什么,可是当
gototop
 

你仔细听时,又分辨不出他的话到底有什么意义、应尽量将名字起得清楚。如果产生一个模棱
两可名字的原因是模棱两可的结构设计,那么就应注意这个危险信号,这时应追回去改进结构
设计。
    在这个例子中,RecordErrorMessage()的含义是很清楚的,因此是个好名字。
    决定如何测试子程序。在编写于程序时,最好能同时考虑如何测试。这对进行单元测试工
作是很有益处的。
    在这个例子中,输入很简单,就是错误代码。因此,可以计划用全部有效错误代码和一系
列无效代码来进行测试。
    考虑效率。根据所处的情形,你可以用一种或两种方式来说明效率。
    在第一种情形下,程序的绝大部分,性能并不是主要的,在这种情况下,应该把子程序作
成高度模块化而且具有很强的可读性,以便在今后需要时很容易对其作出改进。如果其模块化
程度很高,就可以在需要时,用更好的算法或者汇编语言编写的子程序来代替速度较慢的程序
而不致影响程序其它部分。
    在第二种情形下,在大部分程序中,性能都是很重要的,这时,结构设计应该对子程序的
运行速度和允许使用的内存作出规定,只要按照速度和空间指标设计子程序就可以了。如果速
度和空间只有一方面是主要的,则可以牺牲一方面来满足另一方面的要求。在初始创建阶段,
对子程序作出足够调整以使它满足速度和空间要求是合理的。
    除了以上指明的情况以外,不必浪费精力去考虑个别子程序的执行效率。优化的收益主要
来自高层次设计,而不是个别子程序、只有在高层次设计某方面有缺陷时,才需要进行微观优
化,而这点只在程序全部完成时才会知道。除非必要,不要浪费时间进行增量改进。
    研究算法和数据结构。同时提高编码质量和效率的最有效办法是重新使用好的代码。在
学术文章中,已经有许多种算法被发明、讨论、检验和改进过。因此,与其花费时间去发明一
种别人已经为之写过博士学位论文的东西,倒不如花几分钟测览一个算法论著,看有多少种算
法可供选择。如果想使用某种已有的算法,切记要对其做出改进以适应你的程序语言。
    编写PDL 。在做完上述工作之后,编写的时间可能已经不多了。本步骤的主要目的是,建
立一种可以在实际编写子程序时提供思想指导的文件。
    在主要工作步骤完成之后,可以在高层次PDL 水平上编写子程序。可以使用编辑程序或者
整体环境来编写PDL,很快,这些PDL 就将成为用程序语言编码的基础。
编写工作应该从抽象到具体。一个子程序最抽象的部分便是最开始的注释部分,这部分将
说明要求于程序作什么;因此,首先应该写一个关于编写于程序目的的精确说明。编写这个说
明也将帮你更清楚地理解这个子程序。如果在编写这部分说明时感到困难,那说明需要对这个
子程序在整个软件中的地位和作用作出更深刻的理解。总之,如果感到编写抽象说明时有困难,
应该想到可能是某一环节出了问题。以下是一个精确说明子程序作用的例子:
        This routine outputs an error message based on an error code
supplied by the calling routine. The way it outputs the message
depends on the current processing state,which it retrieves
on its own.It returns a variable indicating success or failure.
    写完抽象说明后,再编写关于这个子程序的高层次PDL。下面就是一个关于前述例子的高
层次PDL:
gototop
 

This routine outputs an error message based on an error code
supplied by the calling routine.The way it outputs the message
depends on the current processing state, which it retrieves
on its own. It returns a variable indicating success or failure.
set the default status
look up the message based on the error code
if the error code is valid
determine the processing method
if doing interactive processing
print the error message interactively and declare success
else doing batch processing
if the batch message file opens properly
log the error message to the batch file,
close the file,and declare success
else the message code is not valid
notify the user that an interal error has been detected

    应该注意的是这个PDL 是在一个相当高的层次上写成的。它使用的不是程序语言,而是用
自然语言来精确表达设计思想的。
    考虑数据。可以在编写过程中的几个不同地方设计数据。在这个例子中,数据非常简单,
因而数据操作并不是程序的主要部分。如果数据操作是程序的主要部分,那么在考虑程序的逻
辑结构之前,考虑主要数据是必要的。如果在进行子程序的逻辑设计时,已经有了关键数据结
构的定义,那将是大有梅益的。
    检查PDL 。写好PDL 并设计完数据之后,应该花一点时间来检查一下PDL。返回来看着所写
的PDL,考虑一下应该怎样向别人说明。
    请别人帮助看一下或听一下你的说明。也许你认为请别人看一个只有11 行的PDL 是很
愚蠢的,但你会对这样作的结果感到惊奇。PDL 使假设和高层次错误比程序语言代码容易被发
现。人们往往更愿意检查一个只有几行的PDL,而不愿去检查一个有35 行的C 或Pascal 子程
序。
    要确认对子程序做什么和将怎样做已经有了清楚透彻的了解。如果在PDL 这一层次上对这
点还没有概念上的了解,那么在编码阶段了解它的机会还有多少呢?如果连你都理解不了它的
话,又有谁会理解呢?
    逐步细化。在开始编码之前,要尽可能多使用PDL 尝试一些想法。一旦开始编码,就会对
所写的代码产生爱惜之情,这时,要再想把它扔掉重新开始是非常困难的。
    通常的思想是逐步细化用PDL 写成的子程序,直到可以在每行PDL 语句下面添加一行代码
而成为子程序为止,并把原来的PDL 当作注释文件,或许最初的PDL 的某些部分过于简略,需
要进一步说明,那么切记一定要对其作出进一步说明。如果不能确认如何对某一部分编码,那
么就继续细化PDL,直到可以确认为止。要不断地细化PDL 并对其作出进一步说明,直到你看
到这样作是在浪费时间时,再开始实际的编码工作。
gototop
 

4.4  子程序编码
设计好子程序之后,就要开始实现。可以按照标准步骤实现,也可以根据需要作出改动。图
4-3 给出了实现一个子程序时的步骤。

                                  图4-3 实现子程序的步骤
    书写子程序说明。 编写子程序的接口语句——编写过程或函数说明,应采用所需要的语言,
无论Pascal、C 或Fortran 都可以,只要符合需要。把原来的抽象说明用程序语言实现,把它放
在原来写好的PDL 位置之上。以下是前述子程序的接口语句和抽象说明,它是用Pascal写成的:
procedure RecordErrorMessage
(
ErrorCode:ErrorCode_t ;
var Status:Status_t
);

  { This routine outputs an error message based on an error code
Supplied by the calling routine. The way it outputs the message
depends on the current processing state, which it retrieves
on its own. It returns a variable indicating success or failure. }
    set the default staus
look up the message based on the error code
已转化成Pascal 风格
注释的标题注释
这些是接口语句
gototop
 

if the error code is valid
determine the processing method
if doing interactive processing
print the error message interactively and declare success
else doing batch processing
if the batch message file opens properly
log the error message to the batch file,
close the file, and declare success
else the message code is not valid
notify the user that an internal error has been detected
    这时是指出接口假设的好时机。在本例中,接口变量ErrorCode 和Status 是简明的,并且
根据其特定用途排序,不含任何隐蔽信息。
    把PDL 转变成高层次注释。利用Pascal 中的Begin 和End,或者C 中的“{”和“}”,可
以把PDL变成注释,以下是把前述的PDL变成了Pascal语言:
        procedure RecordErrorMessage
(
Errorcode:ErrorCode_t;
var Status:Status_t
);
{ This routine outputs an error message based on an error code
Supplied by the calling routine. The way it outputs the message
depends on the current processing state, which it retrieves
on its own. It returns a variable indicating success or failure.}
begin
{ set the default status }
{ look up the message based on the error code }
{ if the error code is valid}
{ determine the processing method }
{ if doing interactive processing}
{ print the error message interactively and declare success}
{ else doing batch processing }
{ if the batch message file opens properly}
{log the error message to the batch file,
close the file. and declare success}
{else the message code is not valid}
{ notify the user that an internal error has been detected}
end; { RecordErrorMessage() }
    这时,子程序的特点已经非常明显了,设计工作已经结束了,没看见任何代码,但已经知
道子程序如何工作了。把PDL转换成程序语言代码是一件机械、自然、容易的工作。如果你不
gototop
 
12345678»   4  /  16  页   跳转
页面顶部
Powered by Discuz!NT