Java编程规范指南

上传人:痛*** 文档编号:181875449 上传时间:2023-01-18 格式:DOC 页数:53 大小:629KB
返回 下载 相关 举报
Java编程规范指南_第1页
第1页 / 共53页
Java编程规范指南_第2页
第2页 / 共53页
Java编程规范指南_第3页
第3页 / 共53页
点击查看更多>>
资源描述
Java 编程指南目录简介 6最根本的原则:6程序设计标准 6命名约定 6注释约定 7成员函数标准 10命名成员函数 10命名存取成员函数 11获取函数11获取函数的另一种命名约定。Has 和 Can11设置函数 12命名构造函数 12成员函数的可见性 12注释成员函数 13成员函数的函数头13内部注释 15编写清晰整洁的代码的技巧 16给代码加上注释16让代码分段/缩进16遵循 30 秒条法则17写短小单独的命令行17说明运行顺序17字段标准(字段/属性) 17命名字段 18命名组件(部件) 18命名常量 19命名集合 19字段可见性 20不要“隐藏”名字20注释一个字段 20使用存取成员函数 21为什么使用存取函数? 22命名存取函数 22存取函数的高级技术23存取函数的可见性 28一定要初始化静态字段 28局部变量标准 28命名局部变量29命名流 29命名循环计数器 29命名异常对象 29声明并注释局部变量 29关于声明的一般注释30成员函数的参数标准 30命名参数 30注释参数 31类、接口、包和编译单元的标准 31类的标准32命名类 32注释类 32类的声明 33将公共和保护接口最小化 34接口标准 34命名接口 34注释接口 35包的标准 35命名包 35注释包 36编译单元标准 36命名编译单元 36注释编译单元 37错误处理和异常 37其他标准和版本 38复用38导入类 39优化 Java 代码 39编写 Java 测试集 40成功的模式 40有效地使用这些标准 41其它导向成功代码的因素 41总结 43Java 命名约定 43Java 注释约定 45Java 注释类型 45注释哪些部分 46Java 程序设计约定 (一般) 48参考文献 50词汇表 51简介 本文提供一整套编写高效可靠的 Java 代码的标准、约定和指南。它们以安全可靠的软件工程原则为基础,使代码易于理解、维护和增强。而且,通过遵循这些程序设计标准,你作为一个 Java 软件开发者的生产效率会有显著提高。经验证明,若从一开始就花时间编写高质量的代码,则在软件开发阶段,对代码的修改要容易很多。最后,遵循一套通用的程序设计标准将带来更大的一致性,使软件开发团队的效率明显提高。最根本的原则:运用常识。当找不到任何规则或指导方针,当规则明显不能适用,当所有的方法都失效的时侯: 运用常识并核实这些基本原则。这条规则比其它所有规则都重要。常识是必不可少的。程序设计标准 Java 的程序设计标准很重要,原因在于它将提高开发团队各成员的代码的一致性。一致性的提高会使代码更易理解,这意味着它更易开发和维护。从而降低了应用程序的总开发成本。你必须牢记的是:你的 Java 代码在你已离开并开始另一个项目之后,会保留相当长的一端时间。因此开发过程中一个很重要的目标就是要确保在开发成员或开发团队之间的工作可以顺利交接,不必花很大的力气便能理解已编写的代码,以便继续维护和改进以前的工作。如果代码难以理解,很有可能被废弃和重写。命名约定 我们将在整个标准中讨论命名约定,所以让我们先讨论几个基本点: 1. 使用可以准确说明变量/字段/类的完整的英文描述符。例如,采用类似 firstName,grandTotal 或 CorporateCustomer 这样的名字。虽然象 x1,y1 或 fn 这样的名字很简短,输入起来容易,但是我们难以知道它们代表什么、结果是什么含义,因而使代码难以理解、维护和改进。 2. 采用该领域的术语。如果用户称他们的“客户” (clients) 为“顾客” (customers),那么就采用术语 Customer 来命名这个类,而不用 Client。许多程序开发者会犯的一个错误是,不去使用工业或领域里已经存在着很完美的术语时,却生造出一些普通词汇。 3. 采用大小写混合,提高名字的可读性。一般应该采用小写字母,但是类和接口的名字的首字母,以及任何中间单词的首字母应该大写 KAN97。 强制:类接口名首字大写,常量大写,其他首字小写。4. 尽量少用缩写,但如果一定要使用,就要谨慎地使用。这意味着应该保留一个标准缩写的列表,明智地从中选取,并且在使用时保持一致。例如,想对单词“number”采用缩写,那么可从 nbr,no 或者 num 中选取一个,说明一下采用了哪一个(具体是哪个倒无所谓),并且只使用这一种形式。 5. 避免使用长名字(最好不超过 15 个字母)。虽然 PhysicalOrVirtualProductOrService 看起来似乎是个不错的类名,但是这个名字太长了,应该考虑重新给它起个短一点的名字,比如象 Offering。 6. 避免使用相似或者仅在大小写上有区别的名字。例如,不应同时使用变量名 persistentObject 和 persistentObjects,以及 anSqlDatabase 和 anSQLDatabase。 7. 避免使用下划线作为名字的首末字母。以下划线为首末字母的名字通常为系统保留,除预处理定义之外,一般不用作用户命名。更重要的是,下划线经常造成麻烦而且难输入,所以尽量避免使用。 强制:首尾不使用下划线提示:尽量不使用下划线注释约定 我们还会对注释约定进行讨论,所以,我们先谈谈一些基本点: 基本要求:时间,作者,参数有业务含义需注明1. 注释应该增加代码的清晰度。代码注释的目的是要使代码更易于被同时参与程序设计的开发人员以及其他后继开发人员理解。 2. 如果你的程序不值得注释,那么它也很可能也不值得运行 NAG95。 3. 避免使用装饰性内容,也就是说,不要使用象广告横幅那样的注释语句。二十世纪六十年代和七十年代,COBOL 程序员们养成了画框的习惯,典型的是用星号将他们的内部注释圈起来。当然,这给他们的艺术创造欲一个发泄方式,但是坦白地说,这只是在大量浪费时间,并不能给最终的产品增加丝毫价值。要写的是清晰的代码,不是外表可爱的代码。此外,由于有些字体的显示和打印是成比例的,但有些又不是,所以无法将那些框排整齐。 4. 保持注释的简洁。最好的注释应该是简单明了的注释。注释不必洋洋洒洒,只需提供足够的信息,使别人能够理解你的代码。 5. 先写注释,后写代码。写代码注释的最好方法是在写代码之前就写注释。这使你在写代码之前可以想想代码的功能和运行。而且这样确保不会遗漏注释。另一种方法是边写代码边写注释。因为注释可以使代码更易理解,所以在程序开发的过程中,也可以利用这一点。如果打算花些时间写注释,那么至少你应从这个过程中获得些什么 AMB98 。 6. 注释信息不仅要包括代码的功能,还应给出原因。例如,下面例 1 中的代码显示金额在 $1,000 以上(包括 $1,000)的定单可给予 5% 的折扣。为什么要这样做呢?难道有一个商业法则规定大额定单可以得到折扣吗?这种给大额定单的特殊是有时限的呢,还是一直都这样?最初的程序设计者是否只是由于慷慨大度才这样做呢?除非它们在某个地方(或者是在源代码本身,或者是在一个外部文档里)被注释出来,否则你不可能知道这些。 例 1.1if (grandTotal = 1000.00)grandTotal = grandTotal * 0.95;Java 注释语句类型 Java 有三种注释语句风格:以 /* 开始, */ 结束的文档注释,以 /* 开始,以 */ 结束的C语言风格注释,以及以 / 开始,代码行末尾结束的单行注释。下表是对各类注释语句建议用法的一个概括,也给出了几个例子。注释语句类型用法示例文档注释在接口、类、成员函数和字段声明之前紧靠它们的位置用文档注释进行说明。文档注释由 javadoc 处理,为一个类生成外部注释文档,如下所示。/* Customer(顾客)顾客是指作为我们的服务及产品的销售对象的任何个人或组织。author S.W. Ambler*/C 语言风格注释采用 C 语言风格的注释语句将无用的代码注释掉。保留这些代码是因为用户可能改变想法,或者只是想在调试中暂时不执行这些代码。/* 这部分代码已被它前面的代码替代,所以于 1999 年6 月 4 日被 B. Gustafsson 注释掉。如果两年之后仍未用这些代码,将其删除。. . . (源代码)*/单行注释在成员函数内部采用单行注释语句对业务逻辑、代码片段和临时变量声明进行说明。/ 因为让利活动 / 从 1995 年 2 月开始,/ 所以给所有超过 $1000 的/ 发货单 5% 的折扣。一件很重要的事情是,你的机构应该制订一套如何使用 C 语言风格注释和单行注释的标准,并始终严格遵守。使用一种注释方式来说明业务逻辑,使用另一种方式注释掉旧的代码。业务逻辑采用单行注释,因为这样可以将注释和代码放在同一行(这又叫做“内联”)。采用 C 语言风格的注释屏蔽掉旧的代码,因为这样可以同时注释掉数行。C 语言风格注释看起来很象文档注释,所以为了防止混淆,不应在别处使用。注意行末注释。MCO93 强烈反对采用行内注释,即在一行的末尾加上注释。他指出,这种注释必须在代码的右端对齐,这样才能避免代码结构看起来混乱。结果,这些注释的格式难以划一。“如果你使用了很多这样的注释,则要花时间去将它们排列整齐。这些时间并没有花在更多地了解代码上,而完全花在了敲击空格键和制表符这种冗长乏味的工作上。”他又指出,行末注释也难以维护。因为当该行程序的代码加长时,它们会将这些注释挤出该行,如果你将它们排齐了,你不得不对余下的注释做同样的工作。(我们无所谓)快速浏览 javadoc Sun 公司的 Java Development Kit (JDK) 中有一个名为 javadoc 的程序。它可以处理 Java 的源代码文件,并且为 Java 程序产生 HTML 文件形式的外部注释文档。Javadoc 支持一定数目的标记,标识注释文档中各段起始位置的保留字。详情请参考 JDK javadoc 文档。标记用于目的author name类、 接口说明特定某一段程序代码的作者。每一个作者各有一个标记。deprecated类、 成员函数说明该类的应用程序编程接口 (API) 已被废弃,因此应不再使用。exception name description成员函数说明由成员函数发出的异常。一个异常采用一个标记,并要给出异常的完整类名。param name description成员函数用来说明传递给一个成员函数的参数,其中包括参数的类型/类和用法。每个参数各有一个标记。return description成员函数若成员函数有返回值,对该返回值进行说明。应说明返回值的类型/类和可能的用途。since类、成员函数说明自从有 JDK 1.1 以来,该项已存在了多长时间。see ClassName类、接口、成员函数、字段在文档中生成指向特定类的超文本链接。可以并且应该采用完全合法的类名。see ClassName#member functionName类、接口、成员函数、字段在文档中生成指向特定成员函数的超文本链接。可以并且应该采用完全合法的类名。version text类、接口说明特定一段代码的版本信息。你注释代码的方式很大地影响着你的工作效率以及所有维护改进代码的后继开发者的工作效率。在软件开发过程中及早注释代码,会促使你在开始撰写代码之前仔细考虑这些代码,从而带来更高的工作效率。而且,当你重新阅读数天前或者数星期前所写的代码时,你可以很容易地判断出当时你是怎么想的,因为这一切都有记录。成员函数标准 切记:你今天所写的代码可能在今后的数年里仍在使用,而且很有可能由其他人来维护和改进。应尽可能使你的代码“整洁”易懂,因为这会使代码易于维护和改进。命名成员函数 成员函数的命名应采用完整的英文描述符,大小写混合使用:所有中间单词的第一个字母大写。成员函数名称的第一个单词常常采用一个有强烈动作色彩的动词。示例:openAccount()printMailingLabel()save()delete()这种约定常常使人一看到成员函数的名称就能判断它的功能。虽然这种约定要使开发者多做一些输入的工作,因为函数名常常较长,但是回报是提高代码的可理解性。命名存取成员函数 在后续章节中,我们将更详细地讨论获取和存放字段值(字段/属性)的存取成员函数。下面将概括一下存取函数的命名约定。获取函数获取函数作为一个成员函数,返回一个字段的值。除了布尔字段之外,应采用 get 作为字段的前缀;布尔字段采用 is 作为前缀。示例:getFirstName()getAccountNumber()isPersistent()isAtEnd()遵循这个命名约定,显然,成员函数将返回对象的字段,布尔型的获取函数将返回布尔值“真”或者“假”。这个标准的另一个优点是:它遵循 beans development kit (BDK) 对获取成员函数采用的命名约定 DES97。它的一个主要的缺点是 get 是多余的,需要额外的录入工作。获取函数的另一种命名约定。Has 和 Can基于正规英文约定的一个可行的取代方法是,用 has 或者 can 来代替布尔型获取函数的 is 前缀。例如,形如 hasDependents() 和 canPrint() 的获取函数,读起来就发现它们意义更加明确。这种方法存在的问题是 BDK 目前还不支持这种命名方法。可以将 isBurdenedWithDependents() 和 isPrintable() 这些成员函数重新命名。设置函数 设置函数,也叫变值函数,是可以修改一个字段值的成员函数。无论何种字段类型,都要在字段名的前面加上 set 前缀。示例:setFirstName(String aName)setAccountNumber(int anAccountNumber)setReasonableGoals(Vector newGoals)setPersistent(boolean isPersistent)setAtEnd(boolean isAtEnd)按照这种命名约定,显然是一个成员函数设定一个对象的字段值。这个标准的另一个优点是:它遵循 beans development kit (BDK) 对设置函数采用的命名约定 DES97。它的一个主要的缺点是 set 是多余的,需要额外的录入。命名构造函数 构造函数是在一个对象初次生成时,完成所有必需的初始化的成员函数。构造函数与它所属类的名字总是相同的。例如,类 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,以便使字段所表达的意思一目了然。象数组或者矢量这样是集合的字段,命名时应使用复数来表示它们代表多值。示例:firstNamezipCodeunitPricediscountRateorderItems命名组件(部件) 应采用完整的英文描述符命名组件(接口部件),名字的后缀是组件类型名。这让你容易区分一个组件的目的和它的类型,容易在一个表里找到各个组件(许多可视化的编程环境在一个 Applet 程序或者一个应用程序中提供了一个所有组件的列表。如果所有名字都是类似于 button1, button2, & 这样的话,很容易混淆)。示例:okButtoncustomerListfileMenunewFileMenuItem命名组件的另一种方法。匈牙利符号“匈牙利符号” MCO93 是基于字段应按照以下方法命名的原则:xEeeeeeEeeeee,其中 x 指组件类型,EeeeeEeeeee 是完整的英文描述符。示例:pbOklbCustomermFilemiNewFile这个方法的主要优点是,这是一个通用于 C+ 代码中的工业标准,已经有许多人在遵守它。此外,开发者能快速地从变量的名字上来判断它的类型和用法。主要的缺点是,当有许多同一类型的部件时,前缀符号变得很笨重;而且,违背了采用完整的英文描述符的命名约定。命名组件的另一种方法。匈牙利符号后缀这基本上是其他两种方式的组合,生成的名字如 okPb,customerLb,fileM 和 newFileMi。主要优点是组件名说明了组件类型,并且同一类的组件不在一起,而按照字母顺序排列。主要的缺点仍是未采用完整的英文描述符,它偏离了规范,使标准难以被记住。设定组件命名标准。无论使用哪种约定,都要生成一个“正式”部件名列表。例如,当命名按钮时,是用 Button 或是 PushButton,b 或是 pb?生成一个列表,让组里的每一个 Java 开发者都得到它。命名常量 Java 中,常量,即不变的值,一般用类的静态常量字段来实现。公认的约定是,采用完整的英文大写单词,在词与词之间用下划线连接 GOS96。示例:MINIMUM_BALANCEMAX_VALUEDEFAULT_START_DATE这个约定的主要优点是,它有助于区分常量和变量。在本文后面的章节中我们将看到,如果用定义获取函数返回常量值的方法来取代定义常量,代码的可适应性和可维护性都会大大提高。命名集合 一个集合,例如数组和矢量,应采用复数命名来表示队列中存放的对象类型。命名应采用完整的英文描述符,名字中所有非开头的单词的第一个字母应大写。示例:customersorderItemsaliases这种约定的主要优点是有助于区分表示复数值(集合)和单值(非集合)的字段。字段可见性 当字段被声明为 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() );通过对常量使用获取函数,我们减少了代码出现问题的可能性,同时,提高了系统的可维护性。当帐号的格式变化时,我们知道它肯定会变化的,我们的代码很容易修改,因为它既有隐含的也有集中的供我们构造或分解帐号的必须信息。集合存取函数 存取函数的主要目的是将访问封装到字段,以减少代码的耦合。集合,如数组和矢量,要比单值复杂,实现起来自然不只是需要获取和设置成员函数。特别是因为要对集合进行增减,所以需使用存取成员函数。在集合字段的适当处加入如下存取成员函数:成员函数类型命名约定示例集合获取函数getCollection() getOrderItems() 集合设置函数setCollection() setOrderItems() 在集合中插入一个对象insertObject() insertOrderItem() 从集合中删除一个对象deleteObject() deleteOrderItem() 生成并且插入一个新对象到集合中newObject() newOrderItem() 这种方法的优点是集合被完全封装了,允许你以后用另外一个结构,可能是链表或是 B 树来取代它。同时访问几个字段 存取成员函数的一个优点是,它使你能有效地执行业务规则。考虑如下一个有关形状 (Shape) 的类的层次结构。Shape 的每一个子类通过 xPosition 和 yPosition 这两个字段表示位置,并且可以通过调用成员函数 move(Float xMovement, Float yMovement) 在屏幕上的二维坐标下移动。为达到我们的目的,图形在任何时刻都不可以只在一个坐标轴方向上移动,而应同时沿 x 和 y 轴移动(成员函数 move() 的两个参数中的任何一个参数都可以是 0.0)。这就意味着 move() 成员函数应该是公有的,但是 setXPosition() 和 setYPosition() 应该是私有的,被 move() 成员函数正确调用。另一个实现方法是,引入一个可以同时更新两个字段的设置成员函数,如下文所示。成员函数 setXPosition() 和 setYPosition() 应该仍然是私有的,这样它们不会被外部类和子类直接调用(要加入一些如下文所示的注释来说明它们不应被直接调用)。/* 设定图形位置 */protected void setPosition(Float x, Float y)setXPosition(x);setYPosition(y);/* 设置 x 坐标。重要:调用 setPosition(),不是这个成员函数。*/private void setXPosition(Float x)xPosition = x;/* 设置图形的 y 坐标 重要:调用 setPosition(),不是这个成员函数。*/private void setYPosition(Float y)yPosition = y;存取函数的可见性 尽可能地让字段成为被保护 (protected) 类型,这样只有子类可以访问它们。仅当一个外部类需要访问一个字段时,才将相应的获取函数或设置函数置为公有。注意:获取函数是公有而设置函数是私有的情况经常发生。有时需要将设置函数设为私有以保证某个常量不变。例如,Order 类可能含有一个字段表示 OrderItem 实例的集合,含有另一个叫 orderTotal 的字段表示整个定单 (order) 的总和。orderTotal 是一个表示订购项目子类总和的有用字段。唯一可以更新 orderTotal 值的成员函数是那些处理订购项目集合的函数。假设那些成员函数都
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 管理文书 > 施工组织


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!