Java编程的标准之JAVA编程规范(2)

命名构造函数

构造函数是在一个对象初次生成时,完成所有必需的初始化的成员函数。构造函数与它所属类的名字总是相同的。例如,类Customer 的构造函数是Customer()。注意大小写一致。

示例:

Customer()

SavingsAccount()

PersistenceBroker()

这个命名约定由 Sun 公司设定,必须严格遵守。

成员函数的可见性

良好的程序设计应该尽可能减小类与类之间耦合,所遵循的经验法则是:尽量限制成员函数的可见性。如果成员函数没必要公有 (public),就定义为保护 (protected);没必要保护 (protected),就定义为私有 (private)。

可见性

说明

正确用法

public

公有成员函数可被任何其它对象和类的成员函数调用。

当该成员函数必须被该函数所在的层次结构之外的其他对象和类在访问时。

protected

被保护的成员函数可被它所在的类或该类的子类的任何成员函数调用。

当该成员函数提供的行为被它所在类的层次结构内部而非外部需要时。

private

私有成员函数只可以被该类所在的其它成员函数调用,该类的子类不可以调用。

当该成员函数所提供的行为明确针对定义它的类时。私有成员函数常常是重新分配要素的结果。重新分配要素又叫“重组”,指类内其它成员函数封装某一个特定行为的做法。

注释成员函数

如何注释一个成员函数常常成为判断函数是否可被理解,进而可维护和可扩展的决定性因素。

成员函数的函数头

每一个 Java 成员函数都应包含某种称之为“成员函数文档”的函数头。这些函数头在源代码的前面,用来记录所有重要的有助于理解函数的信息。 这些信息包含但不仅仅局限于以下内容:

1. 成员函数做什么以及它为什么做这个。通过给一个成员函数加注释,让别人更加容易判断他们是否可以复用代码。注释出函数为什么做这个可以让其他人更容易将你的代码放到程序的上下文中去。也使其他人更容易判断是否应该对你的某一段代码加以修改(有可能他要做的修改与你最初为什么要写这一段代码是相互冲突的)。

2. 哪些参数必须传递给一个成员函数。还必须说明,如果带参数,那么什么样的参数必须传给成员函数,以及成员函数将怎样使用它们。这个信息使其他程序员了解应将怎样的信息传递给一个成员函数。在 (第 1.4.2 节“快速浏览javadoc”) 中讨论的 javadoc @param 标识便用于该目的。

3. 成员函数返回什么。如果成员函数有返回值,则应注释出来,这样可以使其他程序员正确地使用返回值/对象。在(第 1.4.2节“快速浏览 javadoc”) 里讨论的 javadoc @return 标识便用于此目的。

4. 已知的问题。成员函数中的任何突出的问题都应说明,以便让其他程序开发者了解该成员函数的弱点和难点。如果在一个类的多个成员函数中都存在着同样的问题,那么这个问题应该写在类的说明里。

5. 任何由某个成员函数抛出的异常。应说明成员函数抛出的所有异常,以便使其他程序员明白他们的代码应该捕获些什么。在 (第 1.4.2节“快速浏览 javadoc”) 中讨论的 javadoc @exception 标识便用于此目的。

6. 可见性决策。如果你觉得你对于一个成员函数可见性的选择会遭到别人的质疑,例如可能你将一个成员函数设为公共的,但是却没有任何对象调用该成员函数,那么应说明你的决定。这将帮助其他开发者了解你的想法,使他们不必浪费时间操心考虑你为什么要选择一种有疑问的东西。

7. 成员函数是如何改变对象的。若一个成员函数修改了一个对象,例如一个银行帐户的成员函数withdraw() 修改了帐户余额,那么就需要说明。这种信息必须给出,使其他 Java 程序员能准确地知道一个成员函数调用将如何影响目标对象。

