收藏 分享(赏)

代码编写规范.docx

上传人:cjc2202537 文档编号:4516574 上传时间:2018-12-31 格式:DOCX 页数:21 大小:109.84KB
下载 相关 举报
代码编写规范.docx_第1页
第1页 / 共21页
代码编写规范.docx_第2页
第2页 / 共21页
代码编写规范.docx_第3页
第3页 / 共21页
代码编写规范.docx_第4页
第4页 / 共21页
代码编写规范.docx_第5页
第5页 / 共21页
点击查看更多>>
资源描述

1、知识管理系统代码编写规范一、介绍本文档为知识管理系统代码编写规范,为保证代码风格的一致性和后期的可维护性,文档讲述的内容要求所有开发人员必须遵守。本规范主要参考了 Google Java Style,包括了其他一些业界约定俗成的公约和普遍采用的标准。本规范并非最终标准,一些规定还需再做商讨。1.1 术语说明本文档除非特殊说明,否则:1. 类(class)统指普通类、枚举类、接口和注解类型。2. 注释(comment)只用来指实现注释(implementation comments) 。我们不使用“文档注释”这样的说法,而会直接说 Javadoc。其他“术语说明” ,将在文档中需要说明的地方单独

2、说明。1.2 文档说明本文档中的代码并不一定符合所有规范。即使这些代码遵循本规范,但这不是唯一的代码方式。例子中可选的格式风格也不应该作为强制执行的规范。二、源码文件基础2.1 文件名源文件以其最顶层的类名来命名,大小写敏感,文件扩展名为.java。2.2 文件编码:UTF-8源码文件使用 UTF-8 编码。2.3 特殊字符2.3.1 空格字符除了换行符外,ASCII 水平空白字符(0x20)是源码文件中唯一支持的空格字符。这意味着:1. 其他空白字符将被转义。2. Tab 字符不被用作缩进控制。2.3.2 特殊转义字符串任何需要转义字符串表示的字符(例如b, t, n, f, r, “, 和

3、 等),采用这种转义字符串的方式表示,而不采用对应字符的八进制数(例如 012)或 Unicode 码(例如 u000a)表示。2.3.3 非 ASCII 字符对于其余非 ASCII 字符,直接使用 Unicode 字符(例如 ),或者对应的Unicode 码(例如 u221e)转义都是允许的。唯一需要考虑的是,何种方式更能使代码容易阅读和理解。注意:在使用 Unicode 码转义,或者甚至是有时直接使用 Unicode 字符的时候,添加一点说明注释将对别人读懂代码很有帮助。三、源码文件结构源码文件按照先后顺序,由以下几部分组成:1. license 或者 copyright 声明信息。 (如

4、果需要声明)2. 包(package)声明语句。3. import 语句。4. 类声明(每个源码文件只能有一个顶级类) 。每个部分之间应该只有一行空行作为间隔。3.1 license 或者 copyright 的声明信息。如果需要声明 license 或 copyright 信息,应该在文件开始时声明。3.2 包声明包声明的行没有行长度的限制。单行长度限制不适用于包声明。3.3 import 语句3.3.1 不使用通配符 import即,不要出现类似这样的 import 语句:import java.util.*;3.3.2 没有行长度限制import 语句的行没有行长度的限制。单行长度限制不

5、适用于 import 语句所在行。3.3.3 顺序和空行import 语句应该被分为几个组,每个组之间由单行的空行隔开。分组的顺序如下:1. 所有的静态导入为归为一组。2. com.sinosoft(项目自带包)包的 import 归为一组。3. 第三方包。每个顶级包归为一组。第三方包之间按 ASCII 码排序。例如:android, com, junit,org, sun4. java 包归为一组。5. javax 包归为一组。同一组内的 import 语句之间不应用空行隔开。同一组中的 import 语句按 ASCII码排序。3.4 类声明3.4.1 只声明一个顶级类每个源码文件中只能有一

