Android Code Style Guidelines for Contributors

英文原文地址:

https://source.android.com/source/code-style.html#java-language-rules


刚入门在进行软件开发的时候,可能在写code的时候有的亲是随心所欲想怎么写就怎么写,只要功能OK就行,而有的亲呢可能会想我的变量名要怎么见名知意, 我的

code要怎么写才健壮等等,当然我更看好后一种想法的小伙伴了,因为有一个好的代码风格,你写出来的code不光便于你自己理解,同时在团队合作的时候更便于别人

的理解与维护,并且能够体现自身的素养与功底,那么我们就根据android对想要向他们提交patch的代码风格要求来学习一下,同时规范自己的每一行代码吧。


好了,划线进入正题~~

===============================================================================================================================

如下这些规则不是指南也不是建议,而是严格的规定(口气还是满严肃的^V^).。如果想要向android贡献代码,不遵循如下的规则提交将不会被接受。

虽然Android中并非所有存在的代码都遵循了如下这些规则,但是我们要求未来添加的任何新代码必须要遵循这些规则。


先简单列一下本文的目录

Java语言规则

  -不要忽略异常

  -不要捕获通用异常

  -不要使用Finalizer

  -高校imports

Java库规则

Java风格规则

  -使用javadoc标准注释

  -写短方法

  -在标准的位置定义属性(字段)

  -控制变量的有效域

  -将import语句排序

  -用空格进行缩进(即不要用tab)

  -遵循字段命名约定

  -使用标准的Brace风格(条件语句除非在一行否则都需要加上花括号{})

  -控制单行的长度

  -使用标准的java注解

  -把缩写当作一个单词

  -使用TODO注解

  -少加log

  -保持一致性

Java测试代码风格规则

  -遵循测试方法命名约定


 正文内容如下,如果看到上面的目录就能明白,可以不用看详细解说,如果看过详细解释那么目录就可以作为条目温习了


Java语言规则

android遵循标准的java编码规则,另外添加了如下几条规则:

不要忽略异常

有时人们很容易写出像如下这种完全忽略异常的代码

void setServerPort(String value) {
    try {
        serverPort = Integer.parseInt(value);
    } catch (NumberFormatException e) { }
}

你必须不要再这么写代码了。也许你会觉得你的代码永远不会遇到这个错误条件或者认为处理这个错误并不重要,像上面该这种

忽略异常的方式会在你的代码里创建一座矿山留给其他人去征服在未来的某一天(相当于给别人埋坑)。你必须按照某种原则处理

你代码里面的所有异常。特定的处理方式根据场景的不同做不同的处理。


每当有人在写一个空的catch语句是都应该有一种毛骨悚然的感觉。虽然肯定有时候这样写确实是对的,但是你至少应该对这样写

有所思考。在java里你无法逃避这种毛骨悚然的感觉。----James Gosling


可以接受的备选方案如下(按照优先级排序):

-将异常抛给你的调用者

void setServerPort(String value) throws NumberFormatException {
    serverPort = Integer.parseInt(value);
}

-抛出适合你的抽象层次的新异常,也即给抛出的异常添加一些你的层次能够知道的信息

void setServerPort(String value) throws ConfigurationException {
    try {
        serverPort = Integer.parseInt(value);
    } catch (NumberFormatException e) {
        throw new ConfigurationException("Port " + value + " is not valid.");
    }
}

-优雅的处理这个错误并在catch块中给替换一个适当的值

/** Set port. If value is not a valid number, 80 is substituted. */

void setServerPort(String value) {
    try {
        serverPort = Integer.parseInt(value);
    } catch (NumberFormatException e) {
        serverPort = 80;  // default port for server 
    }
}

-捕获这个异常并抛出一个运行时异常。注意这是危险的:仅仅在你确定发生这个错误后crash是适当的。

/** Set port. If value is not a valid number, die. */

