Android代码风格指南 原文:Code Style Guidelines for Contributors 下面的规则不是建议而是严格的规定。Android代码贡献者如果不遵守这些规则,那么他们的代码不会被接受。并非所有现存的代码都遵循这些规则,但希望所有的新代码能如此。 Java语言规则 我们遵循标准的Java编码约定,但还添加一些规则。 3.Finalizers:一般不使用它们; 4.Imports:引入具体的类,而非使用*。 Java库规则 这里有一些关于使用Android Java库与工具的约定。在某些情况下,该约定的一些重要方式已经发生了变化,老的代码可能在使用废弃的模式或库。当使用这些代码时,最好继续保持与已存在的风格一致(参见一致性)。当创建新的组件时,从来不使用废弃库。
Java的风格规则 当所有文件都保持一致的风格时,程序就更容易维护。我们遵循标准的Java编码风格,他们由Sun公司为Java编程语言制定的编码约定,除少数例外并增加一些。这些风格指南是全面而详细的,在Java社区很常用。 此外我们增加了下面的风格规则: 3.成员变量:在该文件的顶部,或者紧接在使用它们的方法的前面; 5.imports:android;按字母顺序排列的第三方;java(x); 11.缩写词:缩写词命名如下:XmlHttpRequest, getUrl()等等; 13.一致性:Look at what's around you! Javatests风格规则: 测试方法的命名:testMethod_specificCase是正确的。
Java语言规则
有时很容易编写完全忽略异常的代码,比如:
你绝对不能这样做。 虽然你可能认为你的代码永远不会遇到这个错误条件或处理它并不重要,忽略像上面的异常会在你的代码中给别人埋下地雷,迟早有一天会被绊倒。原则上,你必须在你代码中处理每一个异常。特殊的处理要视情况而定。 任何时候有人使用空的catch子句,他们应该有一个令人毛骨悚然的感觉。 可接受的另外一个方案(为了性能考虑)是:
void setServerPort(String value) throws NumberFormatException {
serverPort = Integer.parseInt(value);
}
捕获该异常并抛出一个新的RuntimeException。这样很危险:除非你不主动这样做该错误就会导致程序崩溃。 void setServerPort(String value) { try { serverPort = Integer.parseInt(value); } catch (NumberFormatException e) { throw new RuntimeException("port " + value " is invalid, ", e); } }
最后:如果你确定忽略异常是合适的,你可以忽略它,但是必须注明充分的理由。 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. } }
异常: 不要捕捉一般异常有时候人们容易为了偷懒,在捕捉异常时会这样做:
你不应该这样做。 异常是指在程序中出现的异常状况,在Java中异常被抽象成一个叫做Throwable的类。 其中如果程序出错并不是由程序本身引起的,而是硬件等其他原因引起的,我们称之为Error,一般情况下Error一旦产生,对程序来说都是致命的错误,程序本身无能为力,所以我们可以不对Error作出任何处理和响应。 异常如果是由程序引起的我们称之为Exception,Exception又分两种,我们把运行时才会出现的异常叫做 RuntimeException,RuntimeException我们不好在程序编写阶段加以事先处理,而其他异常则可以在程序编写和编译阶段加以事 先检查和处理,我们把这种异常叫做检验异常。 程序只需要捕捉和处理检验异常。 相应的我们把除检验异常(可检查异常)之外的异常称之为非检验异常,包括Error和RuntimeException ,非检验异常可以捕捉也可以不捕捉,更多的时候我们不捕捉,因为捕捉了我们也没办法处理,譬如程序运行时发生了一个 VirtualMachineError异常,虚拟机都出错了,作为运行在虚拟机内的程序又有什么办法处理呢?
在几乎所有情况下,不宜捕捉一般的异常或Throwable,尤其是Throwable,因为它也包含Error异常。这是很危险的,它意味着你永远不希望的异常结束了程序捕获异常的能力。它模糊了你代码的故障处理能力,这意味着在你调用的代码中有人增添了新的异常,编译器不会意识到你需要处理不同的错误。总之,你不能用相同的方法处理不同的异常。 但有些罕见的例外:一些测试代码和顶级代码需要捕捉各种误差(防止在UI中显示或保持批处理继续运行)。在这种情况下你可以捕捉一般异常和适当的处理错误。但在这样做之前,你应该仔细考虑,并解释为什么这样做是安全的。 捕获一般异常的替代方案: 在一个try后面捕获每个异常,这样虽然很糟糕,但仍优于捕获所有的异常。不要在catch中重复太多的code。 多使用try重构你的代码使之有更精细的错误处理; 抛出异常,很多时候你不需要捕获这个水平上的异常,只要抛出它即可。 Finalizers它是什么: 当一个对象被垃圾回收时,Finalizers能够去执行某段代码。 优点: 可以方便清理,特别是外部资源。 缺点: 不能保证finalizer什么时候会调用,或甚至根本上没被调用。 决定:我们不使用 finalizers。 Imports在imports使用通配符它是什么 :当你想使用foo包中的Bar类,这有两种可能的方式导入它:
1#的优点 :大大减少了import声明的数目。 2#的优点 :很明显的看到哪些类实际在用,对于维护者而言,代码更具有可读性。 决定 :使用样式#2 。 一个明确的例外是用于Java标准库(使用java.util .*,java.io. *,等等)和单元测试代码(junit.framework .*)。 注释/Javadoc所有的文件应该有一个在顶部版权声明。 然后紧接着是package和import,每一块以空白行分隔。再下来是类或接口的声明。 在Javadoc注释中描述类或接口的用途。
static double sqrt(double a) { } public String(byte[] bytes) { } 简短的方法这在一定程度上是可行的,方法应该保持小而直观的反应它的功能。然而得承认,长的方法有时是比较适当的,因此没有硬性限制方法的长度。如果一个方法超过40行,想想是否可以在没有危害程序结构的基础上进行拆分。 局部变量局部变量的作用范围应保持最小。这样可以增加代码的可读性和可维护性,降低错误的可能性。 每个变量应该在最靠近使用它们的地方声明。 局部变量应该先声明后使用,尽量在声明局部变量的同时初始化。如果你还没有足够的信息来初始化变量,你应该推迟声明,直到你需要声明它的时候。 try-catch语句是一个例外,如果一个变量是通过try中的一个方法的返回值进行初始化,而该方法可能抛出异常,那么该变量必须在try中初始化。如果该值要在try外面使用,则必须在try之前声明。
但是即使是这种情况,也可以通过将方法封装在try-catch中来避免:
循环变量应该for里面声明,除非有令人信服的理由不这样做:
|
Good |
Bad |
XmlHttpRequest |
XMLHTTPRequest |
getCustomerId |
getCustomerID |
这种风格规则也适用于被缩写的名称本身就是缩写词的情况:
Good |
Bad |
class Html |
class HTML |
String url; |
String URL; |
long id; |
long ID; |
使用TODO注释的代码是暂时短期的解决方案,或者足够好但不完美。
// TODO: Remove this code after the UrlTable2 has been checked in. // TODO: Change this to use a flag instead of a constant.
如果你的TODO形式是“At a future date do something”,那么你就要包括一个非常具体的日期或者一个非常具体的事件。
如果你正在编辑代码,花几分钟看看周围的代码并确定其风格。
有一个共同的代码风格,人们则可以专注于你在说什么,而不是你如何这样说。
虽然日志是必要的,但是它对性能有着显著的负面影响,并且迅速失去其作用。日志有5种不同的记录级别,以下是在不同的层次,不同时间下如何使用它们:
ERROR:
WARNING:
INFORMATIVE:
DEBUG:
VERBOSE:
当命名测试方法的时候,可以使用下划线来分隔名称,这种风格可以更清楚的看出什么案件正在被测试。
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)) }
你可以导入development/ide/eclipse下的文件,使得Eclipse按照Android代码风格规则。选择 “Window ? Preferences ? Java ? Code Style,使用 “Formatter ? Import” ,导入android-formatting.xml,”Organize Imports ? Import” 导入 android.importorder.
eclipse
tab 设置为4个空格:
Preferences -> General -> Editors
-> Text Editors:
Insert spaces for tabs
|