• 沒有找到結果。

设计子程序

在文檔中 Code Complete 代码大全 (頁 45-49)

第四章 建立子程序的步骤

4.3 设计子程序

创建一个子程序的第一步是设计。假设想设计一个根据错误代码输出错误信息的子程序,

并且把这个子程序称为 RecordErrorMessge(),以下是关于 RecordErrorMessage()的需求定义:

RecordErrorMessage()的输入变量是非法代码,输出是与这个非法代码相对应的错误信息,

它负责处理非法代码。如果程序运算方式是交互式,那么这个错误信息就打印给用户。如果运 行方式是批处理式的,那么这个信息就送入一个信息文件。在输出信息后,这个子程序应该能 返回到一种状态,指出程序是否成功。

在本章的其余部分,用这个子程序作为一个实际例子。这一部分的其余内容将论述如何设 计这个子程序,设计这个子程序所需要进行的活动见图 4-2。

检查先决条件。在进行与子程序有关的任何工作之前,首先检查是否定义了这个子程序的 工作任务,这项任务是否和整个结构设计融为一体?通过检查确定是否这个子程序被调用了?

至少,在项目的需求定义中就涉及到它。

定义这个子程序将要解决的问题。应该足够详尽地规定它需要解决的问题,以便于创建。

如果结构设计是非常详尽的,那么这项工作可能已经完成了,结构设计应该至少指出以下这些 问题:

・ 这个子程序将要隐含的信息。

・ 这个子程序的输入。

・ 这个子程序的输出,包括受到影响的全局变量。

・ 这个子程序将如何处理错误?

PDL

PDL

图 4-2 设计程序中的所有实现步骤

下面是在 RecordErrorMessage()这个子程序中,上述考虑是如何得以阐明的。这个子程序隐 含了如下两个事实;错误信息与现存的处理方式(交互式或者批处理),子程序的输入是非法代 码,要求两种输出方式:第一是错误信息;第二是 RecordErrorMessass()子程序返回到调用它的 程序时的状态。

问题说明之后,并没有直接给出解决方案。假设以这个例子来说,程序约定是在发现错误 时立即报告。在这种情况下,这个子程序必须报告它所发现的每一个错误,假定其它错误都已 经报告过了。根据要求,这时子程序应把状态变量设置为失败。

给子程序命名。给子程序命名似乎是小事一桩,但好的子程序名字往往是一个高质量软件 的标志之一,而且,命名并不是件容易的事情。一般来说,子程序应该有一清楚的、不容易引 起异义的名字。如果在给程序找一个好名字时感到困难,这往往意味着对程序的功能还不十分 清楚。一个模棱两可的名字就像是一个在进行竞选辩论的政治家,似乎他在说着什么,可是当

你仔细听时,又分辨不出他的话到底有什么意义、应尽量将名字起得清楚。如果产生一个模棱 两可名字的原因是模棱两可的结构设计,那么就应注意这个危险信号,这时应返回去改进结构 设计。

在这个例子中,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:

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 并对其作出进一步说明,直到你看 到这样作是在浪费时间时,再开始实际的编码工作。

在文檔中 Code Complete 代码大全 (頁 45-49)