void setServerPort(String value) {
    try {
        serverPort = Integer.parseInt(value);
    } catch (NumberFormatException e) {
        throw new RuntimeException("port " + value " is invalid, ", e);
    }
}

需要注意的是原异常会作为参数传递给RuntimeException的构造函数,如果你的代码必须在Java 1.3版本以下进行编译,

那么你将需要省略掉这个源头异常,也就是这个运行时异常的真正原因。

-最后一招:如果你确定以及肯定你忽略掉这个异常是正确的选择,那么至少你应该在catch语句块上写下为什么要这么做,

或者打印log提醒曾经出现过异常

/** If value is not a valid number, original port number is used. */
void setServerPort(String value) {
    try {
        serverPort = Integer.parseInt(value);
    } catch (NumberFormatException e) {
        // Method is documented to just ignore invalid user input.
        // serverPort will just be unchanged.
    }
}

不要捕获通用异常

有时候为了偷懒人们更愿意用如下方式捕获异常

try {
    someComplicatedIOFunction();        // may throw IOException 
    someComplicatedParsingFunction();   // may throw ParsingException 
    someComplicatedSecurityFunction();  // may throw SecurityException 
    // phew, made it all the way 
} catch (Exception e) {                 // I'll just catch all exceptions 
    handleError();                      // with one generic handler!
}

首先你不应该这么做,几乎在所有场景下这样捕获通用异常或者Throwable都是不恰当的,最好不要是Throwable,因为它包含

错误的异常,也就是Error.java,因为Error也继承自Throwable,这样如果直接捕获Throwable,那么真正的Error也被捕获了。这样

做是相当危险的,这就意味着你永远不期望错误的出现,及时是RuntimeException例如ClassCastException,甚至或不捕获了应用

层级的错误处理。它隐藏了你代码的错误处理性能。这就意味着如果在你调用的代码里面某人添加了新的异常类型,编译器并不

会提醒你有新的异常类型需要做特殊处理。毕竟在大多数情况下并非所有的异常都可以用同样一种方式进行处理。


当然万事无绝对,对于此规则也有一些例外的情况:某些测试代码和你想要捕获所有错误的顶层代码(阻止这些错误显示到UI界面上,

或者为了保证接下来批量的任务可以继续执行下去)。在这种场景下你可以捕获通用异常(Exception)或者Throwable并且恰当的处理。

在做这样的决定前你需要做相当仔细的考虑,虽然你会在catch语句块中添加注解说明在这里做这样的处理是安全的。


捕获通用异常的替换处理方式如下:

-捕获可能会在对应的try语句块中所有异常,每个异常对应一个catch语句块,虽然这样写会略显尴尬,但是还是建议捕获所有的异常,

  注意在catch语句中不要出现太多重复的代码

-重构你的代码使用多个try语句块去实现细粒度更高的错误处理,例如从解析中将IO处理分离出来,在每个场景中将错误分开处理。

-重新抛出这个异常,许多时候有些异常不需要在你这一层来进行处理,那就索性将它继续抛出去


记住:异常是你的朋友!当编译器想你抱怨你没有捕获某一个异常的时候,不要皱眉,要微笑,编译器只是想在编译的时候就告诉你,

你有需要处理的潜在错误,不用到运行时候发现再处理


不要使用Finalizer

Finalizer是一种能够在对象在被垃圾回收机制回收时执行一段代码的方法。

优点:可以方便做清理工作,尤其是外部资源

缺点:Finalizer什么时候会被调用是没有保证的,甚至它是否会被调用也是不确定的。

抉择:我们不使用Finalizer。在大多数场景下,你可以将需要在Finalizer中所做的处理用一个好的异常处理来取代。如果你确实需要使用Finalizer,

你可以定义一个closer方法(或者类似的其它方法)并且在注解中写清楚该方法什么时候需要被调用。具体例子可以参考InputStream类。在这种情

况下在Finalizer中打印提示的log信息是比较恰当的方式但并不是必须的,只要这里打印log不会太频繁以至于淹没整理日志。