6、个顶级类。例外:package-info.java,该文件中可没有 package-info 类。3.4.2 类成员顺序类成员的顺序对代码的易读性有很大影响,但这也不存在唯一的通用法则。不同的类可能有不同的排序方式。重要的是,每个类都要按照一定的逻辑规律排序。维护者应该要能解释这种排序逻辑。比如, 新的方法不能总是习惯性地添加到类的结尾,因为这样就是按时间顺序而非某种逻辑来排序的。3.4.2.1 重载方法:不应该分开当一个类有多个构造函数,或者多个同名成员方法时,这些函数应该写在一起,不应该被其他成员分开。四、格式术语说明:块状结构(block-like construct)指类、成员函数和构

7、造函数的实现部分(大括号中间部分)。注意,在后面的 4.8.3.1 节中讲到数组初始化,所有的数组初始化都可以被认为是一个块状结构(非强制)。4.1 大括号4.1.1 大括号不可省略大括号一般用在 if, else, for, do 和 while 等语句。即使当它的实现为空或者只有一句话时,也需要使用。4.1.2 非空语句块采用 K 6. catch (ProblemException e) 7. recover();8. 9. 10. 11.;一些例外的情况,将在 4.8.1 节讲枚举类型的时候讲到。4.1.3 空语句块:可以用简洁版本一个空的语句块,大括号可以简洁地写成,不需要换行。如果

8、它是一个多块语句的一部分(if/else 或 try/catch/finally) ,即使大括号内没内容,右大括号也要换行。例子:1. void doNothing() 4.2 语句块的缩进:4 空格每当一个新的语句块产生,缩进就增加两个空格。当这个语句块结束时,缩进恢复到上一层级的缩进格数。缩进要求对整个语句块中的代码和注释都适用。(例子可参考之前 4.1.2 节中的例子)。4.3 一行最多只有一句代码每句代码的结束都需要换行。4.4 行长度限制:80 或 100不同的项目可以选择采用 80 个字符或者 100 个字符作为限制。除了以下几个特殊情况外,其他代码内容都需要遵守这个长度限制。这在

9、 4.5 节会有详细解释。例外: 1. 按照行长度限制,无法实现地方(例如:Javadoc 中超长的 URL 地址, 或者一个超长的 JSNI 方法的引用); 2. package 和 import 语句不受长度限制。(见 3.2、3.3 节); 3. 注释中的命令行指令行,将被直接复制到 shell 中执行的。4.5 换行术语说明:当一行代码按照其他规范都合法,只是为了避免超出行长度限制而换行时,称为长行断行。长行断行,没有一个适合所有场景的全面、确定的规范。但很多相同的情况,我们经常使用一些行之有效的断行方法。注意:将长行封装为函数,或者使用局部变量的方法,也可以解决一些超出行长度限制的情

10、况。并非一定要断行。4.5.1 在何处断行断行的主要原则是:选择在更高一级的语法逻辑的地方断行。其他一些原则如下: 1. 在一个逗号后面断开。2. 在一个操作符前面断开 (= 号和 foreach 语句的冒号除外)。3. 在调用函数或者构造函数需要断行时,与函数名相连的左括号要在一行。也就是在左括号之后断行。 4.5.2 断行的缩进:至少 8 个字符当断行之后,在第一行之后的行,我们叫做延续行。每一个延续行在第一行的基础上至少缩进四个字符。 当原行之后有多个延续行的情况,缩进可以大于 8 个字符。如果多个延续行之间由同样的语法元素断行,它们可以采用相同的缩进。4.6.3 节介绍水平对齐中,解决

11、了使用多个空格与之前行缩进对齐的问题。4.6 空白4.6.1 垂直空白以下情况需使用一个空行:1. 类成员之间需要空行隔开:字段、构造函数、方法、内部类、静态初始化语句块(static initializers) 、实例初始化语句块( instance initializers) 。 o 例外:连续字段之间的空白行不是必需的。一般多个字段中间的空行,是为了对字段做逻辑上的分组。2. 在函数体内,语句的逻辑分组间使用空行。3. 类的第一个成员之前,或者最后一个成员结束之后,用空行间隔。 (可选)4. 本文档中其他部分介绍的需要空行的情况。 (例如 3.3 节中的 import 语句)单空行时使用