8. 避免使用含有信息的函数头。比如说作者、电话、创建和修改日期、单元(或者文件名)的位置,因为这些信息很快就会过时。将版权所有者信息放到单元的最后。例如,读者不会想要翻过两三页诸如“版权所有”等对理解程序毫无帮助且(或)不提供任何编程信息的文本。避免使用垂直滚动条或者关闭的文本框或对话框,这些东西只会增加视觉干扰,而且较难保持一致。采用一个配置管理工具来保存单元历史。

9. 如何在适当情况下调用成员函数的例子。最简单的确定一段代码如何工作的方法是看一个例子。考虑包含一到两个如何调用成员函数的例子。

10. 可用的前提条件和后置条件。前提条件是指一个成员函数可正确运行的限制条件;后置条件是指一个成员函数执行完以后的属性或声明 [MEY88]。前提条件和后置条件以多种方式说明了在编写成员函数过程中所做的假设 [AMB98],精确定义了一个成员函数的应用范围。

11. 所有并行事件。对众多程序开发者来说,并行性是一个新而复杂的概念;对有经验的并行性程序开发者来说,并行性也是一个老但却复杂的课题。最终结果是,如果应用了 Java 的并行编程特性,那么应在程序中详细地将其注释出来。[LEA97] 建议,当一个类既包含了同步也包含了非同步的成员函数时,必须注释出成员函数依赖的执行上下文,尤其是当函数可被无约束访问时。这样可以让其他开发者安全地使用你的成员函数。当一个采用了 Runnable 接口的类的设置函数(即可更新一个字段的成员函数)没有同步时,应说明这样做的理由。最后,如果覆盖或重载一个成员函数,并且修改了它的同步性时,也应说明理由。

仅当注释增加代码的清晰度时,才应加上注释。对于每个成员函数,并非要说明以上所有部分,因为对于每一个成员函数来说,并不是以上所有的部分都适用。但是,对于所写的每个成员函数要说明以上的部分内容。

内部注释

除成员函数注释以外,在成员函数内部还需加上注释语句来说明你的工作。目的是使成员函数更易理解、维护和增强。

内部注释应采用两种方式:C 语言风格的注释 (/* 和 */) 和单行注释 (//)。正如上述所讨论的,应认真考虑给代码的业务逻辑采用一种风格的注释,给要注释掉的无用代码采用另外一种风格的注释。建议对业务逻辑采用单行注释,因为它可用于整行注释和行末注释。采用 C 语言风格的注释语句去掉无用的代码,因为这样仅用一个语句就可以容易地去掉几行代码。此外,因为 C 语言风格的注释语句很象文档注释符。它们之间的用法易混淆,这样会使代码的可理解性降低。所以,应尽量减少使用它们。

在函数内,一定要说明:

1. 控制结构。说明每个控制结构,例如比较语句和循环。你无须读完整个控制结构内的代码才判断它的功能,而仅需看看紧靠它之前的一到两行注释即可。

2. 代码做了些什么以及为什么这样做。通常你常能看懂一段代码做了什么,但对于那些不明显的代码,你很少能判断出它为什么要那样做。例如,看完一行代码,你很容易地就可以断定它是在定单总额上打了 5% 的折扣。这很容易。不容易的是为什么要打这个折扣。显然,肯定有一条商业法则说应打折扣,那么在代码中至少应该提到那条商业法则,这样才能使其他开发者理解你的代码为什么会是这样。

3. 局部变量。虽然我们在第 4 章将仔细讨论这一点,在一个成员函数内定义的每一个局部变量都应在它代码的所在行声明,并且应采用一个行内注释说明它的用法。

4. 难或复杂的代码。若发现不能或者没有时间重写代码,那么应将成员函数中的复杂代码详细地注释出来。一般性的经验法则是,如果代码并非显而易见的,则应说明。

5. 处理顺序。如果代码中有的语句必须在一个特定的顺序下执行,则应保证将这一点注释出来 [AMB98]。没有比下面更糟糕的事了:你对一段代码做一点简单的改动,却发现它不工作,于是花了几个小时查找问题,最后发现原来是搞错了代码的执行顺序。

在闭括号后加上注释。常常会发现你的控制结构内套了一个控制结构,而在这个控制结构内还套了一个控制结构。虽然应该尽量避免写出这样的代码,但有时你发现最好还是要这样写。问题是闭括号 } 应该属于哪一个控制结构这一点就变得混淆了。一个好消息是,有一些编辑器支持一种特性:当选用了一个开括号后,它会自动地使相应得闭括号高亮显示;一个坏消息是,并非所有的编辑器都支持这种属性。我发现通过将类似 //end if//end for//end switch,&这样的注释加在闭括号所在行的行后,可以使代码更易理解。

