Java程式設計風格主題分享
為什麼要有程式設計風格?
好的代碼風格應當是優雅的!
優雅高效的代碼,代碼邏輯直接了當,叫缺陷難以隐藏,盡量減少依賴關系,便于維護;依據某種分層戰略完善錯誤處理代碼,性能調至最優,省的引誘别人做沒規矩的優化,搞出一堆混亂。
整潔的代碼簡單直接,整潔的代碼從不隐藏設計者的意圖,充滿幹淨利落的抽象和直截了當的控制語句整潔的代碼應可由作者之外的開發者閱讀和增補。應當有單元測試和驗收測試。它使用有意義的命名,它隻提供一種而非多種做一件事的途徑。他隻有盡量少的依賴關系,而且要明确的定義和提供清晰、盡量少的API。代碼應當通過其字面表達含義,因為不同的語言導緻并非所有必須資訊均可通過代碼自身清晰表達。
整潔代碼整潔的代碼總是看起來像是某位特别在意他的人寫的。幾乎沒有更改的餘地。在意代碼能夠通過測試沒有重複代碼展現系統中的全部設計理念包括盡量少的實體,比如類、方法、函數如果每個例程都讓你感到深合己意,那就是整潔代碼。如果代碼讓變成語言看起來像是專為解決那個問題而存在,就可以稱之為漂亮的代碼
是以好的程式設計風格能夠使代碼結構清晰、讓代碼是自注釋的、能夠讓自己看懂以前的代碼、看懂同僚的代碼、讓同僚看懂自己的代碼、快速看懂代碼。
1. 代碼通用命名
命名應名副其實,避免誤導,做有意義的區分。要區分名稱,就要以讀者能鑒别不同之處的方式來區分,使用可讀出來的名稱,使用可搜尋出來的名稱,名稱長短與其作用域大小相對應,不應當讓讀者在腦中把你的名稱翻譯為他們熟知的名稱。
命名應避免思維映射,明确是王道,有意義的命名,類名名詞或名詞短語,方法名動詞或動詞短語。每個概念對應一個詞,避免将同一個單詞用于不同的目的。别用雙關語遵循“一詞一義”規則,使用解決方案領域名稱,使用源自所涉問題領域的名稱,添加有意義的語境。
命名短小,隻做一件事,每個函數一個抽象層級。自頂向下讀代碼:向下規則使用描述性的名稱函數短小,功能越集中,越便于起個好名,一進制函數辨別參數辨別true、false,二進制函數函數函數參數,三元函數參數對象參數清單,無副作用分割指令與詢問,使用異常代替傳回錯誤碼。
1) 不要使用數字、下劃線、特殊字元開頭 代碼中的命名均不能以下劃線或美元符号開始,也不能以此結束;
2) 嚴禁中英文結合,更不允許直接使用英文;
3) 不要使用拼音
4) 不要使用用無意義的命名:int a,b;Project project1,project2
5) 盡量表達意圖 最好言意感
6) 使用大家都知道的縮寫,不要自己造縮寫
7) 類名使用駝峰形式,但DO/BO/DTO/VO除外;字尾如POJO應全部大寫 不應使用駝峰命名
8) 方法名、參數名、成員變量、局部變量統一使用駝峰;
9) 常量名全部大寫,單詞間下劃線隔開,不嫌名長,力求語義表述完整
10) 杜絕不規範縮寫,避免歧義
11) 包名全小寫
12) 如果用到了設計模式,類名中展現出具體模式,如:xxxFactory
13) 接口中,方法和屬性不要加任何修飾符,并加上java doc注釋
14) 重寫或實作方法時,加@Overide注解
15) 開發過程中重命名,可能導緻不想重命名的檔案修改 在重命名時需要檢視相關修改項,小範圍手動修改
16) 轉換可以 用2代替To
17) MVC各層命名規約
Service/Dao層
• 擷取單個對象 get 字首
o 擷取多個對象 list 字首
o 擷取統計值的方法 count 字首
o 插入 save 字首
o 删除 remove
o 修改 update
2. 代碼注釋
1) 類,類屬性,類方法,枚舉,枚舉項,使用javadoc規範注釋:/*注釋/
2) 注釋請使用中文
3) 類注釋請加建立人與建立時間
4) 方法邏輯有修改,請一起修改注釋
5) 簡單業務,方法名已經代表含義,可不加注釋
6) 複雜業務必須加注釋
7) 方法中的業務有明顯分層的請使用空行隔開,并為每層業務加簡單注釋說明
8) 類、類屬性、類方法的注釋必須使用/*内容/格式;不得使用//xxx方式;
9) 方法内部單行注釋,在被注釋語句上方另起一行,使用 // 注釋;方法内部多行注釋使用 /* */注釋;
10) 注釋掉的代碼,盡量詳細說明一下原因;如果代碼無用,直接删除;
11) 注釋不能美化糟糕的代碼
3. 代碼結構
1) 屬性之間,方法之間,屬性與方法之間建議有一個空行隔開
2) 一個類中的代碼顯示層級:屬性>構造器>公共方法>保護方法>私有方法>内部類>setter&getter
3) 控制,循環語句即使隻有一行代碼也要使用{}包裹
4) switch語句中每一個case語句請根據情況使用break;return;跳出循環,必須以default收尾
5) 一行代碼過長請折行
6) 鍊式調用請折行
7) 複雜的判斷請抽取成一個易懂的變量名或方法
4. 檔案編碼
【強制】 所有文本檔案請設定編碼為UTF-8
5. Java包
1) 包名全部小寫
2) 包名每一層級盡量用一個單詞:com.gpf.xmxx.order
3) 必須使用多個單詞的情況,之間不要有大寫:com.gpf.xmxx.common.fileserver
4) 組織項目包結構字首:org.組織名項目名
5) 公司公司包結構字首:com.公司名.項目名
6) 業務接口包service
7) 業務服務包server
8) 業務模型包mode1
9) 業務通用包common
10) 業務工具包util
11) 業務持久層包dao
12) 業務持久層複雜邏輯包manager
13) 業務控制層包controller
14) 業務Http接口層包api
6. Java類
1) 類名格式:首字母大寫駝峰格式
2) 普通類名一般是一種事物:Dog Order Project
3) 接口類名一般是行為角色:Executor CacheManager Handler Roulapper Flyable
4) 按口實作類請盡量以按口名為字尾:RediscacheManger UserRowMapper
5) 抽象類以Abstract開頭
6) 業務接口類以 Service結尾
7) 業務接口實作類以5erviceImp1結尾複雜持久層邏輯類以manager結尾
8) 業務控制層以controller結尾
9) 業務Http接口層以Api結尾
10) POJ0類以BO|VO|DTO|Query|FormlParam結尾
POJO字尾不要書寫駝峰 全部大寫
11) 如果使用了設計模式,盡量加設計模式字尾:Proxy lFactory lstrategy lcommondlIterator
12) 在重寫和實作 一定要加@Override
13) 代碼結構應當自治 不要給大家添麻煩
14) 代碼編寫順序需要統一 如:先屬性後方法 先GET後POST 友善閱讀
7. 工具類
1) 工具類使用final修飾類名
2) 工具類構造函數必須私有
3) 通用工具類以util結尾:Cacheutil Dictutil stringutil
4) 通用工具類必須與業務無關
5) 業務工具類以業務類名加s字尾:Dogs Orders Projects collections Arrays
6) 業務工具類必須和業務子產品在一起
7) 業務工具類隻跟該業務有關
8) 優先考慮業務工具類,避免通用工具類
8. Java屬性與方法
1) 屬性|方法名:首字母小寫駝峰格式
2) 常量屬性:全部大寫,多單詞以下劃線隔開:BATCH PAGE_SIZE
3) 多個常量屬于一個範疇,使用範疇字首與其他進行區分:
4) REQUEST_USER,REQUEST_DICT,DATE_YEAR,DATE_MONTH,DATE_DAY
5) 接口中的屬性和方法不需要加public abstrict static final修飾符
6) 屬性引用盡量使用接口、抽象類而不是實作
7) 方法名一定要表達方法含義、精簡(含義優先)
8) 業務接口中操作業務的方法名一般不需要包含業務名稱,因為有業務類名的限定。如projectservice.getProject->projectservice.get
9) 參數名盡量表達出參數的含義:Project updateproject;Project insertProject;Project detail;ProjectAccountVirtualPhone bindInfo;AccountVirtualPhone callInfo
9. 配置
1) 配置檔案中的配置命名:應用名。子產品名。業務名。屬性,如:
xmxx.db.xs.jdbc.ur1;xmxx.common.fileserver.ali.host;xmxx.account.server.virtualphone.huawei.h ost;xmxx.web.portal.session.redis.namespace;
2) 配置類可以以config、property結尾
3) 全局配置與具體業務無關
4) 業務需要配置,請單獨寫一個業務配置
5) 業務配置類隻負責該業務配置
6) 【推薦】不要使用一個常量類維護所有的常量,應該按常量功能進行歸類,分開維護;常量的分類層次問題;
10. 資料庫
1) 各種名稱全部小寫,多單詞用隔開
2) 資料庫名:db業務
3) 表名不要使用複數
4) 一組業務表統一使用相關業務字首:order,order_product,order_status
5) 唯一索引使用uk開頭:uk_email
6) 普通索引使用idx開頭
7) 【強制】使用
count(*)
來統計行數,不要使用
count( 列名 )
或
count(常量)
來替代
count(*)
。
count(*)
就是 SQL 92 定義
的标準統計行數的文法,跟資料庫無關,跟 NULL 和非 NULL 無關。
說明: count(*) 會統計值為 NULL 的行,而 count( 列名 ) 不會統計此列為 NULL 值的行。
8) 【強制】 count(distinct col) 計算該列除 NULL 之外的不重複數量。注意 count(distinct
col 1, col 2 ) 如果其中一列全為 NULL ,那麼即使另一列有不同的值,也傳回為 0。
9) 【強制】當某一列的值全是 NULL 時, count(col) 的傳回結果為 0,但 sum(col) 的傳回結果為
NULL ,是以使用 sum() 時需注意 NPE 問題。
正例:可以使用如下方式來避免 sum 的 NPE 問題: SELECT IF(ISNULL(SUM(g)) ,0, SUM(g))
FROM table;
10) 【強制】使用 ISNULL() 來判斷是否為 NULL 值。注意: NULL 與任何值的直接比較都為 NULL。
說明:
① NULL<>NULL 的傳回結果是 NULL ,而不是 false 。
② NULL = NULL 的傳回結果是 NULL ,而不是 true 。
③ NULL<>1 的傳回結果是 NULL ,而不是 true 。
11) 小數類型為decimal、禁用float和double;
12) varchar,長度不要超過5000;如果存儲長度大于此值,定義為text,獨立出一張表,避免影響其它字段的索引效率;
13)為了可讀性,SQL代碼應當在Navicat中進行美化
11.OOP規約
1) Object的equals方法容易抛出空指針異常,應使用常量或者确定有值的對象來調用equals;
12.集合處理
1) 不要在foreach循環中進行元素的remove/add操作;remove元素請使用Iterator方式,如果并發操作,需要對Iterator對象加鎖;
2) 使用entryset周遊map集合,而不是keyset;
keyset其實是周遊了2次,一次是轉為Iterator對象,;另一次是從hashmap中取出key所對應的value;而entryset隻是周遊了一次就把key和value都放到了entry中;
3) 利用set集合元素的唯一性,而不是list的contains方法;
13.控制語句
1) if/else/for/while/do語句中必須使用大括号,即使隻有一行代碼;
2) 及時的判空操作
3) 不要在條件判斷中執行複雜的語句;可以定義一個布爾類型的變量去執行邏輯判斷;
4) 循環體的語句要考慮性能;
5) 減少if-else嵌套層數(不超過3層)
6) if不要太複雜,少用if-else; 快速結束 可以改寫為if。。return}。。;
7) switch case 一般要有break;防止case 穿透 必須要以default收尾;
14.異常處理
1) 避免抛出exception異常,應使用含有業務含義的自定義異常;
2) 對于runtimeexception,盡量通過預先檢查來規避;
3) 防止NPE問題;
15.工程規約
1) Object的equals方法容易抛空指針異常,使用常量或确定有值的對象來調用 equals方法
2) 當一個類有多個構造方法,或者多個同名方法,這些方法應該按順序放置在一起,便于閱讀
3) 類内方法定義順序依次是:公有方法或保護方法 -> 私有方法 -> getter/setter方法
4) 循環體内,字元串的聯接方式,使用 StringBuilder 的 append 方法進行擴充(JDK8編譯器已優化)
5) 集合初始化時,如果能預估集合大小,盡量指定集合初始值大小
6) 如果自定義對象做為 Map 的鍵,那麼必須重寫 hashCode 和 equals(盡量使用java定義的對象做鍵)
7) 避免使用List的contains方法,用Set代替之
16.雜項補充
1) 嘗試開始做單元測試
2)不要在控制器中直接調用dao層接口;
3) IDEA 阿裡巴巴代碼規約插件
4) 編碼中在比較等操作 确定值放前面
5) 公共類注明何時需要被繼承
6) 及時更新不用代碼
@Deprecated
7) 在調用(使用)第三方接口 最好标記正确 or 錯誤 的示例結果 官方接口位址和幫助文檔位址
8) 代碼在送出之前應當格式化,應當隻格式化自己送出的代碼 防止沖突