前言
在开发中,一个良好的开发习惯以及一个开发规范可能会让你少走很多弯路,也会一定程度上的提高代码的可读性,可维护性和可拓展性。当随着需求的不断变更,需要维护项目的时候。当随着项目的代码量的提升,需要重构的时候。你会明白一个好的开发规范多么多么的重要。
命名规范
基本命名规范
1.包命名规范
Java包的名字都是由小写单词组成。但是由于Java面向对象编程的特性,每一名Java程序员都可以编写属于自己的Java包,为了保障每个Java包命名的唯一性,在最新的Java编程规范中,要求程序员在自己定义的包的名称之前加上唯一的前缀。由于互联网上的域名称是不会重复的,所以程序员一般采用自己在互联网上的域名称作为自己程序包的唯一前缀。
例如: net.frontfree.javagroup
• 包名全部采用小写
• 主包名采用[公司性质].[公司名称].[项目名称]的命名方式
包名 此包中包含
com.xx.应用名称缩写.activities 页面用到的Activity类 (activities层级名用户界面层)
com.xx.应用名称缩写.base 页面中每个Activity类共享的可以写成一个i额BaseActivity类 (基础共享的类)
com.xx.应用名称缩写.adapter 页面用到的Adapter类 (适配器的类)
com.xx.应用名称缩写.tools 此包中包含:公共工具方法类(tools模块名)
com.xx.应用名称缩写.bean
(或则 com.xx.应用名称缩写.unity ) 此包中包含:元素类
com.xx.应用名称缩写.db 数据库操作类
com.xx.应用名称缩写.view
(或则 com.xx.应用名称缩写.ui ) 自定义的View类等
com.xx.应用名称缩写.service Service服务
com.xx.应用名称缩写.broadcast Broadcast服务
如果根据不同情况进行分包的话,可以将包名分别命名为util,view, adapter等。
2.类的命名
类的名字必须由大写字母开头而单词中的其他字母均为小写;如果类名称由多个单词组成,则每个单词的首字母均应为大写例如TestPage;如果类名称中包含单词缩写,则这个所写词的每个字母均应大写,如:XMLExample,还有一点命名技巧就是由于类是设计用来代表对象的,所以在命名类时应尽量选择名词。
例如: Circle
类 描述 例如
activity 类 Aty或者Activity为后缀标识 欢迎页面类WelcomeAty.或者WelcomeActivity
Adapter类 Adp或者Adapte 为后缀标识 新闻详情适配器NewtDetailAdp或则直接 NewDetailAdapter
解析类 Hlr为后缀标识 首页解析类HomePosterHlr
公共方法类 Tools或Manager为后缀标识 线程池管理类:ThreadPoolManager
日志工具类:LogTools
数据库类 以DBHelper后缀标识 新闻数据库:NewDBHelper
Service类 以Service为后缀标识 时间服务TimeService
BroadcastReceive类 以Broadcast为后缀标识 时间通知TimeBroadcast
ContentProvider 以Provider为后缀标识
直接写的共享基础类 以Base开头 BaseActivity,BaseFragment
3.方法的命名
方法的名字的第一个单词应以小写字母作为开头,后面的单词则用大写字母开头。
例如: sendMessge
方法 说明
initXX() 初始化相关方法,使用init为前缀标识,如初始化布局initView()
isXX() checkXX()方法返回值为boolean型的请使用is或check为前缀标识
getXX() 返回某个值的方法,使用get为前缀标识
processXX() 对数据进行处理的方法,尽量使用process为前缀标识
displayXX() 弹出提示框和提示信息,使用display为前缀标识
saveXX() 与保存数据相关的,使用sav为e前缀标识
resetXX() 对数据重组的,使用reset前缀标识
clearXX() 清除数据相关的
removeXXX() 清除数据相关的
drawXXX() 绘制数据或效果相关的,使用draw前缀标识
4.常量的命名
常量的名字应该都使用大写字母,并且指出该常量完整含义。如果一个常量名称由多个单词组成,则应该用下划线来分割这些单词。
例如: MAX_VALUE
5.注释
软件文档以两种形式存在:外部的和内部的。外部文档(如规范、帮助文件和设计文档)在源代码的外部维护。内部文档由开发人员在开发时在源代码中编写的注释组成。
不考虑外部文档的可用性,由于硬拷贝文档可能会放错地方,源代码清单应该能够独立存在。外部文档应该由规范、设计文档、更改请求、错误历史记录和使用的编码标准组成。 以下几点是规范的注释方法:
(1)一个工程应有一个统一的头文件注释,以说明整个工程的信息、创建日期、版本等等
(2)对重要的程序加注释进行说明
(3)修改代码或删除时,将原代码用注释的方法屏蔽,同时要加开发者自身对修改操作的注释。格式为:
//原代码
//Added/(Modified/ Deleted) by 开发者姓名 年-月-日;
//因为业务原因修改的,要注明修改或删除原因)
例如:
/**
* This is an example of
* Javadoc
*
* @author xuchangbing
* @version 0.1, 01/01/2017
新代码
(4)使用XML文档格式,如下面方法的注释:
///
/// 得到某人的年龄
///
/// 用户名
/// 用户年龄
public int GetUserAge(string userName)
{
//
//此处写你的程序代码
//
}
(5)避免杂乱的注释,而是应该使用空白将注释同代码分开。
(6)移除所有临时或无关的注释,以避免在日后的维护工作中产生混乱。
(7)注释应对代码进行准确的说明,不应存在歧义。
(8)在整个应用程序中,使用具有一致的标点和结构的统一样式来构造注释。
分类命名规范
1.基本数据类型命名规范
Integer:int+描述 Char:chr+描述 Boolean:bln+描述
Long:lng+描述 Short:shr +描述 Double:dbl+描述
String:str+描述 Float:flt+描述 Single:sng+描述
DataTime:dt+描述 Array:arr+描述 Object:obj+描述
如:String srtName;
2.变量命名规范
变量命名:前缀+类型描述+意义描述
前缀:
成员变量:m_*** 局部变量:l_*** 形参:a_***
常量:大写_*** 枚举值:em_***
5.控件命名规范
TextView :txt_+描述 Button :btn_+描述
ImageButton :ib_+描述 ImageView :img_+描述
CheckBox :chk_+描述 RadioButton :rb_+描述
AnalogClock :ac_+描述 DigitalClock :dc_+描述
DatePicker :dp_+描述 TimePicker :tp _+描述
ToggleButton :tb_+描述 EditText:edit_+描述
ProgressBar:pb_+描述 SeekBar:sb _+描述
AutoCompleteTextView:autotxt_+描述 MultiAutoCompleteTextView:mlautotxt_+描述
ZoomControls:zc_+描述 Include:ind_+描述
VideoView:vv_+描述 WebView:wv_+描述
RatingBar:ratbr_+描述 Tab:tab__+描述
Spinner:spin_+描述 Chronometer:chro_+描述
ScrollView:sv_+描述 TextSwitcher:tswi_+描述
Gallery:gal_+描述 ImageSwitcher:imgswi_+描述
GridView:gv_+描述 ListView:lv_+描述
ExpandableList: exl_+描述 MapView: mv_+描述
控件说明如下:
• TextView - 文本显示控件
• Button - 按钮控件
• ImageButton - 图片按钮控件
• ImageView - 图片显示控件
• CheckBox - 复选框控件
• RadioButton - 单选框控件
• AnalogClock - 钟表(带表盘的那种)控件
• DigitalClock - 电子表控件
• DatePicker - 日期选择控件
• TimePicker - 时间选择控件
• ToggleButton - 双状态按钮控件
• EditText - 可编辑文本控件
• ProgressBar - 进度条控件
• SeekBar - 可拖动的进度条控件
• AutoCompleteTextView - 支持自动完成功能的可编辑文本控件
• MultiAutoCompleteTextView - 支持自动完成功能的可编辑文本控件,允许输入多值(多值之间会自动地用指定的分隔符 分开)
• ZoomControls - 放大/缩小按钮控件
• Include - 整合控件
• VideoView - 视频播放控件
• WebView - 浏览器控件
• RatingBar - 评分控件
• Tab - 选项卡控件
• Spinner - 下拉框控件
• Chronometer - 计时器控件
• ScrollView - 滚动条控件
• TextSwitcher - 文字转换器控件(改变文字时增加一些动画效果)
• Gallery –画廊控件
• ImageSwitcher - 图片转换器控件(改变图片时增加一些动画效果)
• GridView - 网格控件
• ListView - 列表控件
• ExpandableList - 支持展开/收缩功能的列表控件
编程规范
• 源文件编码格式为 UTF-8。
• java代码中不出现中文,最多注释中可以出现中文
• 服务端可以实现的,就不要放在客户端
• 引用第三方库要慎重,避免应用大容量的第三方库,导致客户端包非常大
• 处理应用全局异常和错误,将错误以邮件的形式发送给服务端
• 图片的.9处理
• 使用静态变量方式实现界面间共享要慎重
• 单元测试(逻辑测试、界面测试)
• 不要重用父类的handler,对应一个类的handler也不应该让其子类用到,否则会导致message.what冲突
• activity中在一个View.OnClickListener中处理所有的逻辑
• strings.xml中使用%1$s实现字符串的通配
• 数据一定要效验,例如字符型转数字型,如果转换失败一定要有缺省值;服务端响应数据是否有效判断
• 对于未完成的方法,使用TODO加以标记
• 若功能已完成,但存在效率等潜在问题时,使用XXX加以标记
• 若代码存在严重问题或仅用于调试,使用FIXME加以标记
• values目录下文件名称较固定,不得随意更改
代码提交规范
我们使用的无论是git,还是svn都需要遵守下面这些规范。
• 工作目录要及时更新,不要和服务器有太大的差别
• 提交代码时,如果出现冲突,必须仔细分析解决,不可以强行提交
• 提交代码之前先在本地进行测试,确保项目能编译通过,且能够正常运行,不可盲目提交
• 必须保证服务器上的版本是正确的,项目有错误时,不要进行提交
• 提交之前先更新
• 提交时注意不要提交本地自动生成的文件,比如我们Android Studio项目中的 idea,build文件夹是不需要提交的。
• 不要提交自己不明白的代码
• 提前协调好项目组成员的工作计划,减少冲突
• 对提交的信息采用明晰的标注(写注释)
架构规范
这是我整个系列文章从零开始搭建android框架系列的重点,所以这里放在最后面。
架构方式
是选择MVP,MVC,MVVM ,Flux还是clean 架构?
,+dagger2?+rxjava?+Retrofit/okhtttp?+loader?+databinding?+contentProvider?
谷歌官方架构示例android-architecture
开源库的选取以及封装
对开源库的选取,一般都需要选择比较稳定的版本,还有作者在维护的项目
,比如这里在github搜索image,出现的安卓中的图片加载库。除了考虑star,还要考虑作者对issue的解决,以及开发者的知名度等各方面。
选取之后,一定的封装是必要的。
网络图片加载的封装这篇文章可能会从图片加载封装的角度给你讲讲封装的必要性。
架构提示
这里尽量写出自己想到的点。
抽象层面上:
• 提高架构的拓展性是有必要的。
以前的框架可能会出现功能不足的情况,但是因为这点是不可预见的,所以我们选择框架时一定要了解好框架本身的扩展性如何,或者对框架有较深的理解,能够自己扩展框架,
• 提高架构的稳定性
• 架构的文档也是必不可少的。
具体操作时:
• activity和fragment里面都会有许多重复的操作以及操作步骤,所以我们都需要提供一个BaseActivity和BaseFragment,让所有的activity和fragment都继承这个基类。
来看看我们BaseActivity中都提供了哪些操作:
• 必要的注释真的会一定程度上的降低你的工作量,而不是提高。
比如说我使用Rxjava做加载数据的操作。这里面的流程可能稍显复杂,但是能够step1, step2的写在上面,能够让别人看懂,自己维护也方便。
• 数据提供统一的入口。
无论是在mvp,mvc,还是mvvm中,提供一个统一的数据入口,都可以让代码变得更加易于维护。
比如,我使用的DataManager,里面的http还是preference,还是eventpost ,还是database ,都在DataManger里面进行操作,我们只需要与DataManger打交道。
• 多用组合, 少用继承
• 提取方法, 去除重复代码。
比如在我的架构中,我会吧imageloader单独的抽取出来作为一个widget,把对RecyclerView的封装单独抽取出来,把下拉刷新上拉加载抽取出来。如下图:
对于必要的工具类抽取也很重要,这在以后的项目中是可以重用的。
• 不要使用魔鬼数字/字符串/尺寸值/颜色值,正确的命名等
比如日间模式和夜间模式的对应颜色值,一看就很清晰了。
• 引入Dagger2 减少模块之间的耦合性
Dagger2 是一个依赖注入框架,使用代码自动生成创建依赖关系需要的代码。减少很多模板化的代码,更易于测试,降低耦合,创建可复用可互换的模块。
• 为你的项目引入Rxjava+RxAndroid这些响应式编程吧。极大的减少逻辑代码,让你爱上写代码停不下来。
• 通过引入 Event Bus(事件总线,这个项目使用的是otto)。它允许我们在Data Layer中发送事件,以便View Layer中的多个组件都能够订阅到这些事件。比如DataManager中的退出登录方法可以发送一个事件,订阅这个事件的多个Activity在接收到该事件后就能够更改它们的UI视图,从而显示一个登出状态。
当然你也可以有很多的选择,EventBus,Otto,自定义RxBus等。减少回调。
• 添加日志打印,用于查找错误等。
logger 以及timber是我推荐的。
需要使用BuildConfig.DEBUG标记对Log进行封装,只在调试时输出重要信息,正式版不输出