12、多行空行是允许的,但是不要求也不鼓励。4.6.2 水平空白除了语法和规范的其他规则,词语分隔、注释和 Javadoc 外,水平的 ASCII 空格只在以下情况出现:1. 所有保留的关键字与紧接它之后的位于同一行的左括号(()之间需要用空格隔开。(例如 if、for、catch)2. 所有保留的关键字与在它之前的右大括号()之间需要空格隔开。 (例如else、catch)3. 在左大括号()之前都需要空格隔开。只有两种例外: o SomeAnnotation(a, b)o String x = “foo“;4. 所有的二元运算符和三元运算符的两边,都需要空格隔开。一元操作符和操作数之间不应该加空

13、格,比如:负号(“- ”),自增( “+”)和自减(“-”) 。例:i+;5. 逗号、冒号、分号和右括号之后。6. 如果在一条语句后做注释,则双斜杠(/)两边都要空格。这里可以允许多个空格,但没有必要。7. 变量声明时,变量类型和变量名之间需要用空格隔开:List list。8. 初始化一个数组时,大括号之间可以用空格隔开,也可以不使用。 (例如:int 5, 6 和 new int 5, 6 都可以)注意:这一原则并不要求或禁止一行开始或者结束时的空格。只针对行内部字符之间的隔开。4.6.3 水平对齐:不做强制要求术语说明:水平对齐,是指通过添加多个空格,使本行的某一符号与上一行的某一符号上

14、下对齐。这种对齐是允许的,但是不会做强制要求。以下是没有水平对齐和水平对齐的例子:1. private int x; / this is fine2. private Color color; / this too3.4. private int x; / permitted, but future edits5. private Color color; / may leave it unaligned注意:水平对齐能够增加代码的可读性,但是增加了未来维护代码的难度。考虑到维护时只需要改变一行代码,之前的对齐可以不需要改动。为了对齐,你更有可能改了一行代码,同时需要更改附近的好几行代码,而这

15、几行代码的改动,可能又会引起一些为了保持对齐的代码改动。这种改动,在最坏的情况下可能会导致大量的无意义的工作,即使在最好的情况下,也会影响版本历史信息,减慢代码 review 的速度,引起更多 merge 代码冲突的情况。4.7 分组括号:建议使用除非作者和代码审核者都认为去掉小括号也不会使代码被误解,或是去掉小括号能让代码更易于阅读,否则我们不应该去掉小括号。我们没有理由假设读者能记住整个 Java 运算符优先级表。4.8 特殊结构4.8.1 枚举类型枚举常量间用逗号隔开,换行可选。没有方法和文档的枚举类可写成数组初始化的格式:例子:1. private enum Suit CLUBS, H

16、EARTS, SPADES, DIAMONDS 枚举类型也是一个类(class),因此类的其他格式要求,也适用于枚举类型。4.8.2 变量声明4.8.2.1 每次声明一个变量不要使用组合声明。例如:int a, b;4.8.2.2 当需要时才声明,尽快完成初始化局部变量不应该习惯性地放在语句块的开始处声明,而应该尽量离它第一次使用的地方最近的地方声明,以减小它们的使用范围。 局部变量应该在声明的时候就进行初始化。如果不能在声明时初始化,也应该尽快完成初始化。4.8.3 数组4.8.3.1 数组初始化:可写成块状结构所有数组的初始化,都可以采用和块代码相同的格式处理。例如以下格式都是允许的:1.

17、 new int 2. 0, 1, 2, 33. 1. new int 2. 0,3. 1,4. 2,5. 36. 1. new int 2. 0, 1,3. 2, 34. 1. new int2. 0, 1, 2, 34.8.3.2 不能使用 C 风格的方式声明数组方括号应该是变量类型的一部分,因此不应该和变量名放在一起。例如:应该是 String args,而不是 String args。4.8.4 switch 语句术语说明:switch 语句是指在 switch 大括号中,包含的一组或多组语句块。每组语句块都由一个或多个 switch 标签(case FOO:或者 default:)打

18、头。4.8.4.1 缩进和其他语句块一样,switch 大括号之后缩进 4 个字符。 每个 switch 标签之后,新起一行,再缩进 4 个字符,后面跟着一条或多条语句。在标签结束后,恢复到之前的缩进,类似大括号结束。4.8.4.2 fall-through 注释在 switch 语句中,每个标签对应的代码执行完后,要么通过break、 continue、return 或抛出异常来终止,要么通过注释说明代码将继续执行下一个标签的代码。任何能表达这个意思的注释都可以(典型的是使用 / fall through)。这个注释在最后一个标签之后不需要注释。例如:1. switch (input) 2.

19、 case 1:3. case 2:4. prepareOneOrTwo();5. / fall through6. case 3:7. handleOneTwoOrThree();8. break;9. default:10. handleLargeNumber(input);11.4.8.4.3 default 标签需要显式声明每个 switch 语句中,都需要显式声明 default 标签,即使它没有任何代码。4.8.5 注解(Annotations )注解应用到类、函数或者构造函数时,应紧接 Javadoc 之后。注解独占一行。 这里换行不属于长行换行(第 4.5 节,长行换行),因此

20、缩进级别不变。例如:1. Override2. Nullable3. public String getNameIfPresent() . 例外: 如果注解只有一个,并且不带参数。则它可以和类或方法名放在同一行。例如:1. Override public int hashCode() . 注解应用到字段时,也是紧接 Javadoc 之后。不同的是,多个注解可以放在同一行。例如:1. Partial Mock DataLoader loader;对于参数或者局部变量使用注解的情况,没有特定的规范。4.8.6 注释4.8.6.1 语句块的注释风格注释的缩进与它所注释的代码缩进相同。可以采用/* .

21、 */进行注释,也可以用/ .进行注释。当使用 /* . */进行多行注释时,每一行都应该以 * 开始, 并且 * 应该上下对齐。 注意文字和注释符之间有一个空格(4.6.2 水平空白)。例如:1. /*2. * This is / And so /* Or you can3. * okay. / is this. * even do this. */4. */提示:多行注释时,如果你希望集成开发环境能自动对齐注释,你应该使用 /* . */,/ .一般不会自动对齐。4.8.7 修饰符多个类和字段的修饰符,按 Java Language Specification 中介绍的先后顺序排序。具体是

22、:1. public protected private abstract static final transient volatile synchronized native strictfp4.8.8 数字型的字面值long 类型的字面值使用大写 L为后缀,永远不要使用小写 l(避免和 1混淆)。例如:3000000000L五、命名5.1 适用于所有命名标识符的通用规范标示符只应该使用 ASCII 字母、数字,字母大小写敏感。因此所有的标示符,都应该能匹配正则表达式w+ 。 标示符不需要使用特殊的前缀或后缀,如 name_, mName, s_name 和 kName,在 Java 编程

23、风格中都不再使用。5.2 不同类型的标示符规范5.2.1 包名包名全部用小写字母,将各单词简单地连在一起(不使用下划线)。例如:com.example.deepspace,不要使用 com.example.deepSpace 或com.example.deep_space。5.2.2 类名类名都以 UpperCamelCase 风格编写。 类名一般使用名词或名词短语,例如:Character 或 ImmutableList。接口名称一般也使用名词或名词短语(如:List),有时也可以使用形容词或形容词短语(如:Readable)。还没有特定的规则或行之有效的约定来命名注解类型。测试类的命名,应

24、该以它所测试的类的名字为开头,并在最后加上 Test 结尾。例如:HashTest 、HashIntegrationTest。5.2.3 方法名方法名都以 lowerCamelCase 风格编写。 方法命名一般使用动词或者动词短语,例如:sendMessage 或 stop。在 JUnit 的测试方法中,可以使用下划线,用来区分逻辑组件的名字,经常使用如下的结构:test_。例如:testPop_emptyStack。 并不存在唯一正确的方式来命名测试方法。5.2.4 常量名常量命名,全部使用大写字符,词与词之间用下划线隔开。(CONSTANCE_CASE)。常量的定义:每个常量都是一个静态

25、final 字段,但不是所有静态 final 字段都是常量。在决定一个字段是否是一个常量时, 考虑它是否真的感觉像是一个常量。例如,如果任何一个该实例的观测状态是可变的,则它几乎肯定不会是一个常量。 只是永远不打算改变对象一般是不够的,它要真的一直不变才能将它示为常量。下面是常量和非常量的例子:1. / Constants2. static final int NUMBER = 5;3. static final ImmutableList NAMES = ImmutableList.of(“Ed“, “Ann“);4. static final Joiner COMMA_JOINER = J

26、oiner.on(,); / because Joiner is immutable5. static final SomeMutableType EMPTY_ARRAY = ;6. enum SomeEnum ENUM_CONSTANT 7.8. / Not constants9. static String nonFinal = “non-final“;10.final String nonStatic = “non-static“;11.static final Set mutableCollection = new HashSet();12.static final Immutable

27、Set mutableElements = ImmutableSet.of(mutable);13.static final Logger logger = Logger.getLogger(MyClass.getName();14.static final String nonEmptyArray = “these“, “can“, “change“;常量一般使用名词或者名词短语命名。5.2.5 非常量的字段名非常量字段名以 lowerCamelCase 风格编写。一般使用名词或名词短语,例如:computedValues 或 index。5.2.6 参数名参数名以 lowerCamelCa

28、se 风格编写。参数应该避免用单个字符命名。5.2.7 局部变量名局部变量名以 lowerCamelCase 风格编写,比起其它类型的名称,局部变量名可以有更为宽松的缩写。但即使如此,也应该尽量避免采用单个字母进行命名的情况,除了在循环体内使用的临时变量。即使局部变量是 final、不可改变的,它也不能被认为是常量,也不应该采用常量的命名方式去命名。5.2.8 类型名类型名有两种命名方式:1. 单独一个大写字母,有时后面再跟一个数字。 (例如,E、T 、X、T2) 。2. 像一般的类命名一样(见 5.2.2 节) ,再在最后接一个大写字母 T。 (例如,RequestT、FooBarT ) 。

29、5.3 驼峰式命名法(CamelCase)驼峰式命名法分大驼峰式命名法(UpperCamelCase)和小驼峰式命名法(lowerCamelCase)。有时一些短语改写成驼峰形式的时候可以有多种写法。例如一些缩写词汇,或者一些组合词:IPv6 或者 iOS 等。 为了统一写法,给出如下几乎可以确定为一种的写法:1. 将字符全部转换为 ASCII 字符,并且移除任何单引号。例如,“Mllers algorithm“ 被转换为 “Muellers algorithm“ 。2. 将上一步转换的结果切分成单词。从空格处或其它标点符号处分割开。 o 注意:一些已经是驼峰式的词语,也应该在这个时候被拆分。

30、 (例如 AdWords 被拆分为 ad words) 。但是例如 iOS 之类的词语,它其实不是一个驼峰式的词语,而是人们惯例使用的一个词语,因此不用做拆分。3. 经过上面两步后,先将所有的字母转换为小写,再把每个词语的第一个字母或除第一个单词之外的单词的第一个字母转换为大写。4. 最后,将所有词语连在一起,形成一个标示符。注意:词语原来的大小写规则,应该被完全忽略。以下是一些例子:Prose form Correct Incorrect“XML HTTP request“ XmlHttpRequest XMLHTTPRequest“new customer ID“ newCustomerI

31、d newCustomerID“inner stopwatch“ innerStopwatch innerStopWatch“supports IPv6 on iOS?“ supportsIpv6OnIos supportsIPv6OnIOS“YouTube importer“ YouTubeImporter YoutubeImporter * 号表示可以接受,但是不建议使用。注意:有些词语在英文中,可以用 - 连接使用,也可以不使用 - 直接使用。例如 “nonempty”和 “non-empty”都是可以的。因此,方法名字为checkNonempty 或者 checkNonEmpty 都是

32、可以的。六、编程实践6.1 override 能用则用只要是符合语法的,就把override 用上。6.2 异常捕获 不应该被忽略一般情况下,catch 住的异常不应该被忽略,而是都需要做适当的处理。例如将错误日志打印出来,或者如果认为这种异常不会发生,则应该作为断言异常重新抛出。 如果这个 catch 住的异常确实不需要任何处理,也应该通过注释做出说明。例如:1. try 2. int i = Integer.parseInt(response);3. return handleNumericResponse(i);4. catch (NumberFormatException ok) 5.

33、 / its not numberic; thats fine, just continue6. 7. return HandleTextResponse(response);例外:在测试类里,有时会针对方法是否会抛出指定的异常,这样的异常是可以被忽略的。但是这个异常通常需要命名为: expected。例如:1. try 2. emptyStack.pop();3. fail();4. catch (NoSuchElementException expected) 5. 6.3 静态成员的访问:应该通过类,而不是对象当一个静态成员被访问时,应该通过类名去访问,而不应该使用这个类的具体实例对象。

34、例如:1. Foo aFoo = .;2. Foo.aStaticMethod(); / good3. aFoo.aStaticMethod(); / bad4. somethingThatYieldsAFoo().aStaticMethod(); / very bad6.4 不使用 Finalizers 方法重载 Object.finalize 方法是非常非常罕见的。提示:不应该使用这以方法。如果你认为你必须使用,请先仔细阅读并理解 Effective Java第七条 “Avoid Finalizers”。然后不要使用它。七、Javadoc7.1 格式规范7.1.1 通用格式最基本的 Jav

35、adoc 的通用格式如下例:1. /*2. * Multiple lines of Javadoc text are written here,3. * wrapped normally.4. */5. public int method(String p1) .或者为单行格式:1. /* An especially short bit of Javadoc. */通用格式在任何时候使用都是可以的。当 Javadoc 块只有一行时,可以使用单行格式来替代通用格式。7.1.2 段落空白行:是指 Javadoc 中,上下两个段落之间只有上下对齐的 * 字符的行。每个段落的第一行在第一个字符之前,有

36、一个标签,并且之后不要有任何空格。7.1.3 Javadoc 标记所有标准的 Javadoc 标记,应该按照如下的顺序添加:param、return 、throws、deprecated。并且如果这四种 Javadoc 标记出现,描述都不能为空。 当从句无法在一行写完时,应该断行。延续行在第一行的字符的位置,缩进至少 4 个字符单位。7.2 摘要片段每个类或者成员的 Javadoc,都是由一个摘要片段开始的。这个片段非常重要。因为它是类或者方法在使用时唯一能看到的文本说明。 主要摘要只是一个片段,应该是一个名词短语或者动词短语,而不应该是一个完整的句子。不应该以类似于:A code Foo i

37、s a.或 This method returns.这样的开头,但是它应该像一个完整的句子一样使用标点符号。提示:一种常见的错误是把单行形式的 Javadoc 写成:/* return the customer ID */,这是不对的。应该改为: /* Returns the customer ID. */。7.3 何处应该使用 Javadoc至少 Javadoc 应该应用于所有的 public 类、public 和 protect 的字段和方法。以下是一些例外:7.3.1 例外:方法本身已经足够说明的情况当方法本身很显而易见时,不需要 Javadoc。例如:getFoo。没有必要加上Java

38、doc 说明“Returns the foo”。 单元测试中的方法基本都能通过方法名,显而易见地知道方法的作用。因此不需要增加 Javadoc。重要:如果有一些相关信息是需要读者了解的,那么以上的例外不应作为忽视这些信息的理由。例如,对于方法名 getCannicalName ,就不应该忽视文档说明,因为读者很可能不知道词语 canonical name 指的是什么。7.3.2 例外:重载方法重载方法有时不需要再写 Javadoc。7.3.3 例外:可选的 Javadoc对于包外不可见的类和方法,如有需要,也是要使用 Javadoc 的。如果一个注释是用来定义一个类,方法,字段的整体目的或行为,那么这个注释应该写成Javadoc,这样更统一更友好。注:本规范的大部分内容可用 Eclipse 格式化工具自动完成,所以提交代码时使用一次代码格式化是不错的选择。代码整洁

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 规范标准 > 国内外标准规范

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报