前言
在项目开发中,拥有统一且得到大家认可的规范是非常重要的,一个好的开发规范不仅可以降低开发人员之间的沟通成本,同时也能减少代码出错的可能。
完全靠自己定义一套完整的开发规范是比较困难的,幸运的是,现在很多大厂都有公开自己在生产环境中使用到的开发规范,我们可以参考这些规范并结合我们自己的经验,总结出属于我们自己的开发规范,下面是我自己整理的开发规范。
我整理的这套规范是参考阿里提供的java开发规范以及Blankj整理的Android开发规范定制的。之所以使用阿里的规范,主要是阿里提供了一套代码规范的检查插件,支持eclipse和android studio,所以在使用上会比较方便。
目录
- 代码规范
- 编码格式
- 命名
- 方法参数
- 异常处理
- 集合处理
- 控制语句
- 注释
- 单元测试
- 流程规范
- gitlab项目分支管理
- 协同开发
- 常用工具
- 附录
代码规范
编码格式
由于我们开发环境所在的系统有Windows、Ubuntu、Mac os等,虽然都是使用Android stuido,但是编码格式还是略有不同的,尤其是换行符,android studio默认的换行符使用的是和系统保持一致,这样就往往造成一个文件在不同平台被打开后得到的md5不同,这就容易造成校验问题。
因此我们统一使用unix风格换行符,这个可以在Android studio:settings->Editor->Code Style->Line separateor设置为unix or OS X。文件编码统一使用UTF-8格式。
命名
- 除了临时变量外,其他命名都应该尽可能使用有意义的名字。
- 类名、成员变量、局部变量、方法名统一使用驼峰式命名。
- 常量使用全大写,不同词之间使用下划线分割。
- 除POJO类的成员外【因为POJO类一般都需要生产get、set方法,如果加上m后会变成setmXXX、getmXXX,这样会不好看,因此凡事需要生成get、set方法的变量,建议都不加这些前缀】,成员变量命名需要加m前缀,静态变量命名需要加s前缀,枚举类型、UI控件变量命名需要加上对应类型的缩写,具体UI控件缩写对照表参照附录。
- activity、fragment、service、BroadcastReceiver、ContentProvider等类的定义需要在类名后加上类型标识,类型标识对照表参照附录。
- 布局文件应该使用layout、activity、fragment等前缀表示该布局文件是什么类型的布局文件。
方法参数
- 构造方法的参数多于4个的时候必须使用builder模式来构造,增加可拓展性同时还避免因为参数过多导致用户输入参数顺序错乱而造成的bug。
- 普通方法参数多于4个的时候建议将参数集合封装成一个内部类,将内部类作为参数来传递。
- 对于public的方法必须做参数校验,private等方法则是情况而定。
- 对于调用者而言,调用public的方法应该保证输入的参数是合规的。
- 方法定义时应该使用注解@Nullable、@NonNull来标明参数以及返回值是否可以为空,如果返回值为空则应该在注释中说明什么情况下回为空。
- 如果传递的参数是一个常量集合,应该将该参数定义成一个枚举类型。
- 当返回类型时集合类型的时候,尽量不要返回null,而是返回一个空集合。
异常处理
- 在开发中应该慎用异常,尤其不应该将异常作为逻辑处理中的一部分。
- 抛出的异常类型应该与异常的发生条件一致,如:当发生数组越界异常时我们不应该抛出NPE异常,同时主动抛出的异常应该首先寻找系统是否有对应的异常类,如果没有才考虑自定义异常。
- 抛出异常时应该在注释中明确说明什么情况下会抛出这个异常,如果希望外部捕获这个异常,则应该在方法定义时使用throw 关键字抛出。
集合处理
- ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException异常,即java.util.RandomAccessSubList cannot be cast to java.util.ArrayList。
- 当集合的key是一个自定义类型的时候,一定要重写hashCode 和 equals方法。
- 使用集合转数组的方法,必须使用集合的toArray(T[] array),传入的是类型完全一样的数组,大小就是 list.size()【因为如果使用不带参数的方法会涉及到强转,有可能出现ClassCastException异常,如果传入的数组长度小于集合长度,则内部会重新new一个数组,造成不必要的开销,如果传入的数组长度大于集合长度,则多出的部分会被赋值为空,容易造成之后遍历时出现NPE异常】。
- 使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方 法,它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。
- 不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator方式,如果并发操作,需要对 Iterator 对象加锁。
- 集合初始化时,指定集合初始值大小。
控制语句
- 遍历一个集合的时候,如果集合元素是一个自定义类型,则需要对遍历中的每个元素进行判空处理。
- 尽量不要在循环体内做大量重复且耗时的操作,如枷锁、调用io打印log等,循环体往往是速度优化的关键点。
- 如果使用else if结构,则一定要写else代码块,尽管else代码块可能为空,这样可以保证逻辑完整性,不容易出现未考虑的情况。
- 在switch语句中,每个case都应该写return或者break,如果不写则应该加注释说明理由,另外不可缺少default代码块。
注释
- 类注释、成员注释都应该使用块注释的方式来表示。
- public方法必须加注释,注释应该包含方法描述,主要描述该方法是做什么用的,而不是怎么做的,同时还需要包含每个参数的说明,以及返回值的说明,如果方法内部回抛出异常,则还需要在注释中提及原因。
- 注释应该独占一行,位于代码上一行,不应位于代码末端。
单元测试
- 单元测试在开发中应该是必须的,要求是:单元测试需要覆盖项目70%的代码,关键方法和模块需要100%覆盖。
流程规范
gitlab项目分支管理
- 之大致就是每个task或者fix bug都应该首先从master分支新建一个版本分支如v1.0.0,再从版本分支新建一个dev分支如dev_v1.0.0,当开发完成后提交merge request从dev_v1,.0.0合到版本分支v1.0.0中,然后提交测试,当测试通过后再将版本分支v1.0.0合入master分支,此时的dev分支可以删除。
- 提交git前都应该对代码进行格式化:Code->Reformat Code,可以勾选Optimize Imports,将多于的import给删除。
协同开发
开发流程图.png- 常见的开发工作方式一般是需求分析、架构设计、模块设计、功能设计、功能实现、功能测试、产品发布都是由我们特定的开发者开单独完成,且这整个过程中没有其他人参与讨论,使得最终实现的产品好坏、性能优劣都是跟某一个人的开发经验以及技术高低相挂钩,并且由于项目开发中往往没有文档留存,使得后续很难被其他人接手维护。敏捷开发不代表不需要文档,同时一个优秀的程序猿不但要拥有优秀的编码能力,还应该写的一手好文档,所以无论是为了项目还是为了我们自己,我们都应该书写项目开发中必要的文档和设计图,如:项目描述文档【描述项目的需求和项目开发使用到的环境、依赖库及对应的版本等】、项目架构图【描述架构划分以及每个模块之间的相互关系】、模块设计图【描述模块内的具体设计】、关键功能的流程图、测试用例【单元测试回用到,跟功能相关】。
- 在gitlab项目管理中有一个很重要的角色assignee,这个角色不应该只参与代码review,还应该参与到整个开发过程中,该角色是实际项目开发的partner,他不需要真正参与项目的编码工作,但是在项目需求分析梳理、程序设计、代码review、功能测试中都应该起到支持和监督的作用。
- 我觉得比较好的方式是:当一个新的项目启动的时候应该由developer和他的partner进行需求分析、架构设计、模块设计,然后将这些分析文档化,再召集更多技术栈相关的人员一起梳理和分析一次,接着再由developer根据讨论的结果修改架构和模块设计,然后在继续跟partner完成功能设计和测试用例设计,接着再由developer完成功能实现,自测无误后在提交merge request,和partner一起将代码review,无误后在提交测试,测试完成后再将版本发布。
常用工具 更多
Android studio插件
- Alibaba Code Guidelines 代码规范检验插件
- FindBugs-IDEA 代码优化插件
在线工具
- JSONSchema2POJO 在线json字符串转javaBean,支持各种json解析器,强大好用
- draw 在线流程图编辑工具,国外网站速度慢
- processon 在线流程图编辑工具,国内网站速度快
调试工具
- Android Debug Database 数据库查看编辑工具
- LeakCanary 内存泄漏分析工具
优化功能
- Drawable Optimizer 图片压缩体积工具
附录
类型标识对照表
类 | 描述 | 例如 |
---|---|---|
Activity 类 |
Activity 为后缀标识 |
欢迎页面类 WelcomeActivity
|
Adapter 类 |
Adapter 为后缀标识 |
新闻详情适配器 NewsDetailAdapter
|
解析类 |
Parser 为后缀标识 |
首页解析类 HomePosterParser
|
工具方法类 |
Utils 或 Manager 为后缀标识 |
线程池管理类:ThreadPoolManager 日志工具类: LogUtils (Logger 也可)打印工具类: PrinterUtils
|
数据库类 | 以 DBHelper 后缀标识 |
新闻数据库:NewsDBHelper
|
Service 类 |
以 Service 为后缀标识 |
时间服务 TimeService
|
BroadcastReceiver 类 |
以 Receiver 为后缀标识 |
推送接收 JPushReceiver
|
ContentProvider 类 |
以 Provider 为后缀标识 |
ShareProvider |
自定义的共享基础类 | 以 Base 开头 |
BaseActivity , BaseFragment
|
UI 控件缩写表
名称 | 缩写 |
---|---|
Button | btn |
CheckBox | cb |
EditText | et |
FrameLayout | fl |
GridView | gv |
ImageButton | ib |
ImageView | iv |
LinearLayout | ll |
ListView | lv |
ProgressBar | pb |
RadioButtion | rb |
RecyclerView | rv |
RelativeLayout | rl |
ScrollView | sv |
SeekBar | sb |
Spinner | spn |
TextView | tv |
ToggleButton | tb |
VideoView | vv |
WebView | wv |
常见的英文单词缩写表
名称 | 缩写 |
---|---|
average | avg |
background | bg(主要用于布局和子布局的背景) |
buffer | buf |
control | ctrl |
current | cur |
default | def |
delete | del |
document | doc |
error | err |
escape | esc |
icon | ic(主要用在 App 的图标) |
increment | inc |
information | info |
initial | init |
image | img |
Internationalization | I18N |
length | len |
library | lib |
message | msg |
password | pwd |
position | pos |
previous | pre |
selector | sel(主要用于某一 view 多种状态,不仅包括 ListView 中的 selector,还包括按钮的 selector) |
server | srv |
string | str |
temporary | tmp |
window | win |
程序中使用单词缩写原则:不要用缩写,除非该缩写是约定俗成的。
网友评论