从这篇文章开始我们暂停一下对android源码的分析,开始讲一下android产品研发中一些常用的技术,技巧,方法,实践等姿势。这里需要强调的是我们所讲解的这些东西可能对产品开发中比较常用的,因为对于项目开发中,可能更多的强调管理,进度方法的东西,对工程化的东西比较强调,而我们这里更多的是对产品技术方面的归纳总结。
而本文中选择将开发规范作为这个系列的第一篇文章,就是个人感觉产品研发过程中,开发规范真的很重要,很重要,非常重要(重要的事情说三遍),一个好的开发规范可以让团队中的人对他人的代码更熟悉,新人也可以更好的了解产品的业务逻辑。开发规范并不是一个死的一成不变的,每个团队可能都有自己的开发规范,只要是适合团队的开发规范就是最好的开发规范。
所以本文中所讲解的开发规范只能是抛砖引玉,有可取的地方可以借鉴,引用,不能照搬全抄不假思索,毕竟不同的团队有不同的实际情况。最好的方式就是可以根据本文的开发规范总结出自身团队比较适合的规范流程。
好吧,废话不多说了,下面我们就介绍一下我在实践中总结的android开发规范。
编码规范对于程序员而言尤为重要,有以下几个原因:
* 一个软件的生命周期中,80%的花费在于维护
* 几乎没有任何一个软件,在其整个生命周期中,均由最初的开发人员来维护
* 编码规范可以改善软件的可读性,可以让程序员尽快而彻底地理解新的代码
* 如果你将源码作为产品发布,就需要确任它是否被很好的打包并且清晰无误,一如你已构建的其它任何产品
* 减少维护花费
* 提高可读性
* 加快工作交接
* 减少名字增生
* 降低缺陷引入的机会
常量命名规范
常量用于保存需要常驻内存中并且经常使用变化不多的数据,定义常量的名称的时候需要遵循望文知意的原则;
代码中涉及到直接使用某个字符串或者其他基本类型的值时,建议定义成常量,避免多处直接使用同样的值作为参数。
变量命名规范
变量用于保存系统中的临时数据,变量命名时遵循望文知意,简单明了,驼峰标示等原则。
无
方法命名规范
方法名的命名应该遵循简单明了的原则;
类命名规范
类名主要表示一个类的作用,需要简明扼要,望文知意,并且首字母大写。
无
接口命名规范
接口命名需要简单明了,长度不宜过长;
包名规范
用于分类管理类文件;
无
无
目录名称规范
主要是一些jar包,so文件的配置目录名称;
无
布局文件名称规范
主要包含资源文件的命名问题;
无
如:如定义H5Activity的xml文件名称,则可以定义为h5.xml;尽量不使用大写字母等。
drawable文件名称命名规范
主要包含资源文件的命名问题;
无
无
资源ID命名规范
各种资源ID的定义问题;
可以考虑按照组件的名称的缩写作为前缀,(同一个xml文件中ID名称不能重复)如:组件简写(大写字母缩写)_业务名称
TextView的组件:tv_pay_money
Button的组件:btn_pay_money
EditText的组件:et_user_name
LinerLayout组件:ll_container
如:比如一个textview组件,可点击用于支付的按钮,则可以把ID定义为: tv_pay_money;
在类、接口定义之前当对其进行注释,包括类、接口的目的、作用、功能、继承于何种父类,实现的接口、实现的算法、使用方法、示例程序等。
/**
* author:作者
* time:时间
* desc:描述
*/
方法注释的模板:
/**
* desc:描述
* @param 参数名 参数描述
* @param 参数名2 参数描述
* @return 返回值类型说明
* @throws Exception 异常说明
*/
成员变量和常量需要使用如下注释的形式,注释位于变量的上侧;
/**
*
**/
内部逻辑注释模板:
//支付成功
if (response.getRet() == 0) {
Toast.makeText(H5Activity.this, "支付成功", Toast.LENGTH_LONG).show();
goToNext(response);
}
//支付失败
else if (response.getRet() == -1) {
Toast.makeText(H5Activity.this, "支付失败", Toast.LENGTH_LONG).show();
//刷新当前页面
reflush(currentUrl);
}
在一个典型的Activity中代码的顺序如下:
/**
* author:sh
* desc:该class的作用
* time:yyyy-MM-dd
**/
public class ClassName {
//(1) 成员变量集合
//(2) 回调方法集合
若该类为activity,则:onCreate、**、onDestory;
若该类为Fragment、则:onCreateView、**、onDestory;
//(3) 其他方法集合
}
左大括号不换行,右大括号换行;
class MyClass {
int func() {
if (something) {
// ...
} else if (somethingElse) {
// ...
} else {
// ...
}
}
}
if (condition) {
body();
} // 推荐
if-else语句应该具有如下格式:
if (condition) {
statements;
}
if (condition) {
statements;
} else {
statements;
}
if (condition) {
statements;
} else if (condition) {
statements;
} else{
statements;
}
注意:if语句总是用”{“和”}“括起来,避免使用如下容易引起错误的格式:
if (condition) // 避免
statement;
一个for语句应该具有如下格式:
for (initialization; condition; update) {
statements;
}
当在for语句的初始化或更新子句中使用逗号时,避免因使用三个以上变量,而导致复杂度提高。
若需要,可以在for循环之前(为初始化子句)或for循环末尾(为更新子句)使用单独的语句。
一个while语句应该具有如下格式:
while (condition) {
statements;
}
do {
statements;
} while (condition);
一个switch语句应该具有如下格式:
switch (condition) {
case ABC:
statements;
/* falls through */
case DEF:
statements;
break;
case XYZ:
statements;
break;
default:
statements;
break;
}
每当一个case顺着往下执行时(因为没有break语句),通常应在break语句的位置添加注释。
定义异常的时候,异常的后缀名称以Exception结尾,及**Exception;
尽量英文描述,简单明了;
一个try-catch语句应该具有如下格式:
try {
statements;
} catch (ExceptionClass e) {
statements;
}
try {
statements;
} catch (ExceptionClass e) {
statements;
} finally {
statements;
}
一般来说源文件的行数不能大于2K行,过多的话可以考虑拆分功能,拆分函数等;
在系统中需要打印LOG的时候,尽量使用自定义的LOG,自定义的LOG在开发环境的时候会打印日志,正式环境的时候不会打印日志。
在系统打印LOG的时候,使用TAG尽量使用tab,同意的TAG标志。
本文以同步至github中:https://github.com/yipianfengye/androidProject,欢迎star和follow