• 沒有找到結果。

子程序编码

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

第四章 建立子程序的步骤

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. }

这些是接口语句

已转化成 Pascal 风格 注释的标题注释

set the default staus

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

这时是指出接口假设的好时机。在本例中,接口变量 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 转换成程序语言代码是一件机械、自然、容易的工作。如果你不

觉得是这样,那么还需要进一步细化 PDL,直到有这种感觉为止。

在每一行注释下面填上代码。在每一行 PDL 注释语句下面填上代码。这有点像给报纸排版。

首先画好轮廓线,然后再把每一篇文章填到空格中,每一个 PDL 注释行都相当于给代码画的轮 廓线,而代码相当于文章。同文学文章的长度一样,代码的长度也是由它所要表达的内容多少 决定的。程序的质量则取决于它的设计思想的侧重点和巧妙程度。

在本例中,前两行 PDL 注释产生了两行代码:

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 }

Status:=Failure;

{ look up the message based on the error code}

LookupErrorMessage(ErrorCode,ErrorMessage); 这里是新变量 ErrorMessage

{ 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() }

这是一个编码的开始,使用了变量 ErrorMessage,所以需要说明它。如果是在事后进行注 释,那么,用两个注释行来注释两行代码就不必要了。但是,采用目前这种方法,是注释的字 面内容而不是它注释了多少行代码。现在,注释行已经存在了,所以还是将其保留。

代码需要变量说明,而且在每一注释行下面都要加入代码,以下是完整的子程序:

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, whict it retrieves on its own. It returns a variable indicating success or failure. } var

这里是变量声明 ProcessingMehod: ProcessingMethod_t;

ErrorMessage: Message_t;

FileStatus: Status_t;

begin

{set the default status}

Status:=Failure;

{look up the message based on the error code } LookupErrorMessage(ErrorCode,ErrorMessage);

{if the error code is valid}

if (ErrorMessage.ValidCode) then begin

{determine the processing method}

ProcessingMethod := CurrentProcessingMehod;

{if doing interaction processing}

if (ProcessingMethod = Interactive) then begin

{print the error message interactively and declare success } PrintInteractiveMessage(ErrorMessage.Text);

Status := Success end

{else doing batch processing}

else if (ProcessingMethod = Batch) then begin {if the batch message file opens properly}

FileStatus := OpenMessageFile;

If (FileStatus = Success) then begin

{log the error message to the batch file,close the file, and declare success}

LogBatchMessage ( ErrorMessage.Text ) ; CloseMessageFile;

Status := Success end { if }

end { else } end

{ else the message code is not valid } else begin

{ notify the user that an interanl error has been detected } PrintlnteractiveMessage ( 'Internal Error; Invalid error code' , 'in RecordErrorMessage()' }

end

end; { RecordErrorMessage () }

每一个注释都产生了一行或一行以上的代码,每一块都在注释的基础上形成了一个完整的 思想。保留了注释以便提供一个关于代码的高层次解释,在子程序的开始,对使用的所有变量 都作了说明。

现在,让我们再回过头来看一下前面的关于这个例子的需求定义和最初的 PDL,从最初的 5 行需求定义到 12 行的初始 PDL,接着这段 PDL 又扩大成为一个较大的子程序。即使需求定 义是很详尽的。子程序的创建还是需要在 PDL 和编码阶段进行潜在的设计工作。这种低层次的 设计工作正是为什么编码不是一件琐碎事的原因,同时,也说明本书的内容是很重要的。

非正式地检查代码。在注释下面填上代码之后,可以对每一块代码作一简略检查。尽力想 一下什么因素可能破坏目前的块,然后证明这种情况不会发生。

一旦完成了对某一子程序的实现,停下来检查一下是否有误。在 PDL 阶段,就已经对其作 了检查。但是,在某些情况下,某些重大问题在子程序实现之前是不会出现的。

使得问题直到编码阶段才出现的原因是多方面的。在 PDL 阶段引入错误可能到了详尽的实 现阶段才会变得明显。一个在 PDL 阶段看起来完美无缺的设计,在用程序语言实现时可能会变 得一塌糊涂。在详尽的实现阶段,可能会发现在结构设计或功能分析阶段引入的错误,最后,

代码可能存在一种司空见惯的错误——混用语言,毕竟大家都不是尽善尽美的嘛。由于上述原 因,在继续工作之前,要检查一下代码。

进行收尾工作。检查完代码是否存在问题后,再检查一下它是否满足本书所提到的通用质 量标准。可以采取几个步骤来确认子程序的质量是否满足要求。

・ 检查子程序的接口。确认所有的输入和输出数据都已作出了解释,并且使用了所有 参数。关于细节问题,见 5.7 节“怎样使用子程序参数”。

・ 检查通用设计质量。确认子程序只完成一项任务而且完成得很好,与其它子程序交 叉是控制不严的表现。并且,应该采用了预防错误的设计。关于细节问题,见第五 章“高质量程序的特点”。

・ 检查子程序的数据。查找出不精确的变量名、没有使用的数据、没有说明的数据等

等。要了解详情,见关于数据使用的第八到第十二章。

・ 检查子程序的控制结构。查找无限循环、不适当的嵌套等错误。详见关于使用控制结 构的第 13 到 17 章。

・ 检查子程序设计。确认已说明了子程序的表达式、参数表和逻辑结构。详见第 18 章 “设 计与风格”。

・ 检查子程序的文档。确认被翻译成注释的 PDL 仍然是精确的。检查算法描述,查找接 口假设和非显式依赖的文件资料,查找不清楚的编码等等。详见第 19 章“自我证明的 代码”。

按需要重复步骤。如果程序的质量很差,请返回 PDL 阶段。高质量程序是一个逐步的过程,

所以在重新进行设计和实现活动时,不要犹豫不决。

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