编写清晰整洁的代码的技巧

这一部分讲述几个技巧,这些技巧有助于区分专业软件开发者和蹩脚代码编写者。这些技巧是:

· 给代码加上注释

· 给代码分段

· 使用空白

· 遵循 30 秒条规则

· 说明消息发送的顺序

· 写短小单独的命令行

给代码加上注释

记住:如果你的代码不值得注释,那么它就不值得保留 [NAG95]。当正确地使用了本文提到的注释标准和方针,就可以大幅度地提高代码质量。

让代码分段/缩进

一种提高代码可读性的方法是给代码分段,换句话说,就是在代码块内让代码缩进。所有在括号{ 和} 之内的代码,构成一个块。基本思想是,块内的代码都应统一地缩进去一个单位。

Java 的约定似乎是开括号放在块的所有者所在行的后面,闭括号应缩进一级。在 [LAF97] 指出的很重要的一点是,你所在的机构应选取一个缩进风格并始终使用这种风格。采用与你的 Java 开发环境所生成的代码一样的缩进风格。

在代码中使用空白。

在 Java 代码中加入几个空行,也叫空白,将代码分为一些小的、容易理解的部分,可以使它更加可读。[VIS96] 建议采用一个空行来分隔代码的逻辑组,例如控制结构,采用两个空行来分隔成员函数定义。没有空白的代码很难读,很难理解。

遵循 30 秒条法则

其他的程序员应能在少于 30 秒钟的时间内完全理解你的成员函数,理解它做什么,为什么这样做,它是怎样做的。如果他们做不到,说明你的代码太难维护,应加以改进。30 秒钟,明明白白。 一个好的经验法则是:如果一个成员函数一个屏幕装不下,那么它就很可能太长了。

写短小单独的命令行

每一行代码只做一件事情。在依赖于穿孔卡片的计算机发展的早期,想让一行代码完成尽量多的功能的想法是可以理解的。若想在一行里做多件事情,就会使代码难于理解。为什么要这样呢?我们应使代码尽量容易理解,从而更容易维护和改进。正如同一个成员函数应该并且只能做一件事一样,一行代码也只应做一件事情。

此外,应让代码在一个屏幕内可见 [VIS96]。 也不应向右滚动编辑窗口来读取一整行代码,包括含有行内注释语句的代码。

说明运行顺序

提高代码可读性的一个相当简单的方法是使用圆括号 (parenthesis,又叫“round brackets”) 来说明 Java 代码运行的准确顺序 [NAG95];[AMB98]。如果为了理解你的源码而必须了解编程语言的操作顺序,那么这说明源码中一定有什么重要的东西做的不对。 这大多是在 AND 或者 OR 其它几个比较关系处产生的逻辑比较上的问题。注意:如果你象前文所建议的那样,采用短小单独的命令行,那么就不会产生这个问题。

 

字段标准 (字段/属性)

field 这个词在这里指的是字段,Beans Development Kit (BDK) 叫它“属性” [DES97]。字段是说明一个对象或者一个类的一段数据。字段可以是象字符串或者浮点数这样的基本数据类型,也可以是一个对象,例如一个消费者或者一个银行帐户。

命名字段

