開發規范

https://jeroenmols.com/blog/2016/03/07/resourcenaming/

書寫規范

1. 編碼方式統一用UTF-8. Android Studio默認已是UTF-8,只要不去改動它就可以了。
2. 縮進統一為4個空格,將Tab size設置為4則可以保證tab鍵按4個空格縮進。另外,不要勾選上Use tab character,可以保證切換到不同tab長度的環境時還能繼續保持統一的4個空格的縮進樣式。
3. 花括號不要單獨一行,和它前面的代碼同一行。而且,花括號與前面的代碼之間用一個空格隔開。
public void method() { // Good 

    } 

public void method()
{ // Bad
}  

public void method(){ // Bad

} 
4. 空格的使用

if、else、for、switch、while等邏輯關鍵字與后面的語句留一個空格隔開。

// Good
if (booleanVariable) {
    // TODO while booleanVariable is true
} else {
    // TODO else
}

// Bad
if(booleanVariable) {
    // TODO while booleanVariable is true
}else {
    // TODO else
}

運算符兩邊各用一個空格隔開。

int result = a + b; //Good, = 和 + 兩邊各用一個空格隔開
int result=a+b; //Bad,=和+兩邊沒用空格隔開

方法的每個參數之間用一個空格隔開。

public void method(String param1, String param2); // Good,param1后面的逗號與String之間隔了一個空格
method(param1, param2); // Good,方法調用時,param1后面的逗號與param2之間隔了一個空格
method(param1,param2); // Bad,沒有用一個空格隔開
5. 空行的使用

將邏輯相關的代碼段用空行隔開,以提高可讀性。空行也只空一行,不要空多行。在以下情況需用一個空行:
兩個方法之間
方法內的兩個邏輯段之間
方法內的局部變量和方法的第一條邏輯語句之間
常量和變量之間

6. 當一個表達式無法容納在一行內時,可換行顯示,另起的新行用8個空格縮進。
someMethod(longExpression1, longExpression2, longExpression3,  
        longExpression4, longExpression5);
7. 一行聲明一個變量,不要一行聲明多個變量,這樣有利于寫注釋。
private String param1; // 參數1
private String param2; // 參數2
8. 行寬設置為100,設置格式化時自動斷行到行寬位置。

9. 使用快捷鍵進行代碼自動格式化。

Windows:CTRL+ALT+L
Mac:OPTION+COMMAND+L

10. 一個方法最多不要超過40行代碼。
11. 范圍型的常量用枚舉類定義,而不要直接用整型或字符,這樣可以減少范圍值的有效性檢查。
// 用枚舉類定義,Good
public enum CouponType {
    // 現金券
    @SerializedName("1")
    CASH,

    // 抵用券
    @SerializedName("2")
    DEBIT,

    // 折扣券
    @SerializedName("3")
    DISCOUNT
}

// 用整型定義,Bad
public static final int TYPE_CASH = 1; // 現金券
public static final int TYPE_DEBIT = 2; // 抵扣券
public static final int TYPE_DISCOUNT = 3; // 折扣券

Android中實現枚舉的方案選擇

12. 文字大小的單位統一用sp,元素大小的單位統一用dp。(我們項目文字還是沿用dp)
13. 應用中的字符串統一在strings.xml中定義,然后在代碼和布局文件中引用。
14. 顏色值統一在colors.xml中定義,然后在代碼和布局文件中引用。另外,不要在代碼和布局文件中引用系統的顏色,除了透明。

命名規范

1. 包命名

域名反寫+項目名稱+模塊名稱,全部單詞用小寫字母。例如,V視角項目的Model模塊包名如下:
com.vpgame.eric.vperspectives.model

2. 類和接口命名

使用大駝峰規則,用名詞或名詞詞組命名,每個單詞的首字母大寫。以下為幾種常用類的命名:

  • activity類,命名以Activity為后綴,如:LoginActivity
  • fragment類,命名以Fragment為后綴,如:ShareDialogFragment
  • service類,命名以Service為后綴,如:DownloadService
  • adapter類,命名以Adapter為后綴,如:CouponListAdapter
  • 工具類,命名以Util為后綴,如:EncryptUtil
  • 模型類,命名以BO為后綴,如:CouponBO
  • 接口實現類,命名以Impl為后綴,如:ApiImpl
3. 方法命名

使用小駝峰規則,用動詞命名,第一個單詞的首字母小寫,其他單詞的首字母大寫。以下為幾種常用方法的命名:

  • 初始化方法,命名以init開頭,例:initView
  • 按鈕點擊方法,命名以to開頭,例:toLogin
  • 設置方法,命名以set開頭,例:setData
  • 具有返回值的獲取方法,命名以get開頭,例:getData
  • 通過異步加載數據的方法,命名以load開頭,例:loadData
  • 布爾型的判斷方法,命名以is或has,或具有邏輯意義的單詞如equals,例:isEmpty
