客户端Android平台开发规范

之前的一份文档 做了删改 有些建议值得学习

1 概述
规范开发流程对提高团队工作效率,降低项目风险有重大意义。此文档旨在制定一个为大家所接受和认可的开发规范,并严格执行。
本文涉及的规范有编码规范,Code review规范,提测流程规范,项目发版规范。
2 编码规范
2.1 Java编码规范
2.1.1 代码书写/排版
2.1.1.1 程序块要采用缩进风格编写,缩进的空格数为4个,不允许使用TAB缩进【规则】
说明:不同的缩进风格对代码的可读性影响很大,以tab为缩进单位在不同的tab step下可读性也相差很多,所以将缩进定为一个soft tab即4个空格,这样在所有环境下缩进都会保持一致。可以适应不同操作系统与不同开发工具。

2.1.1.2 if、while、for、do语句的执行体总是用”{“和”}”括起来,即使单条语句也是。并且在较长(超过一屏)的判断或者循环语句的结尾应该有注释语句做出标识。【规则】
示例:

if (debug) {
log(“单行语句也要使用括号括起来!!!”);
}

if (a > b) {
temp = a;
//……
}//if (a >b)结束

2.1.1.3 一行程序以小于120字符为宜【建议】,超长的语句应该在一个操作符之前折行,并在下一行加入适当的空格进行缩进;当一个表达式无法容纳在一行内时,可以依据如下一般规则断开之:【规则】
a)在一个逗号后面断开
如:
someMethod(longExpression1, longExpression2, longExpression3,
longExpression4, longExpression5); //’,’后换行
b)在一个操作符后面断开,操作符放在行首
如:
longName1 = longName2 * (longName3 + longName4 - longName5)
+ 4 * longname6; //运算符号后换行
c)新的一行应该与上一行同一级别表达式的开头处对齐
d)如果以上规则导致你的代码混乱或者使你的代码都堆挤在右边,那就代之以缩进若干空格。
说明: 这样可读性更好,逻辑更一目了然。

2.1.1.4 不允许把多个短语句写在一行中,即一行只写一条语句【规则】
说明:阅读代码更加清晰
示例:如下例子不符合规范。
Object o = new Object(); Object b = null;

2.1.1.5 相对独立的程序块之间、变量说明之后必须加空行【规则】
说明:阅读代码更加清晰
示例:
if(a > b) {
doStart();
}
//此处是空行
return;
2.1.1.6 在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空格;进行非对等操作时,如果是关系密切的立即操作符(如.),后不应加空格。【规则】
说明:阅读代码更加清晰
示例:

if (a == b) {
objectA.doStart();
}
a *= 2;

2.1.2 命名
2.1.2.1 Package命名规则
Package 的名字应该都是由一个小写单词组成。【规则】
如:
package com.zhibo.rigel.service;
建议:
包名采用域后缀倒置的加上自定义的包名,采用小写字母,都应该以com.zhibo开头(不包括一些特殊原因)。在部门内部应该规划好包名的范围。
格式:
com.zhibo.[平台名].产品名.模块名称
示例:
com.zhibo.android.searchbox.downloads

2.1.2.2 类名和接口使用类意义完整的英文描述,每个英文单词的首字母使用大写、其余字母使用小写的大小写混合法。【规则】
使用完整单词,避免缩写词(除非该缩写词被更广泛使用,像URL,HTML)

示例:OrderInformation, CustomerList, LogManager, LogConfig, SmpTransaction

2.1.2.3 方法名使用类意义完整的英文描述:第一个单词的字母使用小写、剩余单词首字母大写其余字母小写的大小写混合法【规则】
示例:
private void calculateRate();
public void addNewOrder();

2.1.2.4 参数和变量的名字必须用一个小写字母开头,后面的单词用大写字母开头【规则】,此外建议变量的名字最后带有表示该变量类型的后缀。【建议】
如:
List customerDataList;

2.1.2.5 方法中,存取属性的方法采用setter 和 getter方法,动作方法采用动词和动宾结构【规则】
格式:
get + 非布尔属性名()
is + 布尔属性名()
set + 属性名()
动词()
动词 + 宾语()
示例:
public String getType();
public boolean isFinished();
public void setVisible(boolean);
public void show();
public void addKeyListener(Listener);

2.1.2.6 属性名使用意义完整的英文描述,第一个单词的字母使用小写,剩余单词首字母大写其余字母小写的大小写混合法。属性名不能与方法名相同【规则】
示例:
private customerName;
private orderNumber;
private smpSession;

2.1.2.7 2-4: Final 变量和ENUM变量的名字应该都大写,并且指出完整含义,每个单词之间使用“_”分割。【规则】
public static final int MAX_VALUE = 1000;
public static final String DEFAULT_START_DATE = “2001-12-08”;