应采用完整的英文描述符来命名字段 [GOS96],[AMB98],以便使字段所表达的意思一目了然。象数组或者矢量这样是集合的字段,命名时应使用复数来表示它们代表多值。

示例:

firstName

zipCode

unitPrice

discountRate

orderItems

命名组件(部件)

应采用完整的英文描述符命名组件(接口部件),名字的后缀是组件类型名。这让你容易区分一个组件的目的和它的类型,容易在一个表里找到各个组件(许多可视化的编程环境在一个 Applet 程序或者一个应用程序中提供了一个所有组件的列表。如果所有名字都是类似于 button1button2, & 这样的话,很容易混淆)。

示例:

okButton

customerList

fileMenu

newFileMenuItem

命名组件的另一种方法。匈牙利符号

“匈牙利符号” [MCO93] 是基于字段应按照以下方法命名的原则:xEeeeeeEeeeee,其中 x 指组件类型,EeeeeEeeeee 是完整的英文描述符。

示例:

pbOk

lbCustomer

mFile

miNewFile

这个方法的主要优点是,这是一个通用于 C++ 代码中的工业标准,已经有许多人在遵守它。此外,开发者能快速地从变量的名字上来判断它的类型和用法。主要的缺点是,当有许多同一类型的部件时,前缀符号变得很笨重;而且,违背了采用完整的英文描述符的命名约定。

命名组件的另一种方法。匈牙利符号后缀

这基本上是其他两种方式的组合,生成的名字如okPbcustomerLbfileM 和newFileMi。主要优点是组件名说明了组件类型,并且同一类的组件不在一起,而按照字母顺序排列。主要的缺点仍是未采用完整的英文描述符,它偏离了规范,使标准难以被记住。

设定组件命名标准。无论使用哪种约定,都要生成一个“正式”部件名列表。 例如,当命名按钮时,是用Button 或是PushButtonb 或是pb?生成一个列表,让组里的每一个 Java 开发者都得到它。

命名常量

Java 中,常量,即不变的值,一般用类的静态常量字段来实现。公认的约定是,采用完整的英文大写单词,在词与词之间用下划线连接 [GOS96]。

示例:

MINIMUM_BALANCE

MAX_VALUE

DEFAULT_START_DATE

这个约定的主要优点是,它有助于区分常量和变量。在本文后面的章节中我们将看到,如果用定义获取函数返回常量值的方法来取代定义常量,代码的可适应性和可维护性都会大大提高。

命名集合

一个集合,例如数组和矢量,应采用复数命名来表示队列中存放的对象类型。命名应采用完整的英文描述符,名字中所有非开头的单词的第一个字母应大写。

示例:

customers

orderItems

aliases

这种约定的主要优点是有助于区分表示复数值(集合)和单值(非集合)的字段。

字段可见性

当字段被声明为protected 类型时,子类中的成员函数可能会直接访问它,有效地提高了类内层次结构的耦合性。这使类更难维护和加强,所以应该尽量避免。字段不应被直接访问,而应采用存取成员函数(参见下文)访问。

可见性

说明

正确用法

public

一个公共字段可被任何其他对象或者类中的成员函数访问。

不要让字段公有。

protected

被保护的字段可被它声明时所在的类及该类的子类的所有成员函数访问。

不要让字段被保护。

private

私有字段只可以被它声明时所在的类的其它成员函数调用,该类子类中的函数不可以调用。

所有的字段都应置为私有,由获取和设置成员函数(存取函数)访问。

对于那些非长期性的字段(它们不被永久保留),应将它们标注为static 或transient [DES97]。 使它们与 BDK 的约定一致。

不要“隐藏”名字

名字隐藏是指给局部变量、参数或者字段所取的名字,与另一个更大范围内定义的变量、参数或者字段的名字相同(或相似)。例如,如果把一个字段叫做 firstName ,就不要再生成一个局部变量或者参数叫做firstName,或者任何类似的名字,如 firstNames 或 fistName。名字隐藏会使代码难于理解,并容易产生问题。因为你或者其他开发者在修改代码时,会误读代码,而错误又很难发现。