4. 控件縮寫
控件 縮寫 控件 縮寫
TextView tv EditText edt
Button btn ImageButton ibtn
ImageView img ListView list
RadioGroup RadioButton RadioButton rbtn
ProgressBar ProgressBar SeekBar seek
CheckBox chk Spinner spinner
TableLayout tl TableRow trow
LinearLayout ll RelativeLayout rl
ScrollView sv SearchView search
TabHost th TabWidget tw
5. 常量命名

全部為大寫單詞,單詞之間用下劃線分開。
public final static int PAGE_SIZE = 20;

6. 變量命名

{范圍描述+}意義描述+類型描述的組合,用駝峰式,首字母小寫。
private TextView tvHeaderTitle;

7. 控件id命名

控件縮寫{范圍}意義,范圍可選,只在有明確定義的范圍內才需要加上。

<!-- 這是標題欄的標題 -->
<TextView
    android:id="@+id/tv_header_title"
    ... />

<!-- 這是登錄按鈕 -->
<Button
    android:id="@+id/btn_login"
    ... />
8. layout命名

組件類型{范圍}功能,范圍可選,只在有明確定義的范圍內才需要加上。以下為幾種常用的組件類型命名:

  • activity_{范圍_}功能,為Activity的命名格式
  • fragment_{范圍_}功能,為Fragment的命名格式
  • dialog_{范圍_}功能,為Dialog的命名格式
  • item_{范圍_}功能,為列表的item命名格式
    我們項目是組件化開發需要加上module類型前綴,舉例:
    market_item__pro_deal.xml //module類型>market/組件類型>item/范圍>pro/功能>deal
9. strings的命名

類型{范圍}功能,范圍可選。以下為幾種常用的命名:

  • 頁面標題,命名格式為:title_頁面
  • 選項卡文字,命名格式為:tab_選項卡文字
  • 消息框文字,命名格式為:toast_消息
  • 編輯框的提示文字,命名格式為:hint_提示信息
  • 圖片的描述文字,命名格式為:desc_圖片文字
  • 對話框的文字,命名格式為:dialog_文字
  • menu的item文字,命名格式為:action_文字
  • 提示文字,命名格式為:tips_文字
10. colors的命名

前綴{控件}{范圍}{_后綴},控件、范圍、后綴可選,但控件和范圍至少要有一個。

  • 背景顏色,添加bg前綴
  • 文本顏色,添加text前綴
  • 分割線顏色,添加div前綴
  • 區分狀態時,默認狀態的顏色,添加normal后綴
  • 區分狀態時,按下時的顏色,添加pressed后綴
  • 區分狀態時,選中時的顏色,添加selected后綴
  • 區分狀態時,不可用時的顏色,添加disable后綴
  • 多種狀態的,添加selector后綴
11. drawable的命名

全部小寫,采用下劃線命名法,加前綴區分
命名模式:可加后綴 _small 表示小圖, _big 表示大圖,邏輯名稱可由多個單詞加下劃線組成,采用以下規則:

  • 用途模塊名邏輯名稱
  • 用途模塊名顏色
  • 用途_邏輯名稱
  • 用途_顏色
    說明:用途也指控件類型(具體見UI控件縮寫表)
  • 圖標類,添加ic前綴
  • 背景類,添加bg前綴
  • 分隔類,添加div前綴
  • 默認類,添加def前綴
  • 區分狀態時,默認狀態,添加normal后綴
  • 區分狀態時,按下時的狀態,添加pressed后綴
  • 區分狀態時,選中時的狀態,添加selected后綴
  • 區分狀態時,不可用時的狀態,添加disable后綴
  • 多種狀態的,添加selector后綴(一般為ListView的selector或按鈕的selector)
  • shape文件,顏色或者圓角的,添加后綴
    例如:
btn_main_home.png //按鍵
divider_maket_white.png //分割線
ic_edit.png //圖標
bg_main.png //背景
btn_red.png //紅色按鍵
btn_red_big.png //紅色大按鍵
ic_head_small.png //小頭像
bg_input.png //輸入框背景
divider_white.png// 白色分割線
12. 動畫文件命名

動畫類型_動畫方向。

  • fade_in,淡入
  • fade_out,淡出
  • push_down_in,從下方推入
  • push_down_out,從下方推出
  • slide_in_from_top,從頭部滑動進入
  • zoom_enter,變形進入
  • shrink_to_middle,中間縮小

注釋規范

1. 文件頭注釋

文件頂部統一添加版權聲明,聲明的格式如下:
/** * Copyright (c) 2017. vpgame. All rights reserved. */

2. 類和接口注釋

類和接口統一添加javadoc注釋,格式如下:

* 
 * @Description:  $desc$
 * @author: $user$
 * @data:  $date$  $time$
 * @version: 1.0
 */
3. 方法注釋

下面幾種方法,都必須添加javadoc注釋,說明該方法的用途和參數說明,以及返回值的說明。

  • 接口中定義的所有方法
  • 抽象類中自定義的抽象方法
  • 抽象父類的自定義公用方法
  • 工具類的公用方法