高效Imports

当你想用用foo包中的Bar类时,你有如下两种方式可以将它import进来

1.import foo.*;

优点:潜在的减少了import语句的数量

2.import foo.Bar;

优点:比较清晰的能够知道具体哪个类是需要用到的,对于维护者来说增加了代码的可读性。

抉择:android代码中所有的import都使用后一种方式,但是java标准库(java.util.*, java.io.*, etc)和单元测试代码(junit.framework.*)例外。


java类库规则

在使用android中的java库和工具是有约定的。在某些情况下,在一些重要的途径中约定会有所改变,还有一些旧代码中会使用一些被废弃的模式以及

类库。当在处理这类代码时,允许跟随已存在的代码风格。但当在创建新的组件的时候不要再使用被废弃的库。


Java风格规则

使用javadoc标准注解

 每一个文件的顶部都应该有版权信息语句,然后跟上包命语句,以及一系列的import语句,每一类语句块之间用一个空白行隔开。在这之后就是类或者

接口的声明。在javadoc注解中描述清楚这个类或者接口具体是用来做什么的。参考如下:

/*
 * Copyright (C) 2013 The Android Open Source Project 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at 
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */

package com.android.internal.foo;

import android.os.Blah;
import android.view.Yada;

import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Does X and Y and provides an abstraction for Z.
 */

public class Foo {
    ...
}

你所写的每一个类或者重要的公开方法都必须用javadoc注解进行注释,至少包含一句用来描述你这个类和方法是用来做什么的。这个语句应该

以第三人称的口吻来描述。

/** Returns the correctly rounded positive square root of a double value. */
static double sqrt(double a) {
    ...
}

或者

/**
 * Constructs a new String by converting the specified array of 
 * bytes using the platform's default character encoding.
 */
public String(byte[] bytes) {
    ...
}

当然,你不必为每一个类似get和set这种并非很重要的方法添加javadoc注释,例如setFoos这样的方法javadoc中都会描述为"set Foos",这就没有必要了。

如果你的方法做了一些很复杂的事情(例如强制约束或者有比较重要的副作用),这样的方法你就必须要加上注解了。也就是如果不是类似属性“Foo”这种

很明显一眼就能看出其表达的意思,那么你就应该要写出具体的注解。


这样每一个你所写的方法,公开或者其它的,都会从javadoc中收益,如果javadoc注解写得很清楚的话,更利于后期自己或其他人的维护。公开方法属于

API的的一部分因此需要javadoc注解的支持。


Android目前并没有指定javadoc注解的风格。但是你应该遵循How to Write Doc Comments for the Javadoc Tool这个链接中的说明来添加。


写短小的方法

在某种程度上这是可行的,方法应该尽量短小并且集中。然而在有些场景下长方法更合适,因此在方法长度上没有硬性的规定。那么如果方法的长度超过了

40行,就因该考虑一下是否能够在不影响方法的架构的基础上将方法分成几个小的方法


将属性字段定义放在标准的位置

属性字段应该定义在文件的顶部,即类的顶部,或者在即将使用这个字段的方法的上面。


限制变量的作用域

本地变量的作用域应该尽量控制在最小的范围内。这样做能够尽量增加你代码的可读性以及可维护性,减少出现错误的可能性。变量的声明尽量在某一范围的

语句块内,这个语句块范围能够尽量小,最好是刚好覆盖所有使用这个变量的语句。


本地变量应该在第一次使用前进行声明,在每个本地变量被声明的附近应该有对其进行初始化的语句。如果在声明时没有足够的信息来对其进行合理的初始化,

那么你应该尽量推迟该变量的初始化指导你能够进行初始化为止。


这个规则的例外是关于try-catch语句块的。如过变量的初始化是依靠需要进行try-catch进行异常检查的方法调用返回的值,那么该变量必须在try语句块中