注释一个字段

所有的字段都应很好地加以注释,以便其他开发者理解它。要想有效地注释,以下的部分需要说明:

1. 字段的说明。需说明一个字段,才能使人了解如何使用它。

2. 注释出所有采用的不变量。字段中的不变量是指永远为“真”的条件。例如,字段 dayOfMonth 的不变量可能是它的值只能在 1 到 31 之间(显然,可以用基于某一年里的某个月份来限制这个字段值,使其变的更加复杂)。通过说明字段值的限制条件,有助于定义重要的业务规则,使代码更易理解。

3. 示例。对于那些有复杂业务规则与之相关联的字段,应提供几个例子,使它们容易理解。一个例子常象一幅画:它抵得上几千个词语。

4. 并行事件。对众多程序开发者来说,并行性是一个新而复杂的概念;事实上,即使对有经验的并行程序开发者来说,并行性也是一个老但却复杂的课题。最终结果是,如果应用了 Java 的并行编程特性,那么你应在程序中详细地注释出来。

5. 可见性决策。如果声明了一个非私有字段,则应说明为什么要这样做。字段的可见性在上文中(第 3.2节“字段的可见性”)讨论了,支持封装的存取成员函数的用法将在下文(第 3.4 节“存取成员函数的使用”)中讨论。总的来说,最好能有一个好的理由解释为什么不将变量声明为私有类型。

使用存取成员函数

除了满足命名约定之外,适当地使用存取成员函数,即提供更新或访问字段值的成员函数,可以实现字段的可维护性。存取成员函数有两种:设置函数(也叫变化函数)和获取函数。设置函数修改变量的值,获取函数取到变量的值。

虽然存取成员函数往往会增加代码费用,但是现在 Java 编译器使用时已被优化,所以存取成员函数会增加代码费用这一点已不再正确。存取函数帮助隐藏了类的具体实现细节。一个变量仅能访问两个控制点:设置函数和获取函数。让需修改的点最小化,增加了类的可维护性。Java 代码的优化将在(第 7.3 节“优化 Java 代码”)中讨论。

你的机构能改进的最重要的标准之一是存取函数的使用。一些开发者不愿使用存取成员函数的原因是,他们不想多输入几个键(例如,对于一个获取函数,除了字段名之外,还必须输入 in, get 和())。最主要的是,采用存取函数后增加的可维护性和可扩展性,远远超过输入这些字符所做的工作。

存取函数是唯一可以访问字段的地方。正确使用存取成员函数的关键概念是:成员函数中,只有存取成员函数可以直接访问字段。的确,定义字段的类内的其它成员函数可能可以直接访问该私有字段,但是这样做会增加类内的耦合,所以不应这样。

为什么采用存取函数?

“好的程序设计试图将程序部件与不必要、未计划或者不需的外部影响分隔开来。访问修饰语句(存取函数)给编程语言控制这一类的接触提供了一种清晰并可检验的方法。”[KAN97]

存取成员函数通过以下方法提高类的可维护性:

1. 更新字段。.每个字段只有几个单点要更新,这使得修改和检测都很容易。换句话说,字段已被封装。

2. 获得字段的值。你完全控制着字段应怎样被访问以及被谁访问。

3. 获取常量名和类名。在获取函数中封装常量值和类名,当这些值或名字改变时,只需更新获取函数内的值,而并非常量或者名字被使用处的每一行代码。

4. 初始化字段。采用滞后初始化 (lazy initialization) 保证字段总能被初始化,并且只在需要时才初始化。

5. 减少类与子类之间的耦合。 当子类通过它们相应的存取成员函数访问被继承的字段时,它可以不影响它的任何子类,而只修改超类字段的实现方式,这样有效地减少了超类与子类之间的耦合。存取函数减少了那种一旦超类被修改就会波及子类的“脆弱基类”的风险。