/**
 * 登錄
 *
 * @param loginName 登錄名
 * @param password  密碼
 * @param listener  回調監聽器
 */
public void login(String loginName, String password, ActionCallbackListener<Void> listener);
4. 變量和常量注釋

下面幾種情況下的常量和變量,都要添加注釋說明,優先采用右側//來注釋,若注釋說明太長則在上方添加注釋。

  • 接口中定義的所有常量
  • 公有類的公有常量
  • 枚舉類定義的所有枚舉常量
  • 實體類的屬性變量
public static final int TYPE_CASH = 1; // 現金券
public static final int TYPE_DEBIT = 2; // 抵扣券
public static final int TYPE_DISCOUNT = 3; // 折扣券

private int id;                // 券id
private String name;           // 券名稱
private String introduce;      // 券簡介
5. 棄用注釋

棄用的方法,常量,類,都要用*@deprecated *注釋。例如:

棄用類

分包

1.分包分析

按照功能分可能你不是很好區分在哪個功能中,不過也比你按照層區分要好找很多。

具體可以參考這篇博文~Package by features, not layers:

https://medium.com/@cesarmcferreira/package-by-features-not-layers-2d076df1964d#.mp782izhh

當然,我們大谷歌也有相應的sample~iosched

https://github.com/google/iosched/tree/master/android/src/main/java/com/google/samples/apps/iosched

其結構很值得學習

2.常見分包方式對比

PBF(按功能分包Package By Feature)與PBL(按層分包Package By Layer)相比較有如下優勢:

package內高內聚,package間低耦合

哪塊要添新功能,只改某一個package下的東西;

按class職能分層(PBL)降低了代碼耦合,但帶來了package耦合,要添新功能,需要改model、dbHelper、view、service等等,需要改動好幾個package下的代碼,改動的地方越多,越容易產生新問題,不是嗎?

按功能分包(PBF),featureA相關的所有東西都在featureA包,feature內高內聚高度模塊化,不同feature之間低耦合,相關的東西都放在一起,還好找

package有私有作用域(package-private scope)

你負責開發這塊功能,這個目錄下所有東西都是你的;

PBL的方式是把所有工具方法都放在util包下,小張開發新功能時候發現需要一個xxUtil,但它又不是通用的,那應該放在哪里?

沒辦法,按照分層原則,我們還得放在util包下,好像不太合適,但放在其它包更不合適,功能越來越多,util類也越定義越多。后來小李負責開發一塊功能時發現需要一個xxUtil,同樣不通用,去util包一看,怎么已經有了,而且還沒法復用,只好放棄xx這個名字,改為xxxUtil……因為PBL的package沒有私有作用域,每一個包都是public(跨包方法調用是很平常的事情,每一個包對其它包來說都是可訪問的)

如果是PBF,小張的xxUtil自然放在feautreA下,小李的xxUtil在featureB下,如果覺得util好像是通用的,就去util包看看要不要把工具方法添進xxUtil,class命名沖突沒有了;

PBF的package有私有作用域,featureA不應該訪問featureB下的任何東西(如果非訪問不可,那就說明接口定義有問題)

很容易刪除功能

統計發現新功能沒人用,這個版本那塊功能得去掉

如果是PBL,得從功能入口到整個業務流程把受到牽連的所有能刪的代碼和class都揪出來刪掉,一不小心就完蛋;
如果是PBF,好說,先刪掉對應包,再刪掉功能入口(刪掉包后入口肯定報錯了),完事。

高度抽象

解決問題的一般方法是從抽象到具體,PBF包名是對功能模塊的抽象,包內的class是實現細節,符合從抽象到具體,而PBL弄反了;

PBF從確定AppName開始,根據功能模塊劃分package,再考慮每塊的具體實現細節,而PBL從一開始就要考慮要不要dao層,要不要com層等等

只通過class來分離邏輯代碼

PBL既分離class又分離package,而PBF只通過class來分離邏輯代碼
沒有必要通過package分離,因為PBL中也可能出現尷尬的情況:
├─service
│MainServ.java
按照PBL,service包下的所有東西都是Controller,應該不需要Serv后綴,但實際上通常為了碼起來方便,直接import service包,Serv后綴是為了避免引入的class和當前包下的class命名沖突。

當然,不用后綴也可以,得寫清楚包路徑,比如new net.ayqy.service.Main(),麻煩;而PBF就很方便,無需import,直接new MainServ()即可。

package的大小有意義了

PBL中包的大小無限增長是合理的,因為功能越添越多;而PBF中包太大(包里class太多)表示這塊需要重構(劃分子包)。

結束語

這份開發規范說明比較細,也許還不是非常完整,也許有的不符合個人習慣,請大家求同存異,產出一份約束規范,并按照實施,將大大提高代碼的可讀性和維護性。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容