进行初始化。如果该变量必须会在try语句块外被用到,那么你必须将该变量的声明提出到try语句块外,并给初始化一个不算是很合理的值。

// Instantiate class cl, which represents some sort of Set 
Set s = null;
try {
    s = (Set) cl.newInstance();
} catch(IllegalAccessException e) {
    throw new IllegalArgumentException(cl + " not accessible");
} catch(InstantiationException e) {
    throw new IllegalArgumentException(cl + " not instantiable");
}

// Exercise the set 
s.addAll(Arrays.asList(args));
 
 
但是即使在这种情况下,也可以将try-catch封装在方法中来避免,如下所示
 
 
Set createSet(Class cl) {
    // Instantiate class cl, which represents some sort of Set 
    try {
        return (Set) cl.newInstance();
    } catch(IllegalAccessException e) {
        throw new IllegalArgumentException(cl + " not accessible");
    } catch(InstantiationException e) {
        throw new IllegalArgumentException(cl + " not instantiable");
    }
}

...

// Exercise the set 
Set s = createSet(cl);
s.addAll(Arrays.asList(args));

循环变量应该被声明在for语句内,除非因此会有编译错误除外:

for语句

 
 
for (int i = 0; i < n; i++) {
    doSomething(i);
}

foreach语句
 
 
for (Iterator i = c.iterator(); i.hasNext(); ) {
    doSomethingElse(i.next());
}

import语句排序

import语句的顺序应该按照如下分组进行排列:
1.Android类的import语句
2.第三方类库import语句(com,junit,net,org)
3.java和javax
要完全匹配IDE的设置,import顺序应该是:
-每组import按照英文字母排序,并且大写字母排在小写字母的前面(例如 Z应该排在a的前面)
-在每组import语句之间应该有一个空白行来隔开(android, com, junit, net, org, java, javax)
import的排序原本上是没有风格要求的。这就意味着要么IDE自动导入的时候总是在更改import的顺序,或者
用IDE研发的coder关闭了IDE的自动import管理功能而自己手动进行import的书写。这样做被认为是很糟糕
的。当IDE中java风格被设定的时候,首选风格会影响所有方面。它几乎满足我们“选择一个排序,并保持一致”
的需求。因此我们可以选择一种风格,更新风格指南,使得所选风格遵循import排序的这种规则。我们期望所有
用IDE进行编码的工程师能够在没有其它工程师的努力下遵循这种import排序的模式。

这种风格的选择需要满足如下条件:
-做imports的人想要查看第一个import应该在android的顶部
-做imports的人想要查看最后一个import应该在java的底部
-人类能够很轻松的遵循这种风格
-集成开发环境能够遵循这种风格

static import的使用以及放置的位置稍有争议。有的人认为静态导入应该穿插在其它各组imports中,而有的人认为
应该单独给静态导入分一个组。此外,我们还没确定一种方法使得所有IDE都遵循一种排序方式。

当大多数人都认为import排序是一种很小的事情时,请作出你自己的裁决并保持一致。

用空格进行缩进
我们使用4个空格作为一个缩进块,从来不使用tab进行缩进。当有疑问时,请保持和周围code一致。
我们使用8个空格作为换行的缩进,包括方法调用和变量的赋值,例如:
正确的方式

Instrument i =
        someLongExpression(that, wouldNotFit, on, one, line);


错误的方式
Instrument i =
    someLongExpression(that, wouldNotFit, on, one, line);



遵循字段命名约定
-非公开(non-public)非静态(non-static)的字段名以“m”开头
-静态字段名以“s”开头
-其它字段名以小写字母开头即可
-常量(public static final)字段全部字母大写
例如:
public class MyClass {
    public static final int SOME_CONSTANT = 42;
    public int publicField;
    private static MyClass sSingleton;
    int mPackagePrivate;
    private int mPrivate;
    protected int mProtected;
}


使用标准花括号风格