2.1.2.8 通过对函数或过程、变量、结构等正确的命名以及合理地组织代码的结构,使代码成为自注释的。【建议】
说明:清晰准确的函数、变量等的命名,可增加代码可读性,并减少不必要的注释。

2.1.2.9 常用组件类的命名以组件名加上组件类型名结尾【建议】
示例:
Application 类型的,命名以App 结尾——MainApplication
Frame 类型的,命名以Frame 结尾——TopoFrame
Panel 类型的,建议命名以Panel 结尾——CreateCircuitPanel
Bean 类型的,建议命名以Bean 结尾——DataAccessBean
EJB 类型的,建议命名以EJB 结尾——DBProxyEJB
Applet 类型的,建议命名以Applet 结尾——PictureShowApplet

2.1.2.10 准确地确定成员函数的存取控制符号:只是该类内部调用的函数使用 private 属性,继承类可以使用的使用protected属性,同包类可以调用的使用默认属性(不加属性控制符号),对外公开的函数使用public属性。【建议】

2.1.2.11 含有集合意义的属性命名,尽量包含其复数的意义【建议】
示例:
customers, orderItems

2.1.3 注释
2.1.3.1 源程序注释量必须在30%以上。【规则】
说明:由于每个文件的代码注释不一定都可以达到30%,建议以一个系统内部模块作为单位进行检查

2.1.3.2 包的注释(公共模块强制要求)。【建议】
写入一个名为 package.html 的HTML格式的说明文件放入包所在路径。包的注释内容:简述本包的作用、详细描述本包的内容、产品模块名称和版本。


一句话简述。

详细描述。

产品模块名称和版本

公司版权信息


2.1.3.3 类和接口的注释放在class 或者 interface 关键字之前,import 关键字之后。注释主要是一句话功能简述与功能详细描述。类注释使用“/* /”注释方式.【建议】
说明:方便JavaDoc收集,没有import可放在package之后。注释可根据需要列出:作者、内容、功能、与其它类的关系等。功能详细描述部分说明该类或者接口的功能、作用、使用方法和注意事项,每次修改后增加作者和更新版本号和日期,@since 表示从那个版本开始就有这个类或者接口,@deprecated 表示不建议使用该类或者接口。

/**
* 〈一句话功能简述〉
* 〈功能详细描述〉
* @author [作者](可选)
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
* @deprecated (可选)
*/

示例:
package com.xxx.xxx.xxx;

import java.util.*;

/**
* LogManager 类集中控制对日志读写的操作。
* 全部为静态变量和静态方法,对外提供统一接口。分配对应日志类型的读写器,
* 读取或写入符合条件的日志纪录。
* @author 张三,李四,王五
* @see LogIteraotor
* @see BasicLog
* @since CommonLog1.0
*/
public class LogManager

2.1.3.4 方法注释采用标准的javadoc注释规范,注释中必须提供方法说明,参数说明和返回值说明。【规则】
如:
/**
* The doGet method of the servlet.
* This method is called when a form has its tag value method
* equals to get.
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doGet (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}

2.1.3.5 注释应与其描述的代码相近,对代码的注释应放在其上方,并与其上面的代码用空行隔开,注释与所描述内容进行同样的缩排。【规则】

/*
* 注释
*/
public void example2() {
// 注释
CodeBlock One

// 注释
CodeBlock Two

}

/*
* 注释
*/
public void example() {
// 注释
CodeBlock One

// 注释
CodeBlock Two

}

2.1.3.6 修改代码时候必须仔细阅读和修改附近的代码注释;如果在函数前有函数体注释,必须更新函数注释。不在有用的注释要删除。【规则】

2.1.3.7 注释的内容要清楚、明了,含义准确,防止注释二义性。【规则】
说明:错误的注释不但无益反而有害。

2.1.3.8 在代码的功能、意图层次上进行注释,提供有用、额外的信息。【规则】
说明:注释的目的是解释代码的目的、功能和采用的方法,提供代码以外的信息,帮助读者理解代码,防止没必要的重复注释信息。
示例:
如下注释意义不大。
// 如果 receiveFlag 为真
if (receiveFlag)

而如下的注释则给出了额外有用的信息。
// 如果从连结收到消息
if (receiveFlag)

2.1.3.9 对关键变量的定义和分支语句(条件分支、循环语句等)必须编写注释。【规则】
说明:这些语句往往是程序实现某一特定功能的关键,对于维护人员来说,良好的注释帮助更好的理解程序,有时甚至优于看设计文档。

2.1.3.10 方法内的单行注释使用 //【规则】
说明:调试程序的时候可以方便的使用 /* 。。。*/ 注释掉一长段程序。

2.1.3.11 使用Html标签使JavaDoc生成更加美观。【建议】【公共模块强制规则】

