• 沒有找到結果。

特定数据类型命名

在文檔中 Code Complete 代码大全 (頁 136-140)

第九章 数据名称

9.2 特定数据类型命名

除了对数据命名通常需要考虑的一些问题之外,对特殊数据类型必须给予特殊的考虑。本 书将论述循环变量、状态变量、临时变量、逻辑变量、枚举变量和命名常量的命名问题。

9.2.l 循环变量命名

由于几乎每个程序中都含有循环,因此,对循环变量的命名问题加以专门考虑是十分必要 的。

简单循环中的循环控制变量的名字往往也是十分简单的,常用的是 i、j、k 等。下面是一个 Pascal 循环的例子:

for i:=FirstItem to LastItem do Data[i] := 0;

如果这个变量还要在循环外使用,那么应该用比 i、j、k 更能说明问题的名称。比如,你正 从文件中读取记录,并且要知道已经读取了多少个记录,那么用 RecordCount 作为其名称似乎 更合适些,请看下面的这个 Pascal 程序:

RecordCount:= 0

while not eof(InputFile) do

begin

RecordCount := RecordCount + 1;

ReadLn ( Score [ Recordcount ] ) end;

{ lines using RecoudCount }

如果循环体长度较长的话,那就很容易使人忘记它代表的是什么,因此最好给循环控制变 量一个富有意义的名字。由于经常进行更改,扩展和拷贝等代码到另一个程序中,因此,大多 数有经验的程序员都避免用 i、j、k 这类的名字。

使循环体变长的一个常见原因是嵌套。因此,对于一个有多重嵌套的循环,最好给循环控 制变量以较长的名字以便改善其可读性:

for TeamIndex := i to TeamCount to begin

for EventIndex := 1 to EventCount[ TeamIndex ] do Score[ TeamIndex, EventIndex ] := 0

end;

通过精心对循环控制变量进行命名,可以避免它们的交叉:当你想用 i 时误用了 j,或者 想用 j 时却又误用了 i。这样做也可以使对数组的存取操作更为明了。Score [ TeamIndex, EvenIndex ]显然要 Score[i,j]更能说明问题。总之,应尽量避免使用 i、j、k 来命名。如果不得 不使用它们的话,那除了把它们用作循环控制变量之外,最好不再用作别的变量名。这一约定 是众所周知的,如果不遵守它只会引起别人的困惑。

9.2.2 状态变量命名

状态变量描述的是程序所处的状态。下面论述了它们的命名原则。

用比 flag 更好的名称来命名变量,最好不用 flag 作为状态变量的名字。之所以要避免使用 flag 作为标志名称,是因为它不能告诉你关于这个标志的任何信息。为了清楚起见,应该给标 志赋值,并且用枚举类型、命名常量或当作命名常量使用的全局变量对其进行测试。下面是一 个在 C 语言中不恰当命名标志的例子。

if( Flag )...

if( StatusFlag & 0x0F )...

if( PrintFlag == 16 )...

if( ComputerFlag == 0 )...

Flag = 0x1;

StatusFlag = 0x80;

PrintFlag = 16;

ComputerFlag = 0;

如果这个程序不是你写的,而且也没有注释告诉你的话,你是无法知道类似 statusFlag = 0x80 之类的语句到底是要干什么的,而且你也无法知道 Statusflag 和 0x80 到底是什么意思。以

下是功能与内容相同但清楚得多的程序:

if ( DataReady )...

if ( CharacterType & PRINTABLE_CHAR )...

if ( ReportType == AnnualRpt )...

if ( RecalcNeeded == TRUE )...

DataReady = TRUE;

CharacterType = CONTROL_CHARACTER;

ReportType = AnnualRpt;

RecalcNeeded = FALSE;

显然,第二个例子中 CharacterType = CONTROL_CHARACTER 的意义要比第一个中 StatusFlag = 0x80 的意义要清楚得多。同样,第二个例子中的条件语句 if ( ReportType ==

AnnualRpt ) 也显然要比第一个中的 if ( PrintFlag == 16 )清楚得多。第二个例子表明,你可借 助预先命名的常量或枚举类型来使用这种方法。以下是如何利用枚举类型和命名常量来设置上 例中用到的值,仍用 C 来实现:

/* values for DataReady and RecalcNeeded */

#define TRUE 1

#define FALSE 0

/* values for CharacterType */

#define LETTER 0x01

#define DIGIT 0x02

#define PUNCTUATION 0x04

#define LINE_DRAW 0x08

#define PRINTABLE_CHAR ( LETTER | DIGIT | PUNCTUATION | LINE_DRAW )

#define CONTROL_CHARACTER 0x80

/* values for ReportType */

Typedef enum { DailyRpt,MonthlyRpt,,QuarterlyRpt,

AnnualRpt,AllRpts}REPORT_TYPE_T;

当你发现自己“侦破”了一段代码时,应该考虑对变量重新命名。侦破一桩凶杀案是可以 的,但你不应该去“侦破”一段代码。代码应该是具有良好可读性的。

9.2.3 临时变量命名

临时变量用来保存中间运算结果,如用作暂时保留某个位置或保留内务操作值。通常把它 们叫做 TEMP 或 X 等没有什么意义的名字。临时变量的使用往往标志着程序员还没有完全理解