用来括住一段代码的花括号不需要另起一行,只需要跟在其前面的一行代码的最后就可以了,例如
class MyClass {
    int func() {
        if (something) {
            // ...
        } else if (somethingElse) {
            // ...
        } else {
            // ...
        }
    }
}

我们要求条件语句的内容需要用花括号包起来,除非整个条件语句能够在一行中写下,当然包括条件判断
以及满足该条件需要执行的语句。参考如下几个例子:
合法
if (condition) {
    body(); 
}

合法
if (condition) body();

不合法
if (condition)
    body();  // bad!


限制单行的长度

在你的代码中每一行应该最多有100字符的长度。
这个规则有很多的争议,不过最后的裁决是100字符的长度已经是长度的最大值了,不能超过这个长度了。
例外1:如果在注释中有命令的例子或者url链接长度超过100个字符,为了命令以及url链接的方便复制粘贴
长度可以超过100个字符
例外2:import语句可以不受这个规则的限制,因为毕竟人很少关注这个,而且这样也简化了工具(IDEs)的开发。
使用标准的Java注解
注解应该优先于其它修改针对统一语言元素来讲。简单的修饰注解(例如@Override)应该同其所修饰的语言元素
处于同一行[关于这一条我搜了下android的代码,有的确实遵循了,但是有没有,个人认为还是单起一行比较美
观]。如果需要好几个注解,或者参数注解,那么每个注解应该单独占一行。
有三个在java中预定义的注解在Android中的标准做法如下:
-@Deprecated:此注解必须用在被注解的元素是即将被弃用的,不鼓励再继续使用。当你使用这个注解时同时需
要在该元素上加载@Deprecated的javadoc标签并写明转换的实现方法。另外,需要注意的是即使别标注为
@Deprecated的方法还是应该能够工作的。
如果你在旧的代码中看到有方法被加上了@Deprecated的标签请给它添加上@Deprecated的注解
-@Oevrride:此注解必须被用在子类重写在父类中声明或实现的方法上。
例如,如果你使用了@inheritdocs javadoc标签,并且来自于某一个类(注意是类不是接口),那么与此同时你
就必须给重写的父类方法添加上@Overrride注解
-@SuppressWarnings:此注解应该仅被用在无法消除警告的情况下。如果一个警告通过了“不可能消除”的测试,那么
此注解就必须被使用了,为了确保所有的警告都准确反应出了代码中的问题。
当SuppressWarnings注解是必须的时候,它的前面必须加上一个TODO注释,解释“不能被消除”的情况。这通常是被
鉴定出一个违规类有不太合适的接口。例如:

// TODO: The third-party class com.third.useful.Utility.rotate() needs generics 
@SuppressWarnings("generic-cast")
List<String> blix = Utility.rotate(blax);



当@SuppressWarnings注解是必需的时候,代码应该被重构将被注解的软件元素隔离开来。
将缩写当作单词
在给变量,方法和类命名时将缩略词当作一个单词。这样这些名字可读性就更强了:

JDK和Android代码库针对缩写处理都非常不一致。因此,实质上也是不可能让你附近的代码都保持一致的,那么硬着头皮将缩写当作
一个单词吧。
使用TODO注释
代码使用TODO注释是一个临时的,短期的解决方法,或者说是足够好但是不完美的方法。
TODO注释应该以TODO全大写字符开头,后面跟上冒号:
这样
// TODO: Remove this code after the UrlTable2 has been checked in.


或者这样
// TODO: Change this to use a flag instead of a constant.


如果你以"在未来某个时间做某事"的形式添加TODO注释,那么你要么需要加上非常具体的日期("Fix by November 2005"),要么写上
非常具体的事件("Remove this code after all production mixers understand protocol V7.")。
保守的添加log
如果当log是必须的时候,如果该log没有保持足够合理以及间接那么它必要会给性能带来显著的负面影响,从而立马丢失了它的有效作用。
Log设备给提供了五种不同级别的log,如下所述:
-ERROR:这个级别的log应该在发生了某些致命的事情时。即某些用户可见的后果,并且不能够恢复如果不通过明确的删除某些数据,卸载
      应用程序,擦出数据分区或者重新刷机(或者更糟糕)这些方式。这个级别的日志是会总被记录的。这些被标记为ERROR的log信息
      将被作为上报到数据统计收集服务器上的候选者。