6. 将变化封装到字段中。如果一个或者多个字段的业务规则变化了,可以只潜在地修改存取函数,就同样可以提供规则变化之前的功能。这一点使你很容易响应新的业务规则。

7. 简化并行事件。[LEA97] 指出,如果采用了基于字段值的 waits 语句,那么设置成员函数提供了一个位置可包含 notifyAll。这让转向并行解决方案更加容易。

8. 名字隐藏不再是一个大问题。虽然应该避免名字隐藏,即避免赋给局部变量一个与字段相同的名字,但是始终通过存取函数访问字段意味着可以给局部变量任何你想取的名字。不必担心字段名的隐藏,因为你无论如何都不会直接访问它们。

当不用存取函数时:唯一可能你不想用存取函数的时候是当执行时间最重要时。但是,这实际上很少见,因为应用程序耦合性的增加会平衡掉这样做之后赢得的好处。

命名存取函数

获取成员函数应在名字中加上 get + 字段名,除非字段表示的是一个布尔值(“真”或者“假”),这时获取函数名中应加上 is + 字段名。无论何种字段类型,设置成员函数应在名字中加上 set + 字段名[GOS96],[DES97]。注意字段名始终采用大小写混合,所有单词的第一个字母要大写。命名约定在 JDK 中被始终使用,在 beans development 中也必须使用。

Examples:

字段

类型

获取函数名

设置函数名

firstName

字符串

getFirstName()

setFirstName()

address

地址

对象

getAddress()

setAddress()

persistent

布尔值

isPersistent()

setPersistent()

customerNo

整型

getCustomerNo()

setCustomerNo()

orderItems

OrderItem

的对象数组

getOrderItems()

setOrderItems()

存取函数的高级技术

存取函数不仅仅局限在获取和设置实例的字段值时使用。这一节讨论如何将存取函数应用于以下方面,以提高代码的适应性:

· 初始化字段值

· 访问常量值

· 访问集合

· 同时访问几个字段

滞后初始化

