1.1.1 代碼中的命名均不能以下划線或美元符號開始,也不能以下划線或美元符號結束
1.1.2 代碼中的命名嚴禁使用拼音與英文混合的方式,更不允許直接使用中文的方式
1.1.3 / 1.1.4 類名使用UpperCamelCase風格,必須遵從駝峰形式(某些情況諸如領域模型相關的命名除外);方法名、參數名、成員變量、局部變量都統一使用lowerCamelCase風格,必須遵從駝峰形式
1.1.5 常量命名全部大寫,單詞間用下划線隔開
1.1.9 包名統一使用小寫,點分隔符之間有且僅有一個自然語義的英語單詞
1.1.6 抽象類命名使用Abstract或Base開頭;異常類命名使用Exception結尾;測試類命名以它要測試的類的名稱開始,以Test結尾
1.1.13 對於Service和DAO類,基於SOA的理念,暴露出來的服務一定是接口,內部的實現類用Impl的后綴與接口區別
1.1.13 如果是形容能力的接口名稱,取對應的形容詞做接口名 1.1.14 枚舉類名建議帶上Enum后綴,枚舉成員名稱需要全大寫,單詞間用下划線隔開
1.1.11 如果使用到了設計模式,建議在類名中體現出具體模式
1.1.9 包名統一使用單數形式;類名如果有復數含義,類名可以使用復數形式
1.2.1 不允許出現任何魔法值(即未經定義的常量)直接出現在代碼中
1.2.3 不要使用一個常量類維護所有常量,應該按常量功能進行歸類,分開維護
1.2.4 常量的復用層次有五層:跨應用共享常量、應用內共享常量、子工程內共享常量、包內共享常量、類內共享常量
1.2.5 如果變量值僅在一個范圍內變化用Enum類。如果還帶有名稱之外的延伸屬性,必須使用Enum類
1.1.12 盡量不要在接口里定義變量,如果一定要定義變量,肯定是與接口方法相關,並且是整個應用的基礎常量
1.2.2 long或者Long初始賦值時,必須使用大寫的L,不能是小寫的l,小寫容易跟數字1混淆,造成誤解
1.1.12 接口類中的方法和屬性不要加任何修飾符號(public 也不要加),保持代碼的簡潔性,並加上有效的Javadoc注釋
1.4.2 所有的覆寫方法,必須加@Override注解
1.4.3 可變參數必須放置在參數列表的最后。(提倡同學們盡量不用可變參數編程)
1.4.4 對外暴露的接口簽名,原則上不允許修改方法簽名,避免對接口調用方產生影響。接口過時必須加@Deprecated注解,並清晰地說明采用的新接口或者新服務是什么
1.4.5 不能使用過時的類或方法 1.4.10 序列化類新增屬性時,請不要修改serialVersionUID字段,避免反序列失敗
1.4.17 循環體內,字符串的聯接方式,使用StringBuilder的append
1.4.18 final可提高程序響應效率
1.4.19 慎用Object的clone方法來拷貝對象
1.4.7 所有的相同類型的包裝類對象之間值的比較,全部使用equals方法比較
1.4.8 所有的POJO類屬性必須使用包裝數據類型
1.4.8 RPC方法的返回值和參數必須使用包裝數據類型
1.4.8 所有的局部變量【推薦】使用基本數據類型 通常我們都會用is_disabled字段在數據庫中表示某一個表的記錄是否被邏輯刪除,而這個字段,在Java代碼中被映射成什么類型呢? Boolean?如果被映射成包裝類型,那么數據庫里面的這個字段就可以為null,有些讀者會說,這並沒有什么問題啊。可是,數據庫is_disabled字段如果為null,代表什么邏輯含義呢? 這條記錄究竟是有效還是無效? 如果這個字段不能為null,那么將其映射成基本類型是一個皆大歡喜的事情:既保證了數據庫數據的完整性,我們在初始化的時候還可以忽略這個字段,因為boolean天生的默認值就是false 方法命名
1.1.15 Service/DAO層方法命名規約 - 獲取單個對象的方法用get做前綴 - 獲取多個對象的方法用list做前綴 - 獲取統計值的方法用count做前綴 - 插入的方法用save(推薦)或insert做前綴 - 刪除的方法用remove(推薦)或delete做前綴 - 修改的方法用update做前綴 方法和屬性
1.4.9 定義DO/DTO/VO等POJO類時,不要設定任何屬性默認值
1.4.11 構造方法里面禁止加入任何業務邏輯,如果有初始化邏輯,請放在init方法中
1.4.14 當一個類有多個構造方法,或者多個同名方法,這些方法應該按順序放置在一起,便於閱讀
1.4.15 類內方法定義順序依次是:公有方法或保護方法 > 私有方法 > getter/setter方法
1.4.16 setter方法中,參數名稱與類成員變量名稱一致,this.成員名=參數名。在getter/setter方法中,盡量不要增加業務邏輯
1.4.20 類成員與方法訪問控制從嚴 格式規約
1.3.5 縮進采用4個空格,禁止使用tab字符
1.3 6. 單行字符數限不超過 120 個
1.3.8 IDE的text file encoding設置為UTF-8; IDE中文件的換行符使用Unix格式,不要使用windows格式
1.3.10 方法體內的執行語句組、變量的定義語句組、不同的業務邏輯之間或者不同的語義之間插入一個空行 並發處理
1.6.1 獲取單例對象需要保證線程安全,其中的方法也要保證線程安全
1.6.2 創建線程或線程池時請指定有意義的線程名稱,方便出錯時回溯
1.6.3 線程資源必須通過線程池提供,不允許在應用中自行顯式創建線程
1.6.4 線程池不允許使用Executors去創建,而是通過ThreadPoolExecutor去創建
1.6.9 多線程並行處理定時任務時,Timer運行多個TimeTask時,只要其中之一沒有捕獲拋出的異常,其它任務便會自動終止運行,使用ScheduledExecutorService則沒有這個問題
1.6.10 使用CountDownLatch進行異步轉同步操作,每個線程退出前必須調用countDown方法,線程執行代碼注意catch異常,確保countDown方法可以執行, 避免主線程無法執行至countDown方法,直到超時才返回結果回溯
1.6.13 volatile解決多線程內存不可見問題。對於一寫多讀,是可以解決變量同步問題,但是如果多寫,同樣無法解決線程安全問題
1.6.14 HashMap在容量不夠進行resize時由於高並發可能出現死鏈
1.6.15 ThreadLocal無法解決共享對象的更新問題,ThreadLocal對象建議使用static修飾。這個變量是針對一個線程內所有操作共有的,所以設置為靜態變量, 所有此類實例共享此靜態變量 注釋規約
1.8.5 所有的枚舉類型字段必須要有注釋,說明每個數據項的用途
1.8.6 與其"半吊子"英文來注釋,不如用中文注釋把問題說清楚。專有名詞與關鍵字保持英文原文即可
1.8.8 注釋掉的代碼盡量要配合說明,而不是簡單的注釋掉
1.8.10 好的命名、代碼結構是自解釋的,注釋力求精簡准確、表達到位 數據庫規約
3.1.1 是與否概念的字段,必須使用is_xxx的方式命名,數據類型是unsigned tinyint( 1表示是,0表示否)
3.1 2 表名、字段名必須使用小寫字母或數字;禁止出現數字開頭,禁止兩個下划線中間只出現數字
3.1.3 表名不使用復數名詞
3.1.4 禁用保留字
3.1.5 唯一索引名為uk_字段名;普通索引名則為idx_字段名
3.1.10 表的命名最好是加上業務名稱_表的作用
3.1.11 庫名與應用名稱盡量一致
3.1.6 小數類型為decimal,禁止使用float和double
3.1.7 如果存儲的字符串長度幾乎相等,使用char定長字符串類型
3.1.8 varchar是可變長字符串,不預先分配存儲空間,長度不要超過5000 明確日期和時間,日期使用date類型並使用xxDate進行Java字段命名,時間使用date_time類型並使用xxTime進行Java字段命名,以示區分
3.1.9 表必備三字段:id, gmt_create, gmt_modified
3.1.8 如果存儲長度大於此值,定義字段類型為text,獨立出來一張表,用主鍵來對應,避免影響其它字段索引效率
3.1.12 如果修改字段含義或對字段表示的狀態追加時,需要及時更新字段注釋
3.1.13 字段允許適當冗余,以提高性能,但是必須考慮數據同步的情況
3.1.14 單表行數超過500萬行或者單表容量超過2GB,才推薦進行分庫分表
3.1.15 合適的字符存儲長度,不但節約數據庫表空間、節約索引存儲,更重要的是提升檢索速度
3.2.1 業務上具有唯一特性的字段,即使是組合字段,也必須建成唯一索引
3.2.2 超過三個表禁止join
3.2.3 在varchar字段上建立索引時,必須指定索引長度
3.2.4 頁面搜索嚴禁左模糊或者全模糊
3.2.5 如果有order by的場景,請注意利用索引的有序性
3.2.7 利用延遲關聯或者子查詢優化超多分頁場景
3.2.9 建組合索引的時候,區分度最高的在最左邊 禁止超過2個表的join語句出現在程序中 另外有關嚴禁使用全模糊查找,建組合索引時,區分度最高的往左放這些原則,在一定程度上會改變我們編寫程序的習慣,所以應該時刻注意。
3.3.1 不要使用count(列名)或count(常量)來替代count(*)
3.3.5 在代碼中寫分頁查詢邏輯時,若count為0應直接返回,避免執行后面的分頁語句
3.3.6 不得使用外鍵與級聯,一切外鍵概念必須在應用層解決
3.3.7 禁止使用存儲過程,存儲過程難以調試和擴展,更沒有移植性 3.3.9 in操作能避免則避免,若實在避免不了,需要仔細評估in后邊的集合元素數量,控制在1000個之內 3.4.1 在表查詢中,一律不要使用 * 作為查詢的字段列表,需要哪些字段必須明確寫明
1.7.3 推薦盡量少用else, if-else的方式可以改寫成:
if(condition){
...
return obj;
}
// 接着寫else的業務邏輯代碼;
1.7.3 如果非得使用if()...else if()...else...方式表達邏輯,【強制】請勿超過3層,超過請使用狀態設計模式
1.7.5 循環體中的語句要考量性能,以下操作盡量移至循環體外處理,如定義對象、變量、獲取數據庫連接,進行不必要的try-catch操作 這一條值得說一下,因為有些代碼會走得比較深,寫着寫着就忘了它處於循環體的內部了。所以保持一個謹慎的心態比較重要。
1.7.7 方法中需要進行參數校驗的場景:
1) 調用頻次低的方法。
2) 執行時間開銷很大的方法,參數校驗時間幾乎可以忽略不計,但如果因為參數錯誤導致中間執行回退,或者錯誤,那得不償失。
3) 需要極高穩定性和可用性的方法。
4) 對外提供的開放接口,不管是RPC/API/HTTP接口。
5) 敏感權限入口。
1.7.8 方法中不需要參數校驗的場景:
1) 極有可能被循環調用的方法,不建議對參數進行校驗。但在方法說明里必須注明外部參數檢查
2) 底層的方法調用頻度都比較高,一般不校驗。畢竟是像純凈水過濾的最后一道,參數錯誤不太可能到底層才會暴露問題。一般DAO層與Service層都在同一個應用中, 部署在同一台服務器中,所以DAO的參數校驗,可以省略
3) 被聲明成private只會被自己代碼所調用的方法,如果能夠確定調用方法的代碼傳入參數已經做過檢查或者肯定不會有問題,此時可以不校驗參數 在業務邏輯中盡可能不要使用setter方法,而是使用構造函數或者封裝成一個有邏輯意義的方法,提高代碼的可讀性
在業務邏輯中盡可能不要使用setter方法,而是使用構造函數或者封裝成一個有邏輯意義的方法,提高代碼的可讀性
在上面的代碼中,左側代碼中的setter方法調用,會被封裝到ShuttleOrder對象中的cancel方法中去。在實際的service代碼中,只會出現下半部分的一行代碼。
這樣做的好處在於:cancel這個方法被封裝后,shuttleOrder.cancel()的調用從可讀性上要明顯優於使用2句setter方法,同時也為將來的邏輯擴展預留了位置。這也是面向對象的一種實踐