開始講一下android產品研發中一些常用的技術,技巧,方法,實踐等姿勢。這里需要強調的是我們所講解的這些東西可能對產品開發中比較常用的,因為對于項目開發中,可能更多的強調管理,進度方法的東西,對工程化的東西比較強調,而我們這里更多的是對產品技術方面的歸納總結。
而本文中選擇將開發規范作為這個系列的第一篇文章,就是個人感覺產品研發過程中,開發規范真的很重要,很重要,非常重要(重要的事情說三遍),一個好的開發規范可以讓團隊中的人對他人的代碼更熟悉,新人也可以更好的了解產品的業務邏輯。開發規范并不是一個死的一成不變的,每個團隊可能都有自己的開發規范,只要是適合團隊的開發規范就是最好的開發規范。
所以本文中所講解的開發規范只能是拋磚引玉,有可取的地方可以借鑒,引用,不能照搬全抄不假思索,畢竟不同的團隊有不同的實際情況。最好的方式就是可以根據本文的開發規范總結出自身團隊比較適合的規范流程。
好吧,廢話不多說了,下面我們就介紹一下我在實踐中總結的android開發規范。
## 1 前言
### 1.1 為什么需要開發規范
編碼規范對于程序員而言尤為重要,有以下幾個原因:
* 一個軟件的生命周期中,80%的花費在于維護
* 幾乎沒有任何一個軟件,在其整個生命周期中,均由最初的開發人員來維護
* 編碼規范可以改善軟件的可讀性,可以讓程序員盡快而徹底地理解新的代碼
* 如果你將源碼作為產品發布,就需要確任它是否被很好的打包并且清晰無誤,一如你已構建的其它任何產品
### 1.2 開發規范的作用
* 減少維護花費
* 提高可讀性
* 加快工作交接
* 減少名字增生
* 降低缺陷引入的機會
## 2 命名規范
### 2.1 常量命名規范
#### 2.1.1 類型
常量命名規范
#### 2.1.2 說明
常量用于保存需要常駐內存中并且經常使用變化不多的數據,定義常量的名稱的時候需要遵循望文知意的原則;
#### 2.1.3 規則
* 全部為大寫字母;
* 中間以“_”連接;
* 望文知意原則;
#### 2.1.4 備注
代碼中涉及到直接使用某個字符串或者其他基本類型的值時,建議定義成常量,避免多處直接使用同樣的值作為參數。
#### 2.1.5 舉例
* 如:定義一個常量表示最小屏幕寬度的常量,則可以定義一個int類型的常量,該常量可以命名為:“MIN_SCREEN_WIDTH“;
* 其他舉例:
* 例如:static final int MIN_SCREEN_WIDTH = 4;( √)
* 例如:static final int min_screen_width = 4;(×)
* 例如:static final int minScreenWidth = 4; (×)
* 例如:static final int WIDTH = 4;(×)
* 例如:static final int width = 4;(×)
* 例如:static final int wd = 4;(×)
### 2.2 變量命名規范
#### 2.2.1 類型
變量命名規范
#### 2.2.2 說明
變量用于保存系統中的臨時數據,變量命名時遵循望文知意,簡單明了,駝峰標示等原則。
#### 2.2.3 規則
1. 首字母大寫;
2. java駝峰命名;
3. 望文知意原則;
4. 推薦引用類型變量添加前綴“m”;
5. 如果是View組件變量,則組件名稱為xml文件中定義的ID名稱去掉下劃線,下劃線后一位大寫;
#### 2.2.4 備注
無
#### 2.2.5 舉例
* 如:定義一個表示最小屏幕寬度的變量,則可以定義一個int型的臨時變量為:mMinScreenWidth;
* 例如:static final int mMinScreenWidth = 4; ( √)
* 例如:static final int minWidth = 4;(×)
* 例如:static final int screenWidth = 4;(×)
* 例如:static final int width = 4;(×)
* 例如:static final int min = 4; (×)
* 例如:static final int msw = 4; (×)
### 2.3 方法命名規范
#### 2.3.1 類型
方法命名規范
#### 2.3.2 說明
方法名的命名應該遵循簡單明了的原則;
#### 2.3.3 規則
1. 首字母小寫;
2. java駝峰命名;
3. 簡單明了原則;
4. 初始化View方法init*(每個init做一件事)
#### 2.3.4 備注
* 同時在方法的實現上,盡量不要在一個方法中出現太多實現代碼,如一個方法有幾百行的實現邏輯,推薦在邏輯復雜時,按功能點拆分出多個方法,便于閱讀。
* 另外,出現功能一樣的實現邏輯,盡量抽取公用方法,避免將實現邏輯復制到多個用到的地方。
#### 2.3.5 舉例
* 如:定義一個獲取屏幕寬度的方法,依照上述原則,則可以定義為一個靜態方法:public static int getScreenWidth();
* 例如:public static int getScreenWidth();( √)
* 例如:public static int getscreenwidth();(×)
* 例如:public static int getScreenwidth();(×)
* 例如:public static int getWidth();(×)
* 例如:public static int getScreen();(×)
* 例如:public static int getSW();(×)
### 2.4 類命名規范
#### 2.4.1 類型
類命名規范
#### 2.4.2 說明
類名主要表示一個類的作用,需要簡明扼要,望文知意,并且首字母大寫。
#### 2.4.3 規則
1. 首字母大寫;
2. java駝峰命名;
3. 望文知意原則;
4. 能夠說明類的功能和主要作用(注釋的作用);
5. Acitivity類以Acitivity結尾;
6. Fragment類以Fragment結尾;
7. Service類以Service結尾;
8. BroadcastReceiver類以Receiver結尾;
9. ContentProvider類以Provider結尾;
10. Application類以Application結尾;
11. 自定義View類以Custom**View結尾;
12. 自定義Adapter類以Adapter結尾;
13. adapter中的ViewHolder以Holder結尾;
14. 實體Bean以Model結尾;
#### 2.4.4 備注 無
#### 2.4.5 舉例
* 如:定義一個獲取屏幕信息的工具類,則可以定義為public class ScreenUtils;
* 例如:public class ScreenUtils; ( √)
* 例如:public class Screenutils; (×)
* 例如:public class Screen; (×)
* 例如:public class screenutils; (×)
* 例如:public class screen; (×)
* 例如:public class su;(x)
### 2.5 接口命名規范
#### 2.5.1 類型
接口命名規范
#### 2.5.2 說明
接口命名需要簡單明了,長度不宜過長;
#### 2.5.3 規則
1. 首字母大寫(第二個字母也是大寫);
2. java駝峰命名;
3. 望文知意原則;
4. 建議在名稱前面追加“I”;
#### 2.5.4 備注
* I**Listener
* I**CallBack
* I**;
#### 2.5.5 舉例
* 如:定義一個activity的方法接口,實現接口中的某些方法:public interface IFunctionListener;
* 例如:public interface IFunctionListener;( √)
* 例如:public interface BaseActivity; (×)
* 例如:public interface Baseactivityinter; (×)
* 例如:public interface BaseInter; (×)
* 例如:public interface ActivityInter;(×)
### 2.6 包名規范
#### 2.6.1 類型
包名規范
#### 2.6.2 說明
用于分類管理類文件;
#### 2.6.3 規則
1. 所有字母小寫;
2. 簡單明了,層級很深,沒有拼接的包名;
3. 望文知意;
4. 按功能劃分包名,如“我的”
5. 工具類可以劃分為一個工具類的包名,utils,里面可以添加包名層級;
6. 系統類的可以劃分為一個系統類的包,system,里面可以添加包名層級;
7. 組件類的可以劃分為一個組件類的包,***,里面添加adapter的包名,自定義view包名;
8. Service類的可以劃分為一個服務類的包,service,里面可以添加包名層級;
9. 數據庫相關類可以劃分為一個數據庫類,db,里面可以添加數據庫相關類,Bean類,數據庫服務類等;
10. 廣播類的可以劃分為廣播類的包,receiver,可以放一些廣播相關的類;
11. 網絡類相關的可以劃分為,network,放一些網絡相關的類;
12. Fragment類存放在fragment包下;
13. Activity類存放在Activity包下;
#### 2.6.4 備注
無
#### 2.6.5 舉例
無
### 2.7 目錄名稱規范
#### 2.7.1 類型
目錄名稱規范
#### 2.7.2 說明
主要是一些jar包,so文件的配置目錄名稱;
#### 2.7.3 規則
1. 全部為小寫字母;
2. 簡單明了;
3. 望文知意;
4. 駝峰表示;
#### 2.7.4 備注 無
#### 2.7.5 舉例
* 后期增加目錄的可能性不多,現列舉出系統中存在的目錄結構:
* lib:第三方jar的保存路徑;
* jniLibs:jni引用的so文件的目錄;
### 2.8 布局文件名稱規范
#### 2.8.1 類型
布局文件名稱規范
#### 2.8.2 說明
主要包含資源文件的命名問題;
#### 2.8.3 規則
1. 全部為小寫字母;
2. 中間以"_"連接;
3. 望文知意原則;
4. 布局文件的開頭問類名;
5. 列表項的xml布局文件名稱:類名_item.xml;
6. activity類的xml文件名稱:類名_activity.xml;
7. fragment類的xml文件名稱:類名_fragment.xml;
8. 自定義View的xml文件的名稱:類名_父類名.xml;
#### 2.8.4 備注 無
#### 2.8.5 舉例
如:如定義H5Activity的xml文件名稱,則可以定義為h5.xml;盡量不使用大寫字母等。
### 2.9 drawable文件名稱規范
#### 2.9.1 類型
drawable文件名稱命名規范
#### 2.9.2 說明
主要包含資源文件的命名問題;
#### 2.9.3 規則
1. 全部為小寫字母;
2. 中間以"_"連接;
3. 望文知意原則;
4. 布局文件的開頭問類名;
5. 11_22_33_44,44:selector,shape(大概五六個,暫時不定義其他的); 33:src、bg、color(可擴展,可為空); 22:狀態名稱或者為空;11:業務名稱
#### 2.9.4 備注 無
#### 2.9.5 舉例 無
### 2.10 資源ID規范
#### 2.10.1 類型 資源ID命名規范
#### 2.10.2 說明 各種資源ID的定義問題;
#### 2.10.3 規則
1. 全部為小寫字母;
2. 中間以"_"連接;
3. 望文知意原則;
#### 2.10.4 備注
可以考慮按照組件的名稱的縮寫作為前綴,(同一個xml文件中ID名稱不能重復)如:組件簡寫(大寫字母縮寫)_業務名稱 TextView的組件:tv_pay_money Button的組件:btn_pay_money EditText的組件:et_user_name LinerLayout組件:ll_container
#### 2.10.5 舉例
如:比如一個textview組件,可點擊用于支付的按鈕,則可以把ID定義為: tv_pay_money;
## 3 注釋規范
### 3.1 類注釋
~~~
在類、接口定義之前當對其進行注釋,包括類、接口的目的、作用、功能、繼承于何種父類,實現的接口、實現的算法、使用方法、示例程序等。
/**
* author:作者
* time:時間
* desc:描述
*/
~~~
### 3.2 方法注釋
~~~
方法注釋的模板:
/**
* desc:描述
* @param 參數名 參數描述
* @param 參數名2 參數描述
* @return 返回值類型說明
* @throws Exception 異常說明
*/
~~~
### 3.3 類成員變量和常量注釋
~~~
成員變量和常量需要使用如下注釋的形式,注釋位于變量的上側;
/**
*
**/
~~~
### 3.4 內部邏輯注釋
~~~
內部邏輯注釋模板:
//支付成功
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);
}
~~~
## 4 代碼順序
### 4.1 代碼順序
~~~
在一個典型的Activity中代碼的順序如下:
/**
* author:sh
* desc:該class的作用
* time:yyyy-MM-dd
**/
public class ClassName {
//(1) 成員變量集合
//(2) 回調方法集合
若該類為activity,則:onCreate、**、onDestory;
若該類為Fragment、則:onCreateView、**、onDestory;
//(3) 其他方法集合
}
~~~
## 5 代碼風格
### 5.1 大括號換行
~~~
左大括號不換行,右大括號換行;
class MyClass {
int func() {
if (something) {
// ...
} else if (somethingElse) {
// ...
} else {
// ...
}
}
}
~~~
### 5.2 小括號空格
~~~
if (condition) {
body();
} // 推薦
~~~
### 5.3 縮進
* 4 個空格作為縮進排版的一個單位,不使用制表符 tab。
* 8 個空格作為換行后的縮進,包括函數調用和賦值。
* Instrument i = someLongexpression_r(that, NotFit, on, one, line); // 推薦
### 5.4 每一行的長度
* 盡量避免一行的長度超過 100 個字符。
* 例外:如果注釋行包含了超過 100 個字符的命令示例或者 url 文字,為了便于剪切和復制,其長度可以超過 100 個字符。
* 例外:import 行可以超過限制,因為很少有人會去閱讀它。這也簡化了編程工具的寫入操作。
### 5.5 每次聲明一個變量
* 推薦一行一個聲明,因為這樣以利于寫注釋;
* int level; // indentation level
* int size; // size of table
### 5.6 if-else語句
~~~
if-else語句應該具有如下格式: if (condition) { statements; }
if (condition) {
statements;
} else {
statements;
}
if (condition) {
statements;
} else if (condition) {
statements;
} else{
statements;
}
注意:if語句總是用”{“和”}“括起來,避免使用如下容易引起錯誤的格式:
if (condition) // 避免
statement;
~~~
### 5.7 for語句
~~~
一個for語句應該具有如下格式:
for (initialization; condition; update) {
statements;
}
當在for語句的初始化或更新子句中使用逗號時,避免因使用三個以上變量,而導致復雜度提高。
若需要,可以在for循環之前(為初始化子句)或for循環末尾(為更新子句)使用單獨的語句。
~~~
### 5.8 while語句
~~~
一個while語句應該具有如下格式:
while (condition) {
statements;
}
~~~
### 5.9 do-while語句
~~~
do {
statements;
} while (condition);
~~~
### 5.10 switch語句
~~~
一個switch語句應該具有如下格式:
switch (condition) {
case ABC:
statements;
/* falls through */
case DEF:
statements;
break;
case XYZ:
statements;
break;
default:
statements;
break;
}
每當一個case順著往下執行時(因為沒有break語句),通常應在break語句的位置添加注釋。
~~~
## 6 異常規范
### 6.1 異常名稱
定義異常的時候,異常的后綴名稱以Exception結尾,及**Exception;
### 6.2 異常描述
盡量英文描述,簡單明了;
### 6.3 異常格式
~~~
一個try-catch語句應該具有如下格式:
try {
statements;
} catch (ExceptionClass e) {
statements;
}
try {
statements;
} catch (ExceptionClass e) {
statements;
} finally {
statements;
}
~~~
## 7 其他規范
### 7.1 源文件的函數小于2K
一般來說源文件的行數不能大于2K行,過多的話可以考慮拆分功能,拆分函數等;
### 7.2 使用TODO注釋
* 對那些臨時性的、短期的、夠棒但不完美的代碼,請使用 TODO 注釋。
* TODO 注釋應該包含全部大寫的 TODO,后跟一個冒號:
* // TODO: Remove this code after the UrlTable2 has been checked in.
* // TODO: Change this to use a flag instead of a constant. 如果 TODO 注釋是“將來要做某事”的格式)。
### 7.3 使用自定義LOG
在系統中需要打印LOG的時候,盡量使用自定義的LOG,自定義的LOG在開發環境的時候會打印日志,正式環境的時候不會打印日志。
### 7.4 使用自定義TAG
在系統打印LOG的時候,使用TAG盡量使用tab,同意的TAG標志。
另外對產品研發技術,技巧,實踐方面感興趣的同學可以參考我的:
[Android產品研發–>總結(持續更新)](http://blog.csdn.net/qq_23547831/article/details/51645787)
- 前言
- (一)–>實用開發規范
- (二)-->啟動頁優化
- (三)-->基類Activity
- (四)-->減小Apk大小
- (五)-->多渠道打包
- (六)-->Apk混淆
- (七)-->Apk熱修復
- (八)-->App數據統計
- (九)-->App網絡數據解析
- (十)-->盡量不使用靜態變量保存數據
- (十一)-->應用內跳轉Scheme協議
- (十二)-->App長連接實現
- (十三)-->App輪詢操作
- (十四)-->App升級與更新
- (十五)-->內存對象序列化
- (十六)-->開發者選項
- (十七)-->Hybrid開發
- (十八)-->webview問題集錦
- (十九)-->Android studio中的單元測試
- (二十)-->代碼Review
- (二十一)-->Android中的UI優化
- (二十二)-->Android實用調試技巧
- (二十三)-->Android中保存靜態秘鑰實踐
- (二十四)-->內存泄露場景與檢測
- (二十五)-->MVC/MVVM/MVP簡單理解