在访问变量前需要将其初始化。 对于初始化有两种想法:当对象生成时初始化所有的变量(传统方法)或者在第一次使用变量时进行初始化。第一种方式在对象初次创建时调用特殊的成员函数,这些成员函数叫做构造函数。虽然这种方法可行,但是它被证明常常产生错误。当增加一个新的变量时,你很容易就会忘记更新构造函数(另一种称为滞后初始化的方法是,字段由它们的获取函数初始化。如下文所示(注意在获取函数内是如何采用一个设置函数的)。注意:成员函数检查支行个数是否为零,若是则将个数设置为适当的默认值。

/** 返回支行号,支行号

是整个帐号的最左边四位数字。

帐号的格式是 BBBBAAAAAA。

*/

protected int getBranchNumber()

{

if( branchNumber == 0)

{

// 默认支行号是 1000,

// 它是 Bedrock 城市中心的一个主要支行

setBranchNumber(1000);

}

return branchNumber;

}

对于在数据库中实际存放的是其它对象的字段,常采用滞后初始化。例如,当生成一个新的存货清单项时,不必从默认的数据库中获得存货项的类型。而仅仅是在第一次访问该项时,才需用滞后初始化方式设定它的值。这样当需要时,只需从数据库中读出存货项类型对象即可。这种方法对于那些有不常被访问的字段的对象有好处。如果你不打算用这些东西,为什么花精力从固定存取中获取它们呢?

只要获取函数采用了滞后初始化方式,就应该象上文例子那样说明为什么采用那个默认值。 这样做除去了代码中字段是如何被应用的那层神秘,使代码的可维护性和可扩展性都得到了提高。

常量存取函数

Java 中的代码模式是将常量值作为静态常量字段。这种方式对于“常量”是可以理解的,因为它们是固定的。例如,布尔类使用“”和“”这两个静态最终字段,它们代表这个类的两个实例。DAYS_IN_A_WEEK 这个常量的值可能永不会改变,这一点也可以理解。

但是,随时间流逝,许多事物“常量”因为业务规则的变化而发生变化。例如:Archon Bank of Cardassia (ABC) 一直坚持若要获取利息,一个帐户至少应有 $500 的余额。要实现这一点,我们可以在计算利息的成员函数的类 Account 中增加一个叫做 MINIMUM_BALANCE 的静态字段。这虽然可行,但却不灵活。如果业务规则变化为不同种类的帐户有不同的最小余额限制,比如说,储蓄帐户的最小余额为 $500 ,支票帐号的最小余额为 $200,那么又该怎么办呢?又如果业务规则变化为第一年要保持 $500 的最小余额,第二年要保持 $400 的最小余额,第三年要保持 $300 的最小余额,这又应该怎么办呢?要是规则变为夏季应有$500 ,但冬季应有 $250 呢?可能所有这些规则的组合在不久的将来就会采用。

要指出的一点是,将常量作为字段来使用不够灵活,一个好得多的办法是将常量作为获取函数来处理。上例中,采用一个叫做 getMinimumBalance() 的静态成员函数比一个叫做 MINIMUM_BALANCE 的静态字段要灵活得多,因为在成员函数中我们可以实现不同的业务规则,并针对不同的帐号生成不同的子类。

/** 得到帐号值。帐号号码的格式如下:

BBBBAAAAAA,BBBB 是支行号码,

AAAAAA 是支行帐号号码

*/

public long getAccountNumber()

{

return ( ( getBranchNumber() * 100000 ) + getBranchAccountNumber() );

}

/**

设定帐号号码。帐号号码的格式如下:

BBBBAAAAAA,BBBB 是支行号码,

AAAAAA 是支行帐号号码

*/

public void setAccountNumber(int newNumber)

{

setBranchAccountNumber( newNumber % 1000000 );

setBranchNumber( newNumber / 1000000 );

}

常量获取函数的另一个优点是,它们有助于提高代码的一致性。考虑上述代码,它们不能正常工作。一个帐户号码是支行号和支行帐号号码的结合。测试我们的代码,我们发现设置成员函数 setAccountNumber()不能正确更新支行帐号(它取了最左边的三位数,而不是四位)。那是因为我们采用了 1,000,000,而不是100,000 来提取字段 branchAccountNumber。若如下面所示,对这个值采用一个单独的来源,即常量获取函数 getAccountNumberDivisor(),我们的代码将更一致,并能正常工作。

/**

返回要求的除数,用来将整个帐户号分割

为支行号和支行帐户号。

整个帐号的格式是 BBBBAAAAAA。

*/

public int getAccountNumberDivisor()

{

return ( (long) 1000000);

}

/**

得到帐号值。帐号号码的格式如下:

BBBBAAAAAA,BBBB 是支行号码,

AAAAAA 是支行帐号号码

*/

public long getAccountNumber()

{

return ( ( getBranchNumber() * getAccountNumberDivisor() ) *getBranchAccountNumber() );

}

/**

设定帐号号码。帐号号码的格式如下:

BBBBAAAAAA,BBBB 是支行号码,

AAAAAA 是支行帐号号码

*/

public void setAccountNumber(int newNumber)

{

setBranchAccountNumber( newNumber % getAccountNumberDivisor() );

setBranchNumber( newNumber / getAccountNumberDivisor() );

}

通过对常量使用获取函数,我们减少了代码出现问题的可能性,同时,提高了系统的可维护性。当帐号的格式变化时,我们知道它肯定会变化的,我们的代码很容易修改,因为它既有隐含的也有集中的供我们构造或分解帐号的必须信息。转载请注明出处:http://www.youxijishu.com/h-nd-143-2_523.html#module12

更多游戏技术资料请参照:http://www.youxijishu.com

转载于:https://www.cnblogs.com/youxijishu/p/6046527.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值