偶然看到阿里巴巴居然出書了踏烙?踢涌??趁著滿減活動(節(jié)約節(jié)約....)我趕緊買來準(zhǔn)備看看攘残,剛拿到的時候掂量了好多下拙友,總覺得商家給我少發(fā)了一本書,結(jié)果打開才知道..原來這本書這么小....
編碼規(guī)范的重要性
別人都說我們是搬磚的碼農(nóng)歼郭,但我們知道自己是追求個性的藝術(shù)家献宫。也許我們不會過多在意自己的外表和穿著,但在我們不羈的外表下实撒,骨子里追求著代碼的美姊途、系統(tǒng)的美涉瘾、設(shè)計(jì)的美,代碼規(guī)范其實(shí)就是一個對程序美的定義捷兰×⑴眩—— 引自 序
如果有一天在我們的項(xiàng)目中看到了這樣的代碼:
或者是這樣的代碼:
這樣美不美呢?或許看著是還挺美的贡茅,但是如果需要修改秘蛇,是不是人傻啦?
那這樣的代碼呢顶考?
作為一個對自己有一定要求的程序猿赁还,是不是第一反應(yīng)就是:
- 重寫!
- 原作者是誰驹沿?錘他艘策!
規(guī)范不一,就會像下圖中的小鴨和小雞對話一樣渊季,語言不通朋蔫,一臉囧相。雞同鴨講也恰恰形容了人與人之間溝通的痛點(diǎn)却汉,自說自話驯妄,無法達(dá)成一致意見。再舉一個生活中的例子合砂,交通規(guī)則靠左行駛還是靠右行駛青扔,兩者孰好孰壞并不重要,重要的是必須要在統(tǒng)一的方向上通行翩伪,表面上限制了自由微猖,但實(shí)際上是保障了公眾的人身安全。試想幻工,如果沒有規(guī)定靠右行駛励两,那樣的路況肯定擁堵不堪,險象環(huán)生囊颅。同樣当悔,過分自由隨意、天馬行空的代碼會嚴(yán)重的傷害系統(tǒng)的健康踢代,影響到可擴(kuò)展性以及可維護(hù)性盲憎。
- 總結(jié):代碼規(guī)范很重要!
關(guān)于編碼規(guī)范的三大圣戰(zhàn)
眾所周知胳挎,互聯(lián)網(wǎng)公司的優(yōu)勢在于效率饼疙,它是企業(yè)核心競爭力。體現(xiàn)在產(chǎn)品開發(fā)領(lǐng)域慕爬,就是夠溝通效率和研發(fā)效率窑眯。對于溝通效率的重要性屏积,可以從程序猿三大 “編碼理念之爭” 說起:
- 縮進(jìn)采用空格鍵,還是 Tab 鍵
- if 單行語句需要大括號還是不需要大括號
- 左大括號不換行磅甩,還是單獨(dú)另起一行
在美劇《硅谷》中炊林,有這樣的一個經(jīng)典鏡頭:
- 程序媛:Kid? 我們似乎很久沒有一起睡了。
- 程序猿:現(xiàn)在卷要?不可能渣聚!我永遠(yuǎn)不會和使用空格來縮進(jìn)的人睡在一起!
- 程序媛:(瘋狂敲 space 氣走了程序猿)
- 程序猿:(甩了一句)一個 Tab 可以代替 8個 空格僧叉!
之后程序猿就因?yàn)橐晥D一步跨下八個階梯而摔了....
Tab 鍵和空格鍵的爭議確實(shí)存在奕枝,并且在知乎上討論得火熱:寫代碼時,縮進(jìn)使用 tab 還是空格瓶堕?
- 總結(jié):使用 4 個空格好隘道,在《阿里巴巴 Java 開發(fā)手冊》中也明確支持了這樣的做法。下面也引用一張圖來調(diào)侃一下捞烟。
if 單語句是否需要換行薄声,也是爭論不休的話題当船。相對來說题画,寫過格式縮進(jìn)類編程語言的開發(fā)者, 更加習(xí)慣于不加大括號德频。《手冊》中明確 if/for 單行語句必須加大括號苍息,因?yàn)閱涡姓Z句的寫法,容易在添加邏輯時引起視覺上的錯誤判斷壹置。此外竞思,if 不加大括號還會有局部變量作用域的問題。
左大括號是否單獨(dú)另起一行钞护?因?yàn)?Go 語言的強(qiáng)制不換行盖喷,在這點(diǎn)上,“編程理念之爭” 的硝煙味似乎沒有那么濃难咕。如果一定要給一個理由课梳,那么換行的代碼可以增加一行,對于按代碼行數(shù)考核工作量的公司員工余佃,肯定傾向于左大括號前換行暮刃。《手冊》明確左大括號不換行!
- 總結(jié): 其實(shí)爆土,很多編程方式客觀上沒有對錯之分椭懊,一致性很重要,可讀性很重要步势,團(tuán)隊(duì)溝通效率很重要氧猬。
第1章:編程規(guī)約
這一章是對傳統(tǒng)意義上的代碼規(guī)范背犯,包括變量命名、代碼風(fēng)格盅抚、控制語句媳板、代碼注釋等基本的變成習(xí)慣,以及從高并發(fā)場景中提煉出來的集合處理技巧與并發(fā)多線程的注意事項(xiàng)泉哈。
1.1 命名風(fēng)格
第一條:【強(qiáng)制】代碼中的命名均不能以下劃線或美元符號開始蛉幸,也不能以下劃線或美元符號結(jié)束。
- 反例:
_name
/$name
/name_
/name$
盡管 $
可以作為標(biāo)識符使用丛晦,然而我們應(yīng)該盡量避免對其使用奕纫。
-
原因:
$
通常在編譯器生成的標(biāo)識符名稱中使用,如果我們也使用這個符號烫沙,可能會有一些意想不到的錯誤發(fā)生.... - 意想不到的錯誤示例:
package test;
public class User$VIP {
public static void main(String[] args) {
User user = new User();
User.VIP vip = user.new VIP();
vip.print();
}
}
class User{
class VIP{
void print(){
System.out.println("成員類");
}
}
}
仔細(xì)閱讀以下匹层,似乎并沒有什么問題,代碼也比較簡單锌蓄,但正在我們編譯的時候升筏,IDEA提示我們:
定義了重復(fù)的代碼?歸根到底瘸爽,都是 $
惹的禍您访!因?yàn)?$
被編譯器所使用,在源文件(.java 文件)編譯成字節(jié)碼(.class 文件)后剪决,會稱為頂層類型與嵌套類型之間的連接符灵汪。例如,如果存在一個頂層類 A柑潦,在其內(nèi)聲明了一個成員類 B享言,那么編譯之后就會產(chǎn)生兩個 class 文件,分別為 A.class
與 A$B.class
渗鬼。
就本程序來說览露,會生成 3 個 class 文件(如果可以編譯的話),分別是 User$VIP.class
(頂層類)譬胎、User.class
與 User$VIP.class
(User 類的成員類差牛,也就是類 VIP)。由于試圖存在兩個 User$VIP.class
所以才會報(bào)錯银择!
第三至第六條:【強(qiáng)制】
- 類名使用 UpperCamelCase 風(fēng)格多糠,方法名、參數(shù)名浩考、成員變量夹孔、局部變量都同意使用 lowerCamelCase 風(fēng)格,必須遵從駝峰形式。
- 變量命名全部大寫搭伤,單詞兼用下劃線隔開只怎,力求予以表達(dá)完整清楚,不要嫌名字太長怜俐。
正例:MAX_STOCK_COUNT / PRIZE_NUMBER_EVERYDAY
反例:MAX_COUNT / PRIZE_NUMBER
- 抽象類命名使用 Abstract 或 Base 開頭身堡;異常類命名使用 Exception 結(jié)尾;測試類命名以它要測試的類名開始拍鲤,以 Test 結(jié)尾贴谎。
第八條:【強(qiáng)制】 POJO 類中布爾類型的變量都不要加 is 前綴,否則部分框架解析會引起序列化錯誤季稳。
反例:定義為基本數(shù)據(jù)類型
Boolen isDeleted;
的屬性擅这,它的方法名稱也是isDeleted()
,RPC 框架在反向解析的時候景鼠,“誤以為” 對應(yīng)的屬性名稱是deleted
仲翎,導(dǎo)致屬性獲取不到拋出異常。
第十二條:【推薦】 如果模塊铛漓、類溯香、方法使用了設(shè)計(jì)模式,應(yīng)在命名時體現(xiàn)出具體模式
- 說明: 將設(shè)計(jì)模式體現(xiàn)在名字中浓恶,有利于閱讀者快速理解架構(gòu)設(shè)計(jì)理念玫坛。
正例:
public class OrderFactory;
public class LoginProxy;
public class ResourceObserver;
第十三條:【推薦】 接口類中的方法和屬性不要加任何修飾符號(public 也不要加),保持代碼的間接性问顷,并加上有效的 Javadoc 注釋昂秃。盡量不要在接口里定義變量禀梳,如果一定要定義變量杜窄,必須是與接口方法相關(guān)的,并且是整個應(yīng)用的基礎(chǔ)變量算途。
正例:
接口方法簽名:void commit();
接口基礎(chǔ)變量:String COMPANY = "alibaba";
反例:
接口定義方法:public abstract void commit();
- 說明: 如果 JDK8 中接口允許有默認(rèn)實(shí)現(xiàn)塞耕,那么這個 default 方法,是對所有實(shí)現(xiàn)類都有價值的默認(rèn)實(shí)現(xiàn)嘴瓤。
第十四條:接口和實(shí)現(xiàn)類的命名規(guī)則
- 1):【強(qiáng)制】 對于 Service 和 DAO 類扫外,基于 SOA 的理念,暴露出來的服務(wù)一定是接口廓脆,內(nèi)部的實(shí)現(xiàn)類用 Impl 后綴與接口區(qū)別筛谚。
正例: CacheServiceImpl 實(shí)現(xiàn) CacheServcie 接口
- 2):【推薦】 如果是形容能力的接口名稱,取對應(yīng)的形容詞為接口名(通常是 -able 的形式)停忿。
正例: AbstractTranslator 實(shí)現(xiàn) Translatable驾讲。
1.2 常量定義
第二條:【強(qiáng)制】 long 或者 Long 初始賦值時,使用大寫的 L,不能是小寫的 l吮铭。小寫的 l 容易跟數(shù)字 1 混淆时迫,造成誤解。
-
說明:
Long a = 2l;
寫得是數(shù)字的 21 還是 Long 型的 2谓晌?
第三條:【推薦】 不要使用一個常量類維護(hù)所有變量掠拳,要按常量功能進(jìn)行歸類,分開維護(hù)纸肉。
- 說明: 大而全的變量類溺欧,非得使用查找功能才能定位到修改的常量,不利于理解和維護(hù)柏肪。
正例:緩存相關(guān)常量放在類 CacheConsts 下胧奔;系統(tǒng)配置相關(guān)常量放在 ConfigConsts 下。
1.3 代碼格式
public static void main(String[] args){
// 注釋的雙斜線與注釋內(nèi)容之間有且僅有一個空格
// 縮進(jìn) 4 個空格
String say = "hello";
// 運(yùn)算符的左右必須有 1 個空格
int flag = 0;
// 關(guān)鍵字 if 與括號之間必須有 1 個空格预吆,括號內(nèi)的 f與左括號龙填、
// 0 與右括號之間不需要空格
if (flag == 0) {
System.out.println(say);
}
// 左大括號前加空格且不換行;左大括號后換行
if (flag == 1) {
System.out.println("world");
// 右大括號前換行拐叉,右大括號后有 else岩遗,不用換行
} else {
System.out.println("ok");
// 在右大括號后直接結(jié)束,則必須換行
}
}
第八條:【強(qiáng)制】 方法參數(shù)在定義和傳入時凤瘦,多個參數(shù)逗號后邊必須加空格宿礁。
正例:下例中實(shí)參的“one”,后邊必須要有一個空格蔬芥。
method("one", "two", "three");
1.4 OOP 規(guī)約
第二條:【強(qiáng)制】 所有的復(fù)寫方法梆靖,必須加 @Override 注解。
-
說明: getObject() 與 get0bject() 的問題笔诵。一個是字母 O,一個是數(shù)字 0返吻,
加 @Override 注解可以準(zhǔn)確判斷是否覆蓋成功。另外乎婿,如果在抽象類中對方法簽名進(jìn)行修改测僵,其實(shí)現(xiàn)類會馬上編譯報(bào)錯。
第七條:【強(qiáng)制】 所有相同類型的包裝類對象之間值得比較谢翎,全部使用 equals 方法
-
說明: 對于
Intergre var = ?
在 -128~127 范圍內(nèi)的賦值捍靠, Integer 對象是在 IntegerCache.cache 中產(chǎn)生的,會復(fù)用已有的對象森逮,這個區(qū)間內(nèi)的 Integer 值可以直接使用 == 進(jìn)行判斷榨婆,但是這個區(qū)間之外的所有數(shù)據(jù),都會在堆上產(chǎn)生褒侧,并不會復(fù)用已有對象良风。這是一個大坑颜武,推薦使用 equals 方法進(jìn)行判斷。
第十二條:【強(qiáng)制】 POJO 類必須寫 toString 方法拖吼。在使用 IDE 中的工具 source>generate toString 時鳞上,如果繼承了另一個 POJO 類,注意在前面加一下 super.toString吊档。
- 說明: 在方法執(zhí)行拋出異常時篙议,可以直接調(diào)用 POJO 的 toString() 方法打印其屬性值,便于排查問題怠硼。
1.5 集合處理
第七條:【強(qiáng)制】 不要在 foreach 循環(huán)里進(jìn)行元素的 remove / add 操作鬼贱。remove 元素請使用 Iterator 方式,如果并發(fā)操作香璃,需要對 Iterator 對象加鎖这难。
// 正例
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if (刪除元素的條件) {
iterator.remove();
}
}
// 反例
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
for (String item : list) {
// 如果把 1 改為 2 再試一下看看是否相同
if ("1".equals(item)) {
list.remove(item);
}
}
第十一條:【推薦】 高度注意 Map 類集合 K/V 能不能存儲 null 值得情況
1.6 并發(fā)處理
第三條:【強(qiáng)制】 線程資源必須通過線程池提供,不允許在應(yīng)用中自行顯式創(chuàng)建線程葡秒。
- 說明: 使用線程池的好處是減少在創(chuàng)建和銷毀線程上所消耗的時間以及系統(tǒng)資源姻乓,解決資源不足的問題。如果不適用線程池眯牧,有可能造成系統(tǒng)創(chuàng)建大量同類線程而導(dǎo)致消耗完內(nèi)存或者 “過渡切換” 的問題蹋岩。
1.7 控制語句
第二條:【強(qiáng)制】 在 if / else / for / while / do 語句中,必須使用大括號学少。即使只有一行代碼剪个,也應(yīng)該避免采用單行的編碼方式:if (condition) statements;
第三條:【強(qiáng)制】 在高并發(fā)場景中,避免使用 “等于” 判斷作為終端或退出的條件
- 說明: 如果并發(fā)控制沒有處理好版确,容易產(chǎn)生等值判斷被 “擊穿” 的情況扣囊,應(yīng)使用大于或小于的區(qū)間判斷條件來代替。
反例:判斷剩余獎品數(shù)量等于 0 時绒疗,終止發(fā)放獎品侵歇,但因?yàn)椴l(fā)處理錯誤導(dǎo)致獎品數(shù)量瞬間變成了負(fù)數(shù),這樣的話忌堂,活動無法終止盒至。
第四條:【推薦】 在表達(dá)異常的分支時,盡量少用 if-else 方式
- 說明: 如果不得不使用 if()...else if()...else... 方式表達(dá)邏輯士修,【強(qiáng)制】 避免后續(xù)代碼維護(hù)困難,請勿超過 3 層樱衷。
// 正例:超過 3 層的 if-else 邏輯判斷代碼可以使用衛(wèi)語句棋嘲、策略模式
// 狀態(tài)模式等來實(shí)現(xiàn),其中衛(wèi)語句實(shí)例如下:
public void today() {
if (isBusy()) {
System.out.println("change time,");
return;
}
if (isFree()) {
System.out.println("go to travel.");
return;
}
System.out.println("stay at home to learn Java");
return;
}
1.8 注釋規(guī)約
第一條:【強(qiáng)制】 類矩桂、類屬性沸移、類方法的注釋必須使用 Javadoc 規(guī)范,使用 /**內(nèi)容*/
格式,不得使用 //xxx
方式
第二條:【強(qiáng)制】 所有的抽象方法(包括接口中的方法)必須要用 Javadoc 注釋雹锣,除了返回值网沾、參數(shù)、異常說明外蕊爵,還必須指出該方法做什么事情辉哥,實(shí)現(xiàn)什么功能。
- 說明: 對子類的實(shí)現(xiàn)要求攒射,或者調(diào)用注意事項(xiàng)醋旦,請一并說明。
第三條:【強(qiáng)制】 所有的類都必須添加創(chuàng)建者和創(chuàng)建日期别渔。
1.9 其他
第三條:【強(qiáng)制】 后臺輸送給網(wǎng)頁的變量必須加$!{var}——中間是感嘆號
- 說明: 如果 var=null 或者不存在悬襟,那么 ${var} 會直接顯示在頁面上愈捅。
第四條:【強(qiáng)制】 注意 Math.random() 這個方法返回的是 double 類型,取值的范圍 0≤x<1(能夠取到零值捂人,注意除零異常),如果向獲取整數(shù)類型的隨機(jī)數(shù)矢沿,不要將 x 放大 10 的若干倍然后取整先慷,直接使用 Random 對象的 nextInt 或者 nextLong 方法。
第六條:【推薦】 不要在視圖模板中加入任何復(fù)雜的邏輯咨察。
- 說明: 根據(jù) MVC 理論论熙,視圖的職責(zé)是展示,不要搶模型和控制器的工作摄狱。
第4章:安全規(guī)約
“安全生產(chǎn)脓诡,責(zé)任重于泰山∶揭郏” 這句話同樣適用于軟件生產(chǎn)祝谚,本章主要說明編程中需要注意的比較基礎(chǔ)的安全準(zhǔn)則。
第一條:【強(qiáng)制】 隸屬于用戶個人的頁面或者功能必須進(jìn)行權(quán)限控制校驗(yàn)
- 說明: 放置皆有做水平權(quán)限校驗(yàn)就可以隨意訪問酣衷、修改交惯、刪除別人的數(shù)據(jù),比如查看他人的私信內(nèi)容穿仪、修改他人的訂單席爽。
第二條:【強(qiáng)制】 用戶敏感數(shù)據(jù)禁止直接展示,必須對展示數(shù)據(jù)進(jìn)行脫敏啊片。
- 說明: 個人手機(jī)號碼會顯示為 158****9119只锻,隱藏中間 4 位,防止個人隱私泄露紫谷。
第三條:【強(qiáng)制】 用戶輸入的 SQL 參數(shù)嚴(yán)格使用參數(shù)綁定或者 METADATA 字段值限定齐饮,防止 SQL 注入捐寥,禁止字符串拼接 SQL 訪問數(shù)據(jù)庫。
第四條:【強(qiáng)制】 用戶請求傳入的任何參數(shù)必須做有效性驗(yàn)證
-
說明: 忽略參數(shù)校驗(yàn)可能導(dǎo)致如下情況祖驱。
1)page size 過大導(dǎo)致內(nèi)存溢出
2)惡意 order by 導(dǎo)致數(shù)據(jù)庫慢查詢
3)任意重定向
4)SQL 注入
5)反序列化注入
6)正則輸入源串拒絕服務(wù) ReDoS
Java 代碼用正則來驗(yàn)證客戶端的輸入握恳,有些正則寫法驗(yàn)證普通用戶輸入沒有問題,但是如果攻擊人員使用的是特殊構(gòu)造的字符串來驗(yàn)證捺僻,則有可能導(dǎo)致死循環(huán)乡洼。
第五條:【強(qiáng)制】 禁止向 HTML 頁面輸出未經(jīng)安全過濾或未正確轉(zhuǎn)義的用戶數(shù)據(jù)。
第六條:【強(qiáng)制】 表單陵像、AJAX 提交必須執(zhí)行 CSRF 安全過濾
第七條:【強(qiáng)制】 在使用平臺資源就珠,譬如短信、郵件醒颖、電話妻怎、下單、支付泞歉,必須實(shí)現(xiàn)正確的防重放限制逼侦,如數(shù)量限制、疲勞度控制腰耙、驗(yàn)證碼校驗(yàn)榛丢,避免被濫刷、資損挺庞。
- 說明:如注冊時發(fā)送驗(yàn)證碼到手機(jī)晰赞,如果沒有限制次數(shù)和頻率,那么可以利用此功能騷擾到其它用戶选侨,并造成短信平臺資源浪費(fèi)掖鱼。
第5章:MySQL 數(shù)據(jù)庫
5.1 建表規(guī)約
第二條:【強(qiáng)制】 表名、字段名必須使用小寫字母或數(shù)字 援制, 禁止出現(xiàn)數(shù)字開頭戏挡,禁止兩個下劃線中間只出現(xiàn)數(shù)字。數(shù)據(jù)庫字段名的修改代價很大晨仑,因?yàn)闊o法進(jìn)行預(yù)發(fā)布褐墅,所以字段名稱需要慎重考慮。
- 說明: MySQL 在 Windows 下不區(qū)分大小寫洪己,但在 Linux 下默認(rèn)區(qū)分大小寫妥凳。因此,數(shù)據(jù)庫名码泛、表明猾封、字段名都不允許出現(xiàn)任何大寫字母,避免節(jié)外生枝噪珊。
正例: getter _ admin 晌缘, task _ config , level 3_ name
反例: GetterAdmin 痢站, taskConfig 磷箕, level 3 name
第四條:【強(qiáng)制】禁用保留字,如 desc 阵难、 range 岳枷、 match 、 delayed 等呜叫,請參考 MySQL 官方保留字空繁。
第五條: 【強(qiáng)制】主鍵索引名為 pk_ 字段名;唯一索引名為 uk _字段名 朱庆; 普通索引名則為 idx _字段名盛泡。
- 說明: pk_ 即 primary key;uk _ 即 unique key娱颊;idx _ 即 index 的簡稱傲诵。
第六條:【強(qiáng)制】小數(shù)類型為 decimal ,禁止使用 float 和 double 箱硕。
- 說明:float 和 double 在存儲的時候拴竹,存在精度損失的問題,很可能在值的比較時剧罩,得到不正確的結(jié)果栓拜。如果存儲的數(shù)據(jù)范圍超過 decimal 的范圍,建議將數(shù)據(jù)拆成整數(shù)和小數(shù)分開存儲惠昔。
第八條:【強(qiáng)制】 varchar 是可變長字符串幕与,不預(yù)先分配存儲空間,長度不要超過 5000舰罚,如果存儲長度大于此值纽门,定義字段類型為 text ,獨(dú)立出來一張表营罢,用主鍵來對應(yīng)赏陵,避免影響其它字段索引效率。
第九條:【強(qiáng)制】表必備三字段: id , gmt _ create , gmt _ modified
- 說明:其中 id 必為主鍵饲漾,類型為 unsigned bigint 蝙搔、單表時自增、步長為 1考传。 gmt _ create ,gmt _ modified 的類型均為 date _ time 類型吃型。
第十條: 【推薦】表的命名最好是加上“業(yè)務(wù)名稱_表的作用”。
正例: tiger _ task / tiger _ reader / mpp _ config
第十五條:【參考】合適的字符存儲長度僚楞,不但節(jié)約數(shù)據(jù)庫表空間勤晚、節(jié)約索引存儲枉层,更重要的是提升檢索速度。
正例:如下表赐写,其中無符號值可以避免誤存負(fù)數(shù)鸟蜡,且擴(kuò)大了表示范圍。
對象 | 年齡區(qū)間 | 類型 | 表示范圍 |
---|---|---|---|
人 | 150 歲之內(nèi) | unsigned tinyint | 無符號值:0 到 255 |
龜 | 數(shù)百歲 | unsigned smallint | 無符號值:0 到 65535 |
恐龍化石 | 數(shù)千萬年 | unsigned int | 無符號值:0 到約 42.9 億 |
太陽 | 約 50 億年 | unsigned bigint | 無符號值:0 到約 10 的 19 次方 |
5.2 索引規(guī)約
第五條: 【推薦】如果有 order by 的場景挺邀,請注意利用索引的有序性揉忘。 order by 最后的字段是組合索引的一部分,并且放在索引組合順序的最后端铛,避免出現(xiàn) file _ sort 的情況泣矛,影響查詢性能。
正例: where a =? and b =? order by c; 索引: a _ b _ c
反例:索引中有范圍查找禾蚕,那么索引有序性無法利用您朽,如: WHERE a >10 ORDER BY b; 索引 a _ b 無法排序。
第九條: 【推薦】建組合索引的時候夕膀,區(qū)分度最高的在最左邊虚倒。
正例:如果 where a =? and b =? , a 列的幾乎接近于唯一值产舞,那么只需要單建 idx _ a 索引即可魂奥。
- 說明: 存在非等號和等號混合判斷條件時,在建索引時易猫,請把等號條件的列前置耻煤。如: where a >? and b = ? 那么即使 a 的區(qū)分度更高,也必須把 b 放在索引的最前列准颓。
5.3 SQL 語句
第一條:【強(qiáng)制】不要使用 count( 列名 ) 或 count( 常量 ) 來替代 count( * ) 哈蝇, count( * ) 是 SQL 92 定義的標(biāo)準(zhǔn)統(tǒng)計(jì)行數(shù)的語法,跟數(shù)據(jù)庫無關(guān)攘已,跟 NULL 和非 NULL 無關(guān)炮赦。
- 說明: count( * ) 會統(tǒng)計(jì)值為 NULL 的行,而 count( 列名 ) 不會統(tǒng)計(jì)此列為 NULL 值的行样勃。
第六條: 【強(qiáng)制】不得使用外鍵與級聯(lián)吠勘,一切外鍵概念必須在應(yīng)用層解決。
- 說明: ( 概念解釋 ) 學(xué)生表中的 student _ id 是主鍵峡眶,那么成績表中的 student _ id 則為外鍵剧防。如果更新學(xué)生表中的 student _ id ,同時觸發(fā)成績表中的 student _ id 更新辫樱,則為級聯(lián)更新峭拘。外鍵與級聯(lián)更新適用于單機(jī)低并發(fā),不適合分布式、高并發(fā)集群 鸡挠; 級聯(lián)更新是強(qiáng)阻塞辉饱,存在數(shù)據(jù)庫更新風(fēng)暴的風(fēng)險 ; 外鍵影響數(shù)據(jù)庫的插入速度宵凌。
第八條: 【強(qiáng)制】數(shù)據(jù)訂正時鞋囊,刪除和修改記錄時止后,要先 select 瞎惫,避免出現(xiàn)誤刪除,確認(rèn)無誤才能執(zhí)行更新語句译株。
5.4 ORM 映射
整個規(guī)約對自己來說都挺有用的瓜喇,因?yàn)檎蒙婕暗竭@方面,幸好感覺臉不怎么疼歉糜。
第一條:【強(qiáng)制】在表查詢中乘寒,一律不要使用 * 作為查詢的字段列表,需要哪些字段必須明確寫明匪补。
- 說明: 1 ) 增加查詢分析器解析成本伞辛。2 ) 增減字段容易與 resultMap 配置不一致。
第二條:【強(qiáng)制】 POJO 類的 布爾 屬性不能加 is 夯缺,而數(shù)據(jù)庫字段必須加 is _蚤氏,要求在 resultMap 中進(jìn)行字段與屬性之間的映射。
- 說明: 參見定義 POJO 類以及數(shù)據(jù)庫字段定義規(guī)定踊兜,在 <resultMap>中 增加映射竿滨,是必須的。在 MyBatis Generator 生成的代碼中捏境,需要進(jìn)行對應(yīng)的修改于游。
第三條:【強(qiáng)制】不要用 resultClass 當(dāng)返回參數(shù),即使所有類屬性名與數(shù)據(jù)庫字段一一對應(yīng)垫言,也需要定義 贰剥; 反過來,每一個表也必然有一個與之對應(yīng)筷频。
- 說明: 配置映射關(guān)系蚌成,使字段與 DO 類解耦,方便維護(hù)截驮。
第七條:【強(qiáng)制】更新數(shù)據(jù)表記錄時笑陈,必須同時更新記錄對應(yīng)的 gmt _ modified 字段值為當(dāng)前時間。
第九條:【參考】@ Transactional 事務(wù)不要濫用葵袭。事務(wù)會影響數(shù)據(jù)庫的 QPS 涵妥,另外使用事務(wù)的地方需要考慮各方面的回滾方案,包括緩存回滾坡锡、搜索引擎回滾蓬网、消息補(bǔ)償窒所、統(tǒng)計(jì)修正等。
總結(jié)
瀏覽了一遍帆锋,還是學(xué)習(xí)到了很多東西吧吵取,上面也僅僅只是總結(jié)了對我自己比較收益,現(xiàn)階段我能吸收能實(shí)際感受得到的規(guī)約锯厢,如果想要 PDF 版的可以在這里下載:戳這里
歡迎轉(zhuǎn)載皮官,轉(zhuǎn)載請注明出處!
簡書ID:@我沒有三顆心臟
github:wmyskxz
歡迎關(guān)注公眾微信號:wmyskxz_javaweb
分享自己的Java Web學(xué)習(xí)之路以及各種Java學(xué)習(xí)資料