程序。而且,由于名义上给了它一个“临时”的状态,因而程序员们在处理它们时往往会采取 漫不经心的态度,从而增大了出错机会。

要警惕“临时”变量。通常,暂时保留某些值是完全必要的。但如果在你的程序中出现很 多临时变量的话,则说明你对它们在程序中作用和使用它们的目的还不清楚。先让我们看一下 下面用 C 语言写成一个例子:

/* Compute root of a quadratic equation.

This assumes that ( b^2 - 4 * a * c ) is positive. */

Temp = sqrt ( b^ 2 - 4 * a * c );

root[0] = ( -b + Temp )/( 2 * a );

root[1] = ( -b – Temp )/( 2 * a );

把由公式 sqrt ( b^2 - 4 * a * c ) 计算出来的值储存起来是个不错的想法,尤其是在后面还有 两处用到了它的情况下。但是用 TEMP 作为它的名称不能告诉你关于这个变量意义的任何信息。

一个较好的作法是下面这个例子:

/* Compute roots of a quadratic equation.

This assumes that ( b^2 – 4 * a * c )is positive */

Discriminant = sqrt ( b^2 - 4 * a *c );

root[0] = ( -b + Discriminant )/( 2 * a );

root[1] = ( -b - Discriminant )/( 2 * a );

事实上两段代码是完全一样的,但是通过采用更准确也更能说明问题的变量名,大大改善 了其可读性。

9.2.4 逻辑变量命名

以下命名逻辑变量的几条准则:

记住一些典型的逻辑变量名。以下是些非常有用的逻辑变量名:

Done。用 Done 来表示某项工作已经完成了。这个变量可以表示子程序或循环是否已经完 成。当某项工作没有完成时,把 Done 的值赋为 False;当某项工作已经完成时,把 Done 的值 赋为 True。

Error。用 Error 来表示发生了错误。当没有错误时将 Error 的值赋为 False;当有错误时将

赋为 True。

Found。用 Found 来表示是否找取了某个值。当搜寻数组来查找某一值或搜寻某一文件表 查找某一雇员的识别卡时,没有找到某一值时将其值赋为 False,而一旦找到这个值。则把 Found 值赋为 True。

Success。用 Success 来表示某一操作是否已成功地完成。当某一程序无法完成时,将 Success 的值置为 False;而当某一操作已经完成时,将 Success 的值置为 True。如果可能的话,可以用 比 Success 更准确更具有表达力的名称来代替它,用这个新名称应可以精确地表达出到底是什 么 已 成 功 地 完 成 了 。 比 如 当 某 一 程 序 完 成 处 理 后 就 可 以 认 为 是 成 功 时 , 就 可 以 用 Processingcomplete 来代替 Success。如果当找到某一值就可以为程序是成功的时,可以用 Found 来代替它。

用暗含非真即假的名字来给逻辑变量命名。像 Done 或 Success 等之所以是恰当地逻辑变量 名,是因为它们的状态是非真(True) 即假 (False)的。某项工作或者完成了或者没完成;或者 是成功的或者不成功,不会有第三种状态。而类似 Status 或 SourceFile 等则是不恰当的名字,

因为看不出它们的状态是非真即假的。如果 Status 的值是 True,那它是否意味着某种物质有状 态呢?任何物质都有状态。或者说当其值是 True 时,意味着某种物质的状态很好,而为 False 时则意味着状态不好?仅从 Status 这个名称是无法回答这些问题的。

为清楚起见,最好用 Error 或 Status_OK 等来代替 Status;用 SourceFileAvailable 或 SourceFileFound 来代替 Source。

有些程序员喜欢用 Is 用为逻辑变量名的前缀,于是变量名就成了一个问句:IsDone?

IsError?IsSuccess?当用 True 或 False 来回答上述问题时,就等于给变量赋了值。这样做的好 处是可以避免那些不恰当的名称。如 IsStatus 显然没有任何意义。

使用肯定的逻辑变量名。否定式的变量名如 NotFound、NotDone 和 Notsuccessful 等在“非”

运算中是很难读懂的,如:

if not NotFound

这类名字应该用 Found,Done,Successful 等来代替,以方便“非”运算。

9.2.5 枚举类型命名

当使用枚举型变量时,可以通过使用相同的前缀或后缀表示某一类型的元素都是属于同一 组的,如下面的这段 Ada 程序所示:

type COLOR is ( COLOR_RED, COLOR_GREEN,COLOR_BLUE );

type PLANET is ( PLANET_ERATH, PLANET_MARS, PLANET_VENUS );

9.2.6 常量命名

对常量来说,应该用它所代表的抽象实体而不是数值来命名。FIVE 是一个很不恰当的常量 名 称 ( 不 管 它 代 表 的 数 值 是 否 是 5.0 ); CYCLES_NEEDED 则 是 个 恰 当 的 名 称 , CYCLES_NEEDED 可以等于 5.0 也可以等于 6.0,而 Five = 6.0 则是个荒唐的语句。由于同样的 原因,BAKERS_DOZEN 也是很不恰当的变量名,而 MAX_DONUTS 则要恰当得多。

在文檔中 Code Complete 代码大全 (頁 136-140)