2.1.4 常量与变量
2.1.4.1 具有全局性逻辑功能的常量值需要定义为常量,而不要将数值直接出现在代码中。此外程序中多处使用到的常量一定要在公共文件中进行定义,并且必须使用该常量进行赋值。【规则】
说明:避免魔鬼数字,魔鬼数字经常会引起维护不当,引起严重bug。
如:
public static final int MAX_VALUE = 100;
……
System.out.println(MAX_VALUE);

2.1.4.2 一行一个声明,避免在一个语句中给多个变量赋值。【规则】
如:
int indexBegin = indexEnd = 0; //!!!避免使用
indexBegin = 5; indexEnd = 10; //!!!避免使用

2.1.4.3 数组定义方法如下: 数组元素类型紧跟着”[]”,其后是数组标识。【规则】
如:
byte[] buffer = null; //提倡的使用
byte buffer[] = null; //!避免使用

2.1.5 函数
2.1.5.1 函数划分原则【规则】
a)按照逻辑功能合理划分函数。
b)避免重复代码。在多个地方需要重复使用的代码,使用独立的函数来封装。

2.1.5.2 尽量控制函数总长度小于150行。当一个函数代码超过150行,一般将其中相对独立的功能使用单独的函数来实现。【规则】
说明:太长的函数给维护带来很大成本。

2.1.5.3 设计代码时,尽量减少函数入口、出口参数的数量,以及各个参数所代表含义的复杂度。【建议】

2.1.5.4 判断函数入口参数的合法性,特别是public和protected的函数,一定要检查入口参数是否合法。【规则】
public static String getStringWithLen(String str, int len) {
if((str != null) && (str.length() > len)){
str = str.substring(0, len);
}
return str;
}

2.1.5.5 使用一个由其他函数返回的对象之前,先判断是否为null,以免产生NullPointerException 异常
如:
//不规范写法:
User user = getUser();
System.out.print(user.getName());

//应写为:
User user = getUser();
if(user == null) {
//提示错误
……
} else {
System.out.print(user.getName());
}

2.1.5.6 不要在函数中对函数的参数进行赋值。【规则】
说明:private String getCustomerIdsFromFormattedArray(Object object) ,不要在函数体中使用“object =”之类的赋值语句,在函数返回后,参数的值实际上不会改变。

2.1.5.7 只公布必须公布的方法,尽量使方法私有化。【建议】
说明:只公布自己必须公布的,就可放心大胆地改变其他任何东西。如果修改一个没有必要公开的方法,就可能破坏其他人现有的代码,使他们不得不重新编写和设计。

2.1.6 编码原则
2.1.6.1 尽量使用接口而不是一个具体的类。【建议】
例如有以下需求:给定一个SQL语句,返回一个对象的列表,实现中用java.util.ArrayList实现,于是定义方法为:
public java.util.ArrayList getObjectItems(String sql){
……
}
上面的方法存在一个问题,当getObjectItems内改用Vector或LinkedList实现,外部类必须做相应更改。一个更好的方法是定义返回值为java.util.AbstractList更合适:
public java.util.AbstractList getObjectItems(String sql){
……
}
这样即使更改实现,外部类也不必做相应更改。

2.1.6.2 对于可能发生异常的代码,都应在尽可能低的层次进行捕获。若低层不知如何处理,则将异常继续抛给高层处理,但最终必须得到处理。【规则】

2.1.6.3 程序的逻辑不要依赖于一个异常【规则】
说明:程序逻辑依赖于一个异常的话,很容易破坏程序逻辑,而且不便于阅读和维护。
比如:
int result = -1;
try {
……
result = func(); // 此函数会抛出异常。
……

} catch (Exception e) {

}
return result;
以上代码不是很好理解,也不太方便维护。如果代码量打的话,也很难看出func函数会抛出异常。当维护前后代码的时候。很容易造成错误。

应该改为:
int result = -1;
……
try {
result = func(); // 此函数会抛出异常。
} catch (Exception e) {
result = xxx?;
}
……

return result;

或者直接把异常捕获到 func 函数中。

2.1.6.4 防止下标越界,在使用数组下标之前先判断下标的合法性,比如数组类型,集合类型。【规则】
如:
// 以下为不规范的写法:
String[] ary = getAry();
System.out.print(ary[2]);

// 应写为:
String[] ary = getAry();
if ((ary != null) && (ary.length > 2)){
System.out.print(ary[2]);
}

2.1.6.5 尽量使用Java 5.0新循环写法。(5.0+)【建议】
说明:代码更加简洁,也更安全。
示例:
ArrayList list = new ArrayList();
list.add…
for(String str:list) {
System.out.println(str);
}

2.1.6.6 谨防数据类型越界。【规则】
如:
int milsec = 25 * 86400 * 1000;
System.out.println(milsec);
// 打印结果是-2134967296 (超过int最大值范围2147483647)