-WARNING:这个级别的log应该用在发生了严重并且在意料之外的事情时。即某些将会是用户可见的后果但是很可能会被恢复而不会有数
      据丢失由于执行了某些明确的操作,范围从等待或者重启应用程序一直到重新下载应用程序的新版本或者重启设备。这个级别的log也
      是总会被记录的。WARNING级别的log信息也将被考虑是否上报给数据统计收集服务器
-INFORMATIVE:这个级别的log信息应该在需要提示发生某些大多数人比较关心的事情是打印。即当一个解决方案被采用但其极有可能会
      影响比较广,虽然不一定是一个错误。这种状态的log应该被在这个领域具有权威性的模块打印(避免非权威模块的log重复打印),这个级
             别的log也是总会被记录的。
-DEBUG:这个级别的log打印是为了进一步提示在设备上发生了什么事情以便与调查和调试非期望事情发生的原因。你应该只打印需要用来搜集
      足够的信息以确定你的模块都发生了些什么的log内容。如果你的调试log信息占据了整个log日志那么你应该使用详细日志级别VERBOSE。
      这个级别也会被记录,甚至是在发布版本上,并且这个log需要被if (LOCAL_LOG)或者if (LOCAL_LOGD)语句块包围,而LOCAL_LOG[D]
      会被定义在你的类或者子模块中,这样就存在了关闭所有这类log的可能性。因此在If (LOCAL_LOG[D])语句块中不能有代码逻辑相关内容。
      并且所有的字符串拼装也只能在这个语句块中进行。如果将if (LOCAL_LOG[D])语句块提取成一个方法会导致字符串的拼装被提取到这个语
      句块之外的话,是不建议这么做的。
      也许现有代码中还有通过if (localLOGV)这种形式,虽然它的名字不规范,但是也被考虑为可以接受的。
-VERBOSE:这个级别的log应该用于可以打印一切信息。这类log应该仅在调试版本上被记录,并且应该被if(LOCAL_LOGV)语句快包围(或者其它
      等效的方式),因为这样我们才可能在默认的版本上不记录这个类型的log。任何关于这个log的字符串拼装都应该剥离在if (LOCAL_LOGV)
      中,以保证其不会出现在发行(release)版本中。
注意:
-在一个给定的模块中,除了VERBOSE级别的log信息外,一个错误的日志应该尽量只被打印一次:在一个模块的一连串函数调用中,应该仅最内层的
 方法调用应该返回错误,而该函数的调用者应该仅仅打印一些对与分离问题原因有重要作用的log信息。
-在模块链中,除了VERBOSE级别的log信息外,在低层模块中发现了来自于高层模块的无效数据,低层模块应该仅将这种情况打印在DEBUG级别的
  log信息中,并且仅当日志提供了不会另外对调用者有效的信息。具体来讲,没有没有必要给抛Exception的场景(这个exception应该会携带
  所有的有效信息),或者仅有包含一个错误代码的信息的场景打印log。这一点在framework和apllication之间尤其重要,并且这种状况由第三方应用程序
  导致时framework正确的处理方式就是不应该打印高于DEBUG级别的log信息。能够触发INFORMATIVE或者更高级别的log信息打印的场景是仅当一个
  模块或者应用程序发现了自身的错误或者其对应的低层级的错误。
-当在某种情况发生时,有部分log会被打印很多次,那么比较好的做法应该是通过实现某中速率限制的机制来控制相同或者相似的log信息被打印多次,
 以至于淹没整个日志。
