爲什麼要有編碼規範?編碼規範對於程序員而言尤爲重要,主要有以下幾個原因:
|
重 要性
一個軟件的生命週期 中,80%的花費在於維護。
幾乎沒有任何一個軟 件,在其整個生命週期中,均由最初的開發人員來維護。
編碼規範可以改善軟件 的可讀性,可以讓程序員儘快而徹底地理解新的代碼。
如果你將源碼作爲產品 發佈,就需要確任它是否被很好的打包並且清晰無誤。
|
|
簡 而言之
代碼是寫給別人看的!
|
代碼規範是高代碼質量和高開發效率的前提。代碼規範是團隊成員之間無阻礙交流的保證。每個軟件開發人員必須一致遵守編碼規範。
1. 命名規範
定義這個規範的目的是讓項目中所有的文檔都看起來像一個人寫的,增加可讀性,減少項目組中因爲換人而帶來的損失。
1.1 包的命名
包名命名必須全部是英文的小寫字母,由名詞或名詞縮寫組成。按照國際規例,包的命名由組織性質,組織名稱縮寫或全名,系統名稱組成。比如公司一般用 com,社團用net,非盈利的組織用org。包末端的名稱一般是根據包含的類或接口的職責,功能來名稱,比如業務邏輯的,可以是service或 manager,具體實現可能是service.impl。包命名的基本原則是能夠抽象出包管轄的類的職責和功能。簡單的說就是一看包就知道下面的類是做 什麼的。
一些常見的包的命名:
org.apache.commons.logging
org.springframework.dao
org.hibernate
1.2 類和接口的命名
類和接口的名稱必須以大寫的英文字母開頭,必須是名詞或名詞短語,多個名詞存在的時候名詞的第一字母大寫。禁止在名稱中出現形容詞、動詞和動詞衍生 形式,比如DeleteUser,UpdateDClass,GetNode,MyNode,YourTree來命名。類和接口名稱要有實際的意義,根據 名稱就大概知道這個類的職責是什麼。嚴禁使用Page1,Page2來命名。對於Domain model,直接就是對象的名稱,比如Book,Address之類,如果是業務接口,那就是BookManager或者BookService,業務實 現類就是BookManagerImpl或者BookServiceImpl。這裏的Impl是Implement的縮寫。對於一些工具類,可能是會加上 Utils,比如FileUtils,StringUtils,這些工具類的方法一般都是靜態方法,比較著名的 org.apache.commons.lang,下面有很多工具類。如果是異常類,一般都以Exception爲後綴,比如 UniqueException,一看名稱大概就是這個一個違反唯一約束的異常類。
以下常見的命名方法:
org.hibernate.Criteria
javax.servlet.http.HttpSession
org.apache.tapestry.util.ContentType
org.apache.commons.lang.StringUtils
org.springframework.dao.DataIntegrityViolationException
1.3 變量的命名
變量以名詞或名詞短語組成,第一個英文字母必須小寫。如果是靜態變量,則全部大寫,用下滑劃線分割。禁止在名稱中出現形容詞、動詞和動詞衍生形式。 實例的名稱儘量用類的名字或者有意義的英文單詞,比如User user 和 UserService userService。嚴禁使用無意義的字母活數字,如a,b,c,x,y,a1,a2,myNode,myTree來命名。如果是實例結合或數組,那 一般用類名的複數形式或者後綴加上list和map,比如userList,userMap,users,儘量避免直接用map,list作爲實例名稱。
常見的命名方法:
byte[] buffer
public static final int INDEX = 0
private final boolean isCascadeDeleteEnabled;
EntityKey key = new EntityKey()
1.4 參數的命名
參數的名字和變量的命名規範一致。
1.5 數組的命名
數組應該總是用下面的方式來命名:
byte[] buffer;
而不是:
byte buffer[];
1.6 方法的命名
方法的命名以動詞和動詞短語組成,第一個英文字母必須小寫,但有一個例如,以is和has爲前綴的方法名。方法名儘量讓客戶程序員看見名稱就大概知 道這個方法的行爲。Is和has爲前綴的方法返回的都是boolean或Booelan.
常見的方法命名:
protected boolean hasPostCommitEventListeners()
private static EntityPersister create
publicboolean isAdmin()
2. 文件樣式
2.1 Package/Imports
Package 行要在 import 行之前,import 中標準的包名要在本地的包名之前,而且按照字母順序排列。禁止使用*方式,如 java.io.* 。導入定義應當是類的全稱
import java.util.ArrayList;
import java.util.Hashtable;
2.2 類和接口
類和接口需要填寫註釋,一般是用來解釋類的職責和使用方法,而且要儘可能的詳細。
/**
* A class representing a set of packet and byte counters
* It is observable to allow it to be watched, but only
* reports changes when the current set is complete
* @author Ken
*/
public interface DClassDao extends GenericDao<DClass, Long>
2.3成員變量
public 的成員變量必須生成文檔。proceted、private和 package 定義的成員變量如果名字含義明確的話,可以沒有註釋。
/**
* Packet counters
*/
protected int[] packets;
2.4構造函數
構造函數應該用遞增的方式寫(比如:參數多的寫在後面)。 訪問控制符("public", "private" 等.) 和 任何 "static", "final" 或 "synchronized" 應該在一行中,並且方法和參數另寫一行,這樣可以使方法和參數更易讀。
public CounterSet(int size){
this.size = size;
}
2.5方法
接口的方法默認是public,定義接口方法可以不定義訪問控制符號。類的方法必須指定訪問控制符。所有的方法必須寫方法註釋,但接口和抽象類的實 現方法可以不寫。
3. 編程慣例
3.1 public private final protected使用
任何一個類,接口,方法,變量必須要有訪問控制符號,如果是提供給客戶程序使用,那麼申明爲public,如果只是內部過渡行爲,那麼申明爲 private.這裏有一個原則,儘量使用private,少使用public.
3.2 代碼中不能出現無用的包和類、變量
具體到Eclipse工作區內禁止出現任何紅色錯誤和黃色警告的標記出現。
3.3 禁止在一個Java文件中編寫多個類。
內部類和匿名類除外,但建議少用。
3.4 繼承一般只能繼承抽象類一般不能超過兩層繼承
繼承非抽象類,重載了非抽象方法,在實例的向上轉型和向下轉型會帶來一些意想不到的困擾,建議經驗不足者慎用。繼承是一種無契約無保證的方法重用, 父類方法行爲的改變不會通知到子類和子類的客戶程序。多用接口,少用繼承。
3.5 if,if-else,if else-if else語句(if, if-else, if else-if else Statements)
if-else語句應該具有如下格式:
if (condition) {
statements;
} else if (condition) {
statements;
} else{
statements;
}
注意:if語句總是用
括起來,避免使用如下容易引起錯誤的格式:
if (condition)
statement;
3.5 while,if, for,相互嵌套的層次不能超過3層
while(true){
if(size > 0){
for(User user : userList){
if(user.name.isEmpty()){
……..
}
}
}
}
3.6 java代碼中不能出現SQL和HQL
SQL和HOL在Java代碼中很難排版和維護,禁止在代碼中出現。
String sql = "select c.* from metaone_dclass ";
Session session = getSession(false);
Query query = session.createSQLQuery(sql).addEntity(DClass.class);
query.setParameter("id", id);
return query.list();
3.7 禁止直接在控制檯打印。
禁止使用System.out.和System.error.,e.printStackTrace()。請使用Log4j來處理。
3.8 Collection和Map之間儘可能避免相互嵌套,禁止相互嵌套超過一層。
Map<String, Map<? extends Object, Map<Integer, Object>>> authorities = authorization.getAuthorities();
3.9 方法參數的個數禁止超過3個。
錯誤範例:
public List<DClass> findDClass(String name,
List<DAttribute> attributes, Long mid, int firstResult,
int maxResults, boolean matchCase)
3.10 import的類不能超過30個。
此項作爲建議。
3.11 頁寬限制
頁寬應該設置爲80字符。源代碼一般不會超過這個寬度, 並導致無法完整顯示,但這一設置也可以靈活調整。在任何情況下,超長的語句應該在一個逗號或者一個操作符後折行。一條語句折行後,應該比原來的語句再縮進 2個字符。
3.12 {} 對限制
{} 中的語句應該單獨作爲一行. {應當在一行的結束出現,不出現在新行開始,應當在一個新行中開始和結束, 即使代碼體中只有一行,也需要使用{}例如, 下面的第1行是錯誤的, 第2行是正確的:
錯誤範例
正確範例
3.13 類代碼長度和方法代碼長度
每個Java程序一般不的超過200行,每個Java方法一般不的超過50行。如果超過類超過200行,方法超過50行,那就需要重新審查一下設 計,類的職責是否單一,方法是否承載的過多的功能。臃腫的類和方法的出現,一般都伴隨的“相同或相似的代碼”出現。如果出現了相同和相似的代碼,那麼就需 要的相同的代碼抽象出來成一個獨立的類或方法。
3.14 代碼禁止出現TODO
這些代碼一般都是IDE自動生成。
4. 註釋規範
註釋主要是用於描述類的職責,方法的行爲。註釋應被用來給出代碼的總括,並提供代碼自身沒有提供的附加信息。註釋應該僅包含與閱讀和理解程序有關的 信息。
禁止在代碼中出現“到此一遊”的現象,比如在代碼中註釋“某人在某時做某事”,這部分註釋內容應該提交到版本管理工具中。
|
建 議
儘可能避免註釋單行和在方法內部寫註釋。比如String password;//密碼。如果需要註釋請重新審視變量的命名。如果需要在方法內部寫註釋,請重新檢查方法的註釋是否足夠詳細或者方法的設計是否存在問 題。
|
|
注 意
頻繁的代碼內註釋有時反映出代碼的低質量。當你覺得被迫要加註釋的時候,考慮一下重構代碼使其更清晰。
|
4.1 範例
Java 的註釋:/** ...... */ 註釋若干行,並寫入 javadoc 文檔
註釋要簡單明瞭,邊寫代碼邊註釋,修改代碼同時修改相應的註釋,以保證註釋與代碼的一致性。在必要的地方註釋,註釋量要適中。註釋的內容要清楚、明 了,含義準確,防止註釋二義性。在每個源文件的頭部要有必要的註釋信息,包括:版本號;作者;生成日期;模塊功能描述(如功能、主要算法、內部各部分之間 的關係、該文件與其它文件關係等)。
比如:
/**
* This class can be used to parse other classes containing constant definitions
* in public static final members. The <code>asXXXX</code> methods of this class
* allow these constant values to be accessed via their string names.
*
* @author Rod Johnson
* @author Juergen Hoeller
*/
4.2 Null規約
如果方法允許Null作爲參數,或者允許返回值爲Null,必須在JavaDoc中說明。如果沒有說明,方法的調用者不允許使用Null作爲參數, 並認爲返回值是Null Safe(不會返回NULL)。
/**
* get object.
*
* @ return the object to found or null if not found.
*/
pubic Object get(Integer id){
...
}
4.3 註釋標籤語法
@author 對類的說明 標明開發該類模塊的作者
@version 對類的說明 標明該類模塊的版本
@see 對類、屬性、方法的說明 參考轉向,也就是相關主題
@param 對方法的說明 對方法中某參數的說明
@return 對方法的說明 對方法返回值的說明
@exception 對方法的說明 對方法可能拋出的異常進行說明