2.1.6.7 数据库操作、IO操作等需要使用结束close()的对象必须在try -catch-finally 的finally中close(),如果有多个IO对象需要close(),需要分别对每个对象的close()方法进行try-catch,防止一个IO对象关闭失败其他IO对象都未关闭。【规则】
示例:
try
{
// … …
}
catch(IOException ioe)
{
//… …
}
finally
{
try
{
out.close();
}
catch (IOException ioe)
{
//… …
}

try
{
in.close();
}
catch (IOException ioe)
{
//… …
}

}

2.1.6.8 循环编程:尽量选取for循环而不是while循环;如果使用while循环,最好能用iterator;while循环的终止条件需慎重,以避免死循环的可能。【建议】
如:
/* 不正确的用法:当interval取零或者负数时将可能出现死循环 */
while (i <= max) {
i += interval;
}

2.1.6.9 字符串比较时,将常量置于equals之前,避免null异常。【规则】

2.1.6.10 一般而言,在含有多种运算符的表达式中使用圆括号来避免运算符优先级问题,是个好方法。即使运算符的优先级对你而言可能很清楚,但对其他人未必如此。你不能假设别的程序员和你一样清楚运算符的优先级。【建议】
if (a == b && c == d) //!!!避免使用
if ((a == b) && (c == d)) //正确的使用方法

2.1.6.11 系统非正常运行产生的异常捕获后,如果不对该异常进行处理,则应该记录日志。 【规则】
说明:此规则指通常的系统非正常运行产生的异常,不包括一些基于异常的设计。若有特殊原因必须用注释加以说明。
如果不输出log,不方便问题定位,
示例:
try
{
//…. …
}
catch (IOException ioe)
{
logger.error(ioe);
}

2.1.6.12 自己抛出的异常必须要填写详细的描述信息。【规则】
说明:便于问题定位。
示例:
throw new IOException(“Writing data error! Data: ” + data.toString());

2.1.6.13 运行时异常使用RuntimeException的子类来表示,不用在可能抛出异常的方法声明上加throws子句。非运行期异常是从Exception继承而来的,必须在方法声明上加throws子句。【规则】
说明:
非运行期异常是由外界运行环境决定异常抛出条件的异常,例如文件操作,可能受权限、磁盘空间大小的影响而失败,这种异常是程序本身无法避免的,需要调用者明确考虑该异常出现时该如何处理方法,因此非运行期异常必须有throws子句标出,不标出或者调用者不捕获该类型异常都会导致编译失败,从而防止程序员本身疏忽。
运行期异常是程序在运行过程中本身考虑不周导致的异常,例如传入错误的参数等。抛出运行期异常的目的是防止异常扩散,导致定位困难。因此在做异常体系设计时要根据错误的性质合理选择自定义异常的继承关系。
还有一种异常是Error 继承而来的,这种异常由虚拟机自己维护,表示发生了致命错误,程序无法继续运行例如内存不足。我们自己的程序不应该捕获这种异常,并且也不应该创建该种类型的异常。

2.1.6.14 在程序中使用异常处理还是使用错误返回码处理,根据是否有利于程序结构来确定,并且异常和错误码不应该混合使用,推荐使用异常。【规则】
说明:
一个系统或者模块应该统一规划异常类型和返回码的含义。
但是不能用异常来做一般流程处理的方式,不要过多地使用异常,异常的处理效率比条件分支低,而且异常的跳转流程难以预测。

2.1.6.15 避免使用不易理解的数字,用有意义的标识来替代。涉及物理状态或者含有物理意义的常量,不应直接使用数字,必须用有意义的静态变量或者枚举来代替。使用异常来表示方法执行错误,而不是使用其他语言的错误返回码方式。【规则】
示例:如下的程序可读性差。
if (state == 0)
{
state = 1;
… // program code
}
应改为如下形式:
private final static int TRUNK_IDLE = 0;
private final static int TRUNK_BUSY = 1;
private final static int TRUNK_UNKNOWN = -1;

if (state == TRUNK_IDLE)
{
state = TRUNK_BUSY;
… // program code
}

异常:
public void function()
{

throw new RuntimeException(“。。。”);
}

2.1.6.16 不要使用 System.out 与 System.err 进行控制台打印,应该使用工具类(如:日志工具)进行统一记录或者打印。【规则】
说明:代码发布的时候可以统一关闭控制台打印,代码调试的时候又可以打开控制台打印,方便调试。

2.1.6.17 用调测开关来切换软件的DEBUG版和正式版,而不要同时存在正式版本和DEBUG版本的不同源文件,以减少维护的难度。【规则】
说明:其他类似功能同样试用,尽量减少维护成本。

2.1.6.18 集合必须指定模板类型(5.0+)【规则】
说明:方便程序阅读,除去强制转换代码
示例:
Map

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值