-网络连接的断开被认为是普遍并且完全可以预料到的场景,因此不应该随便的打印这种场景发生的log信息。网络连接的断开如果给app带来一定的后果
 那么应该被记录为DEBUG或者VERBOSE级别(完全取决于后果是否足够严重并且足够出乎意料到需要记录在发行版本中)。
-A full filesystem on a filesystem that is accessible to or on behalf of third-party applications should not be logged at a level higher than INFORMATIVE
  真心无力翻译,可能这方面接触得少,搞不明白想表达什么,之后明白了再翻译吧 = =||
-无效数据来自于任何不可信的源头(包括共享存储上的文件,或者来自任何网络的数据)被认为是预料之中的,当数据被发现为无效时(即便如此log也是
 被尽可能限制的)不应该打印高于DEBUG级别的log信息
-请记住当你在给字符串使用+操作符时,会隐式创建一个默认拥有16个字符大小缓冲区的StringBuilder对象以及几个其它的临时字符串对象。即显示创建
 StringBuilder并不会比用+操作符更加高的资源消耗(没准可能会更高效)。与此同时也请记住调用Log.v的代码在发行版本上会被编译并且执行,包括编译
 字符串,即使logs别没有被读取。
-所有是为了给人们阅读以及出现在发行版本上的log日志都应该精炼但不神秘,也就是不要太晦涩难懂,应该能够被人合理的理解。这包括所有高于等于
 DEBUG级别的log
-当可能的时候,log应该保持在一行内如果合理的话。单行的长度应该在80或者100个字符长度以内。当长度超过了130或者160个字符长度(包括tag的长度)
  在可能的情况下应该尽量避免
-用于提示成功的log信息的级别应该不得高于VERBOSE
-临时log为了确认很难复现的问题应该使用DEBUG或者VERBOSE级别,and should be enclosed by if blocks that allow to disable it entirely at compile-time.
  后面这句翻译不动了
-小心通过log发生的安全泄漏。私有信息应该被避免打印。被保护内容的信息毫无疑问必须应该避免打印。尤其是在写framework代码时由于并不容易能够
  知道哪些内容会是私有或者被保护的,所以在写代码的时候更应该注意对安全的考虑
-System.out.println() (或者native代码中的printf() )应该永远不被使用。System.out和System.err会被重定向到/dev/null,所以你的log将不会被打印到能看到的
  地方。然而,所有关于这写调用的字符串创建仍然会被执行。
-日志的黄金规则是你的log可能没有必要将被人的log推出缓存区,就像别人的log可能不会推出你的一样。
保持一致
我们的临别思想:保持一致。当你在编辑代码的时候,花几分钟的时间看看附近的代码,然后决定你的代码风格。如果它们的if语句周围有
间距,那么你也应该这样做。如果它们的注释周围有星号包围,那没你的注释也应该有星号围绕。
这篇代码风格的关键在与能够有通用的编码词汇,这样人们可以专注于你在说什么,而不是你怎么在说。我们在这里介绍了整体风格规则以便
人们能够知道这些词汇。但是本地风格(代码原来的风格)也同样很重要,也许你遵循了此文章所说的规则,但是你修改了一个文件,在里面添
加了打篇幅的不一样风格的代码,这样子完全改变了阅读代码者的节奏,不可取,尽量阻止这样的事情发生。
Java测试风格规则
遵循测试代码命名约定
当给测试方法命名的时候,你可以用下划线来将当前正在测试的内容从具体测试case中分离出来。这个风格能够更便于知道什么内容被测试了。
例如:
For example:


testMethod_specificCase1 testMethod_specificCase2


void testIsDistinguishable_protanopia() {
    ColorMatcher colorMatcher = new ColorMatcher(PROTANOPIA)
    assertFalse(colorMatcher.isDistinguishable(Color.RED, Color.BLACK))
    assertTrue(colorMatcher.isDistinguishable(Color.X, Color.Y))
}

你可能感兴趣的:(编码规范)