前言
來到一個新公司,動手寫代碼前,我一般都是找領導要開發規範。但是,許多公司都是沒有任何開發規範,或者開發規範真是非常簡單,只有對修改注釋的格式說明,這……。現在的這家公司,我來這二年了,都沒有看到什麼開發規範,在我的強烈要求下,公司領導才給了一個功能手機開發時代的c++的開發規範,我說要android的java開發規範,領導非常不樂意,就在網上找了一個開發規範文檔發給我,還說大家都不是剛開發,應該都知道代碼怎麼寫,……。其實我本意是要公司成立自己的開發規範,說實在話,這個開發規範不是僅僅應付我的要求,應該是公司自己研發品質和體系的自我要求,我其實基本上是不需要什麼開發規範文檔,因為我寫的代碼還是比較規範的,但是公司領導的水平實在不怎麼樣,覺得我就是個trouble maker。好吧,我錯了……。以致於後來有人問我,我們寫代碼有什麼講究沒,我想了一下,回了一句,你想怎麼寫就怎麼寫,沒有人會看你的代碼,根本就沒有人答理你。這,真是有點絕,但是這就是事實……。
好吧,別人不搞,我們自己來整理一個android開發規範吧,這個以後也是用的著的。 目的
此文檔主要是: 統一代碼的風格,提高代碼的可讀性,方便代碼維護和移植。 統一代碼的約定,方便研發工程師協作,提高工作效率 提高軟體品質,減少代碼的錯誤,加強代碼的追蹤和管理 android開發規範
我們以android開發寫代碼的順序來組織此開發規範: 代碼修改注釋:
我們對代碼的任何一條修改都需要使用修改注釋,方便代碼的修改追蹤和管理: java檔案:
代碼修改注釋的開始:
//add—XXX(修改者名字)—XXXX(功能描述)—XXXX(修改日期20150101) —start
代碼修改注釋的結束:
//add—XXX(修改者名字)—XXXX(功能描述)—XXXX(修改日期20150101) —end
xml檔案:
代碼修改注釋的開始:
<!--add—XXX(修改者名字)—XXXX(功能描述)—XXXX(修改日期20150101) —start-->
代碼修改注釋的結束:
<!--add—XXX(修改者名字)—XXXX(功能描述)—XXXX(修改日期20150101) —end-->
檔案注釋
在java或xml檔案開關,我們一般要給此檔案一個檔案的注釋,主要是包括著作權的聲明,檔案名稱、版本資訊、日期和作者等等。
java檔案注釋:
/* * Copyright (C) 2016 XXX(公司名) Inc. * All Rights Reserved. * File name: * Function: * Version: * Date: * */
xml檔案注釋:
<!--* * Copyright (C) 2016 XXX(公司名) Inc. * All Rights Reserved. * File name: * Function: * Version: * Date: * *-->
命名規範
命名規範基本上是符合java和android現有的源碼風格,方便代碼閱讀和代碼理解。
名稱類型 |
基本規範 |
範例 |
包(Packages) |
一個唯一包名的首碼總是全部小寫ASCII字母並且是一個頂級網域名稱,通常是com,第二個參數是公司名,第三個參數是功能模組,比如:[網域名稱反轉].[項目名].[模組名].[子模組名]…,例如package com.android.contacts; |
com.xxx.helloworld(xxx為公司名縮寫) |
類(Classes) |
類名採用大小寫混合的方式,每個單詞的首字母大寫。類名應具體,可讀,完整表達類的含義。使用完整單詞,避免縮寫詞(除非該縮寫詞被更廣泛使用,像URL,HTML)。繼承自系統組件類的命名,尾碼必須明確表示出系統組件的類別,Activity類尾碼使用Activity,Service類尾碼使用Service,BroadcaseReceiver類尾碼使用Receiver,ContentProvider使用Provider |
Class UsbManager,Class ActivityManager,Class SpeechRecorderActivity, Class AccountService |
介面(Interfaces) |
與類名類似,只是在前加I以表示介面 |
interface IActivityManager |
方法(Methods) |
方法名是一個動詞+賓語,採用大小寫混合的方式,第一個單詞的首字母小寫,其後單詞的首字母大寫,以它做什麼來命名,而不是以它怎樣做命名 |
finishActivity(),getID() |
變數(Variables) |
變數名,包括類,類常量,均採用大小寫混合的方式,第一個單詞的首字母小寫,其後單詞的首字母大寫.變數名應簡短,完整,清楚的表達變數的含義.變數名的選用應該易於記憶,即,能夠指出其用途。盡量避免單個字元的變數名,除非是一次性的臨時變數。 臨時變數通常被取名為 i,j,k,m 和 n,它們一般用於整型;c,d,e,它們一般用於字元型.非 public 的、非 static 的欄位名稱以 m 開頭。static 欄位名稱以 s 開頭。其它欄位以小寫字母開頭 |
int i,j,k; Context mContext;PackageManager mPm;Button mOk;Uri mOriginatingURI;private static MyClass sSingleton |
常量(Constants) |
類常量的聲明全部大寫,單詞間用底線隔開 |
public static final int START_VOICE_HIDDEN_SESSION = -10; |
包和引入
在java檔案,檔案注釋之後就是包和引入,
package主要是包的路徑,這要符合開發的定義,比如android的一個包:
package com.android.contacts;
package com.android.server.usb;
我們可以自訂package:
package com.XXX.helloword
XXX為公司的英文名。
同一包中的類在匯入時應聲明在一起,無效的未使用到的引用要刪除:
import範例:
import android.content.Context;
類和介面的注釋
標準的注釋:
/** * 類或介面的說明 * @see 相關的類或介面 */
但是,如果類比較簡單,我們也可以直接用一句話描述此類或介面的功能
比如UsbAlsaManager類的注釋:
/** * UsbAlsaManager manages USB audio and MIDI devices. */
方法
方法的規範要求比較多:
(1)方法的名稱要清晰描述方法的功能,建議是動詞+賓語(例如getID)
(2)方法的職責單一,功能明確(是符合單一職責原則)
(3)方法的長度合適,不要太長,也不要太短,最好是體現介面隔離原則,介面盡量顆粒化
(4)方法的參數數量和順序要合適,參數數量不要太多,參數的順序要有一定的順序,比如按照in–modify–out的順序排列
(5)方法的注釋要合理,方便閱讀
(6)方法的布局和風格要一致
(7)方法盡量不要使用神秘數
(8)方法要符合迪米特法則,盡量不要使用不是參數的其它變數,降低方法的耦合性,提高方法的內聚性,也方便移植
(9)方法要有相應的處理異常,錯誤的手段,提高方法的健壯性。
比如:
/** * 一句話描述方法 * 方法詳細描述 * @param 參數,說明 * @param 參數,說明 * @return 傳回值,說明 * @throws 異常,說明 * @see 相關的方法 */public boolean functionName(int param_0,boolean param_1) { boolean result = false; ...........; return result;}
當然,許多時候,方法簡單明了,根本就不需要方法的注釋,我們可以不添加註釋,也可以只添加一個對方法簡單描述的注釋。比如:
/** * Show the overflow items from the associated menu. * @return true if the menu was able to be shown, false otherwise */public boolean showOverflowMenu() { return mMenuView != null && mMenuView.showOverflowMenu();}
類成員變數和常量注釋
成員變數注釋:
/** * 成員變數描述 */private String test;/** 成員變數描述 */private int hello;// Buttons to indicate user acceptanceprivate Button mOk;
常量注釋:
// Dialog identifiers used in showDialogprivate static final int DLG_BASE = 0;
變數的聲明和初始化 在聲明變數的時候初始化 在靠近變數第一次使用的位置初始化 理想情況下,在靠近第一次使用變數的位置聲明和定義該變數,並初始化
括弧
大括弧不單獨佔用一行,應緊接著上一行。比如:
public class NullObject extends AbstractObject { ........ public void doAction() { ...... }}
if, if-else, if else-if else 語句
if (condition) { statements;}if (condition) { statements01;} else { statements02;}if (condition) { statements01;} else if (condition) { statements02;} else{ statements03;}
if語句要注意: 先處理正常的代碼路徑,再處理不正常的情況 把最常見的情況放在最前面 把正常的情況放在if後面,把不要放到else後面 讓if後面跟隨一個有意義的語句 利用布爾方法調用簡化複雜的條件檢測 switch語句
switch (condition) { case case1: statements01; break; case case2: statements02; break; case case3: statements3; break; default: statements; break;}
switch語句注意: 把正常的情況放在前面 按執行頻率排列case子句 每個case後都添加break 迴圈
for 語句:
for (initialization; condition; update) { statements;}
while語句:
while (condition) { statements;}
do-while 語句:
do { statements;} while (condition);
迴圈要注意: 保持迴圈的邏輯簡單易讀 將迴圈內的判斷外提 儘可能減少在迴圈內部做的工作 把最忙的迴圈放在最內層 可以使用一個哨兵值來控制是否退出迴圈 try-catch 語句
try { statements;} catch (ExceptionClass e) { statements;}try { statements;} catch (ExceptionClass e) { statements;} finally { statements;}
try-catch 語句注意: catch時,一定要把異常列印出來,絕不允許catch為空白,什麼都不做。比如如下的代碼是要禁止的。
try { statements;} catch (ExceptionClass e) { //什麼都不做}try { statements;} catch (ExceptionClass e) { //什麼都不做} finally { statements;}
不要使用魔法數
所謂魔法數值,是指在代碼中直接出現的數值。
比如:
public void magicFunction() { int i = 1000; }
我們不知道這個100從那裡來,表示什麼意義。正確的使用方式為:
public static final int NUMBER_LIGHT = 1000; public void magicFunction() { int i = NUMBER_LIGHT ; }
這樣一方面可以提高代碼的可讀性,另一方面,也可以把變更的地方局部化,從而提高可維護性。 Layout 命名
布局檔案的命名,我們採用全部單詞小寫,單詞間以底線分割,儘可能的使用名詞或名片語,即使用模組名_功能名稱來命名。比如:
contact_tile_list_frequent.xml
contact_editor_activity.xml
group_browse_list_item.xml 資源 ID 命名
layout中所使用的id命名必須以全部單詞小寫,單詞間以底線分割,儘可能的使用名詞或名片語,能夠通過id直接理解當前組件要實現的功能。
Button android:id=”@+id/cancel_button”
ImageButton android:id=”@+id/open_details_button”
TextView android:id=”@+id/suggestion_for_contacts_number” strings.xml 中 ID 命名
命名必須以全部單詞小寫,單詞間以底線分割,並且儘可能的使用名詞或名片語,例如:
<string name="menu_create_contact_shortcut">Place on Home screen</string><string name="photo_picker_title">Choose photo</string>
圖片資源命名
drawable目錄下的圖片命名必須以全部單詞小寫,單詞間以底線分割,儘可能的使用名詞或名片語,即使用模組名_用途來命名。如果為公用資源,如分割線等,則直接用用途來命名。比如:
group_icon_1.pngbtn_star_on_normal_holo_light.png
控制項的使用
以Button為例:
在布局檔案定義一個控制項:
<Button android:id="@+id/cancel_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/quickcontact_suggestion_cancel_button"/>
在java檔案使用:
private Button mCancelButton;mCancelButton= (Button) findViewById(R.id.cancel_button);mCancelButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { ...... }});
log資訊
日誌資訊是對系統的效能有影響的,建議伺服器上的代碼,把我們開發時的調試日誌資訊全部刪除。 公用方法和介面
有一些是公用方法或介面,建議放在單獨建立的檔案裡,比如(Util.java,Help.java),或是放在系統本身的公用檔案中,定義成public static 的形式,方便方法複用。 參考資料:
1.Android開發規範
http://blog.csdn.net/huangyabin001/article/details/30095775
2.代碼大全2