命名風(fēng)格
【強(qiáng)制】代碼中的命名均不能以下劃線或美元符號(hào)開始艾凯,也不能以下劃線或美元符號(hào)結(jié)束
【強(qiáng)制】代碼中的命名嚴(yán)禁使用拼音與英文混合的方式抵蚊,更不允許直接使用中文的方式。
說明:正確的英文拼寫和語法可以讓閱讀者易于理解,避免歧義薪丁。注意锯蛀,即使純拼音命名方式也要避免采用灭衷。
【強(qiáng)制】類名使用UpperCamelCase風(fēng)格,但以下情形例外:DO / BO / DTO / VO / AO / PO等谬墙。
```
正例:MarcoPolo / UserDO / XmlService / TcpUdpDeal / TaPromotion
反例:macroPolo / UserDo / XMLService / TCPUDPDeal / TAPromotion
```
分層領(lǐng)域模型規(guī)約:DO(DataObject):與數(shù)據(jù)庫表結(jié)構(gòu)一一對(duì)應(yīng)今布,通過DAO層向上傳輸數(shù)據(jù)源對(duì)象。DTO(DataTransferObject):數(shù)據(jù)傳輸對(duì)象拭抬,Service或Manager向外傳輸?shù)膶?duì)象部默。BO( BusinessObject):業(yè)務(wù)對(duì)象。 由Service層輸出的封裝業(yè)務(wù)邏輯的對(duì)象造虎。AO( ApplicationObject):應(yīng)用對(duì)象傅蹂。 在Web層與Service層之間抽象的復(fù)用對(duì)象模型,極為貼近展示層算凿,復(fù)用度不高份蝴。VO(ViewObject):顯示層對(duì)象,通常是Web向模板渲染引擎層傳輸?shù)膶?duì)象氓轰。POJO( Plain OrdinaryJavaObject):在本手冊(cè)中婚夫, POJO專指只有setter/getter/toString的簡(jiǎn)單類,包括DO/DTO/BO/VO等署鸡。Query:數(shù)據(jù)查詢對(duì)象案糙,各層接收上層的查詢請(qǐng)求限嫌。 注意超過2個(gè)參數(shù)的查詢封裝,禁止使用Map類來傳輸时捌。領(lǐng)域模型命名規(guī)約:數(shù)據(jù)對(duì)象:xxxDO怒医,xxx即為數(shù)據(jù)表名。數(shù)據(jù)傳輸對(duì)象:xxxDTO奢讨,xxx為業(yè)務(wù)領(lǐng)域相關(guān)的名稱稚叹。展示對(duì)象:xxxVO,xxx一般為網(wǎng)頁名稱拿诸。POJO是DO/DTO/BO/VO的統(tǒng)稱扒袖,禁止命名成xxxPOJO。
【強(qiáng)制】方法名佳镜、參數(shù)名僚稿、成員變量、局部變量都統(tǒng)一使用lowerCamelCase風(fēng)格蟀伸,必須遵從駝峰形式蚀同。
正例:localValue / getHttpMessage() / inputUserId
【強(qiáng)制】常量命名全部大寫,單詞間用下劃線隔開啊掏,力求語義表達(dá)完整清楚蠢络,不要嫌名字長。
正例:MAX_STOCK_COUNT 反例:MAX_COUNT
【強(qiáng)制】抽象類命名使用Abstract或Base開頭迟蜜;異常類命名使用Exception結(jié)尾刹孔;測(cè)試類命名以它要測(cè)試的類名開始,以Test結(jié)尾
【強(qiáng)制】類型與中括號(hào)緊挨相連來定義數(shù)組娜睛。
正例: 定義整形數(shù)組int[]arrayDemo;int[]arrayDemo;反例: 在main參數(shù)中髓霞,使用Stringargs[]來定義
【強(qiáng)制】POJO(簡(jiǎn)單的Java對(duì)象,實(shí)際就是普通JavaBeans)類中布爾類型的變量畦戒,都不要加is前綴方库,否則部分框架解析會(huì)引起序列化錯(cuò)誤。
反例:定義為基本數(shù)據(jù)類型BooleanisDeleted障斋;的屬性纵潦,它的方法也是isDeleted(),RPC框架在反向解析的時(shí)候垃环,“誤以為”對(duì)應(yīng)的屬性名稱是deleted邀层,導(dǎo)致屬性獲取不到,進(jìn)而拋出異常遂庄。
【強(qiáng)制】包名統(tǒng)一使用小寫寥院,點(diǎn)分隔符之間有且僅有一個(gè)自然語義的英語單詞。包名統(tǒng)一使用單數(shù)形式涛目,但是類名如果有復(fù)數(shù)含義只磷,類名可以使用復(fù)數(shù)形式经磅。
正例:應(yīng)用工具類包名為com.alibaba.ai.util、類名為MessageUtils(此規(guī)則參考spring的框架結(jié)構(gòu))
【強(qiáng)制】杜絕完全不規(guī)范的縮寫钮追,避免望文不知義。
反例:AbstractClass“縮寫”命名成AbsClass阿迈;condition“縮寫”命名成 condi元媚,此類隨意縮寫嚴(yán)重降低了代碼的可閱讀性。
【推薦】為了達(dá)到代碼自解釋的目標(biāo)苗沧,任何定義編程元素在命名時(shí)使用盡量完整單詞 組合來表達(dá)其意刊棕。
正例: 從遠(yuǎn)程 倉庫 拉取代碼的類 命名 為 PullCodeFromRemoteRepository 。 反例: 變量inta;? 的隨意命名 方式待逞。
【推薦】如果模塊甥角、接口、類识樱、方法使用了設(shè)計(jì)模式嗤无,在命名時(shí)體現(xiàn)出具體模式,將設(shè)計(jì)模式體現(xiàn)在名字中,有利于閱讀者快速理解架構(gòu)設(shè)計(jì)理念
正例:publicclassOrderFactory;publicclassLoginProxy;publicclassResourceObserver;
【推薦】接口類中的方法和屬性不要加任何修飾符號(hào)(public 也不要加)怜庸,保持代碼的簡(jiǎn)潔性当犯,并加上有效的Javadoc注釋。盡量不要在接口里定義變量割疾,如果一定要定義變量嚎卫,肯定是與接口方法相關(guān),并且是整個(gè)應(yīng)用的基礎(chǔ)常量宏榕。
正例:接口方法簽名voidf();接口基礎(chǔ)常量String COMPANY ="alibaba"; 反例:接口方法定義publicabstractvoidf(); 說明:JDK8中接口允許有默認(rèn)實(shí)現(xiàn)拓诸,那么這個(gè)default方法,是對(duì)所有實(shí)現(xiàn)類都有價(jià)值的默認(rèn)實(shí)現(xiàn)麻昼。
接口和實(shí)現(xiàn)類的命名有兩套規(guī)則:
【強(qiáng)制】對(duì)于Service和DAO類奠支,基于SOA的理念,暴露出來的服務(wù)一定是接口涌献,內(nèi)部的實(shí)現(xiàn)類用Impl的后綴與接口區(qū)別
正例:CacheServiceImpl實(shí)現(xiàn)CacheService接口胚宦。
【推薦】 如果是形容能力的接口名稱,取對(duì)應(yīng)的形容詞為接口名(通常是–able的形式)
正例:AbstractTranslator實(shí)現(xiàn) Translatable燕垃。
【參考】枚舉類名建議帶上Enum后綴枢劝,枚舉成員名稱需要全大寫,單詞間用下劃線隔開卜壕。
說明:枚舉其實(shí)就是特殊的常量類您旁,且構(gòu)造方法被默認(rèn)強(qiáng)制是私有。
正例:枚舉名字為ProcessStatusEnum的成員名稱:SUCCESS / UNKNOWN_REASON轴捎。
【參考】各層命名規(guī)約:
Service/DAO層方法命名規(guī)約 1) 獲取單個(gè)對(duì)象的方法用get作前綴鹤盒。2) 獲取多個(gè)對(duì)象的方法用list作前綴蚕脏。 3) 獲取統(tǒng)計(jì)值的方法用count作前綴。 4) 插入的方法用save/insert作前綴侦锯。5) 刪除的方法用remove/delete作前綴驼鞭。6) 修改的方法用update作前綴。領(lǐng)域模型命名規(guī)約1) 數(shù)據(jù)對(duì)象:xxxDO尺碰,xxx即為數(shù)據(jù)表名挣棕。2) 數(shù)據(jù)傳輸對(duì)象:xxxDTO,xxx為業(yè)務(wù)領(lǐng)域相關(guān)的名稱亲桥。3) 展示對(duì)象:xxxVO洛心,xxx一般為網(wǎng)頁名稱。4) POJO是DO/DTO/BO/VO的統(tǒng)稱题篷,禁止命名成xxxPOJO词身。
常量定義
【強(qiáng)制】不允許任何魔法值(即未經(jīng)預(yù)先定義的常量)直接出現(xiàn)在代碼中。
反例:String key ="Id#taobao_"+ tradeId; cache.put(key,value);
【強(qiáng)制】long或者Long初始賦值時(shí)番枚,使用大寫的L法严,不能是小寫的l,小寫容易跟數(shù)字1混淆户辫,造成誤解渐夸。
說明:Long a = 2l; 寫的是數(shù)字的21,還是Long型的2?
【推薦】不要使用一個(gè)常量類維護(hù)所有常量渔欢,按常量功能進(jìn)行歸類墓塌,分開維護(hù)。
說明:大而全的常量類奥额,非得使用查找功能才能定位到修改的常量苫幢,不利于理解和維護(hù)。
正例:緩存相關(guān)常量放在類CacheConsts下垫挨;系統(tǒng)配置相關(guān)常量放在類ConfigConsts下韩肝。
【推薦】如果變量值僅在一個(gè)固定范圍內(nèi)變化用enum類型來定義。
說明:如果存在名稱之外的延伸屬性使用enum類型九榔,下面正例中的數(shù)字就是延伸信息哀峻,表示一年中的第幾個(gè)季節(jié)。正例:publicenumSeasonEnum {? ? SPRING(1), SUMMER(2), AUTUMN(3), WINTER(4);intseq;? ? SeasonEnum(intseq){this.seq = seq;? ? }}
代碼格式
【強(qiáng)制】大括號(hào)的使用約定哲泊。如果是大括號(hào)內(nèi)為空剩蟀,則簡(jiǎn)潔地寫成{}即可,不需要換行切威;如果是非空代碼塊則:
左大括號(hào)前不換行育特。
左大括號(hào)后換行。
右大括號(hào)前換行先朦。
右大括號(hào)后還有else等代碼則不換行缰冤;
表示終止的右大括號(hào)后必須換行犬缨。
【強(qiáng)制】 左小括號(hào)和字符之間不出現(xiàn)空格;同樣棉浸,右小括號(hào)和字符之間也不出現(xiàn)空格怀薛。詳見第5條下方正例提示
【強(qiáng)制】if/for/while/switch/do等保留字與括號(hào)之間都必須加空格
【強(qiáng)制】任何二目、三目運(yùn)算符的左右兩邊都需要加一個(gè)空格涮拗。
說明:運(yùn)算符包括賦值運(yùn)算符=乾戏、邏輯運(yùn)算符&&、加減乘除符號(hào)等三热。
【強(qiáng)制】注釋的雙斜線與內(nèi)容之間有且僅一個(gè)空格。
正例://這是示例注釋三幻,請(qǐng)注意在雙斜線之后有一個(gè)空格 String ygb =newString();
【強(qiáng)制】單行字符數(shù)限不超過 120 個(gè)就漾,超出需要換行時(shí) 遵循如下原則:
第二行相對(duì)一縮進(jìn) 4個(gè)空格,從第三行開始不再繼續(xù)縮進(jìn)參考示例念搬。
運(yùn)算符與下文一起換行抑堡。
方法調(diào)用的點(diǎn)符號(hào)與下文一起換行。
方法調(diào)用時(shí)朗徊,多個(gè)參數(shù)首妖,需要換行時(shí),在逗號(hào)后進(jìn)行爷恳。
在括號(hào)前不要換行有缆,見反例。
正例:StringBuffer sb =newStringBuffer();// 超過120個(gè)字符的情況下温亲,換行縮進(jìn)4個(gè)空格棚壁,點(diǎn)號(hào)和方法名稱一起換行sb.append("zi").append("xin")....append("huang")....append("huang")....append("huang");
反例:StringBuffer sb =newStringBuffer();// 超過120個(gè)字符的情況下,不要在括號(hào)前換行sb.append("zi").append("xin")...append("huang");// 參數(shù)很多的方法調(diào)用可能超過120個(gè)字符栈虚,不要在逗號(hào)前換行method(args1, args2, args3, ..., argsX);
【強(qiáng)制】方法參數(shù)在定義和傳入時(shí)袖外,多個(gè)參數(shù)逗號(hào)后邊必須加空格。
正例:下例中實(shí)參的"a",后邊必須要有一個(gè)空格魂务。method("a","b","c");
【強(qiáng)制】IDE的text file encoding設(shè)置為UTF-8; IDE中文件的換行符使用Unix格式曼验,不要使用Windows格式。
【推薦】沒有必要增加若干空格來使某一行的字符與上一行對(duì)應(yīng)位置的字符對(duì)齊粘姜。
正例:inta =3;longb =4L;floatc =5F;StringBuffer sb =newStringBuffer();說明:增加sb這個(gè)變量鬓照,如果需要對(duì)齊,則給a相艇、b颖杏、c都要增加幾個(gè)空格,在變量比較多的情況下坛芽,是非常累贅的事情留储。
【推薦】不同邏輯翼抠、不同語義、不同業(yè)務(wù)的代碼之間插入一個(gè)空行分隔開來以提升可讀性获讳。 說明:沒有必要插入多個(gè)空行進(jìn)行隔開阴颖。
OOP規(guī)約
【強(qiáng)制】避免通過一個(gè)類的對(duì)象引用訪問此類的靜態(tài)變量或靜態(tài)方法,無謂增加編譯器解析成本丐膝,直接用類名來訪問即可
【強(qiáng)制】所有的覆寫方法量愧,必須加@Override注解。
【強(qiáng)制】外部正在調(diào)用或者二方庫依賴的接口帅矗,不允許修改方法簽名偎肃,避免對(duì)接口調(diào)用方產(chǎn)生影響。接口過時(shí)必須加@Deprecated注解浑此,并清晰地說明采用的新接口或者新服務(wù)是什么累颂。
【強(qiáng)制】不能使用過時(shí)的類或方法。
【強(qiáng)制】Object的equals方法容易拋空指針異常凛俱,應(yīng)使用常量或確定有值的對(duì)象來調(diào)用equals紊馏。
正例:"test".equals(object); 反例:object.equals("test");說明:推薦使用java.util.Objects#equals(JDK7引入的工具類)
【強(qiáng)制】所有的相同類型的包裝類對(duì)象之間值的比較,全部使用equals方法比較蒲犬。
說明:對(duì)于Integervar= ? 在-128至127范圍內(nèi)的賦值朱监,Integer對(duì)象是在IntegerCache.cache產(chǎn)生,會(huì)復(fù)用已有對(duì)象原叮,這個(gè)區(qū)間內(nèi)的Integer值可以直接使用==進(jìn)行判斷赫编,但是這個(gè)區(qū)間之外的所有數(shù)據(jù),都會(huì)在堆上產(chǎn)生篇裁,并不會(huì)復(fù)用已有對(duì)象沛慢,這是一個(gè)大坑,推薦使用equals方法進(jìn)行判斷达布。
【推薦】當(dāng)一個(gè)類有多個(gè)構(gòu)造方法团甲,或者多個(gè)同名方法,這些方法應(yīng)該按順序放置在一起黍聂,便于閱讀躺苦,此條規(guī)則優(yōu)先于第15條規(guī)則。
【推薦】 類內(nèi)方法定義的順序依次是:公有方法或保護(hù)方法 > 私有方法 > getter/setter方法产还。
說明:公有方法是類的調(diào)用者和維護(hù)者最關(guān)心的方法匹厘,首屏展示最好;保護(hù)方法雖然只是子類關(guān)心脐区,也可能是“模板設(shè)計(jì)模式”下的核心方法愈诚;而私有方法外部一般不需要特別關(guān)心,是一個(gè)黑盒實(shí)現(xiàn);因?yàn)槌休d的信息價(jià)值較低炕柔,所有Service和DAO的getter/setter方法放在類體最后酌泰。
【推薦】setter方法中,參數(shù)名稱與類成員變量名稱一致匕累,this.成員名 = 參數(shù)名陵刹。在getter/setter方法中,不要增加業(yè)務(wù)邏輯欢嘿,增加排查問題的難度
【推薦】循環(huán)體內(nèi)衰琐,字符串的連接方式,使用StringBuilder的append方法進(jìn)行擴(kuò)展炼蹦。
說明:反編譯出的字節(jié)碼文件顯示每次循環(huán)都會(huì)new出一個(gè)StringBuilder對(duì)象羡宙,然后進(jìn)行append操作,最后通過toString方法返回String對(duì)象掐隐,造成內(nèi)存資源浪費(fèi)辛辨。反例:Stringstr ="start";for(int i =0; i <100; i++) {? str = str +"hello";}
【推薦】類成員與方法訪問控制從嚴(yán):
控制語句
【強(qiáng)制】在一個(gè)switch塊內(nèi),每個(gè)case要么通過break/return等來終止瑟枫,要么注釋說明程序?qū)⒗^續(xù)執(zhí)行到哪一個(gè)case為止;在一個(gè)switch塊內(nèi)指攒,都必須包含一個(gè)default語句并且放在最后慷妙,即使空代碼。
【強(qiáng)制】在if/else/for/while/do語句中必須使用大括號(hào)允悦。即使只有一行代碼膝擂,避免采用
【強(qiáng)制】在高并發(fā)場(chǎng)景中,避免使用 ”等于 ”判斷作為中或退出的條件隙弛。 判斷作為中或退出的條件架馋。
說明: 如果并發(fā)控制沒有處理好,容易產(chǎn)生等值判斷被 如果并發(fā)控制沒有處理好全闷,容易產(chǎn)生等值判斷被 “擊穿 ”的情況叉寂,使用大于或小區(qū)間 的情況,使用大于或小區(qū)間 的情況总珠,使用大于或小區(qū)間 的情況屏鳍,使用大于或小區(qū)間 判斷條件來代替。 反例: 判斷剩余獎(jiǎng)品數(shù)量等于 0時(shí)局服,終止發(fā)放獎(jiǎng)品但因?yàn)椴⑻幚礤e(cuò)誤導(dǎo)致數(shù)量瞬間變 時(shí)钓瞭,終止發(fā)放獎(jiǎng)品但因?yàn)椴⑻幚礤e(cuò)誤導(dǎo)致數(shù)量瞬間變 時(shí),終止發(fā)放獎(jiǎng)品但因?yàn)椴⑻幚礤e(cuò)誤導(dǎo)致數(shù)量瞬間變 成了負(fù)數(shù)淫奔, 這樣的話山涡,活動(dòng)無法終止。
【推薦】表達(dá)異常的分支時(shí),少用if-else方式鸭丛,這種方式可以改寫成
if(condition) {...returnobj;}//接著寫else的業(yè)務(wù)邏輯代碼;說明:如果非得使用if()...elseif()...else...方式表達(dá)邏輯竞穷,【強(qiáng)制】避免后續(xù)代碼維護(hù)困難,請(qǐng)勿超過3層系吩。
【推薦】除常用方法(如getXxx/isXxx)等外来庭,不要在條件判斷中執(zhí)行其它復(fù)雜的語句,將復(fù)雜邏輯判斷的結(jié)果賦值給一個(gè)有意義的布爾變量名穿挨,以提高可讀性月弛。
說明:很多if語句內(nèi)的邏輯相當(dāng)復(fù)雜,閱讀者需要分析條件表達(dá)式的最終結(jié)果科盛,才能明確什么樣的條件執(zhí)行什么樣的語句帽衙,那么,如果閱讀者分析邏輯表達(dá)式錯(cuò)誤呢贞绵? 正例:// 偽代碼如下finalbooleanexisted = (file.open(fileName,"w") !=null) && (...) || (...);if(existed) {...}反例:if((file.open(fileName,"w") !=null) && (...) || (...)) {...}
【推薦】循環(huán)體中的語句要考量性能厉萝,以下操作盡量移至循環(huán)體外處理,如定義對(duì)象榨崩、變量谴垫、獲取數(shù)據(jù)庫連接,進(jìn)行不必要的try-catch操作(這個(gè)try-catch是否可以移至循環(huán)體外)母蛛。
【推薦】避免采用取反邏輯運(yùn)算符翩剪。
說明: 取反邏輯不利于快速理解,并且寫法必然存在對(duì)應(yīng)的正向彩郊。正例: 使用if(x < 628)if(x < 628)if(x < 628) 來表達(dá) x 小于 628 前弯。反例: 使用if(!(x >= 628))if(!(x >= 628))if(!(x >= 628)) 來表達(dá) x 小于 628 。
【參考】下列情形秫逝,需要進(jìn)行參數(shù)校驗(yàn):
調(diào)用頻次低的方法恕出。
執(zhí)行時(shí)間開銷很大的方法。此情形中违帆,參數(shù)校驗(yàn)時(shí)間幾乎可以忽略不計(jì)浙巫,但如果因?yàn)閰?shù)錯(cuò)誤導(dǎo)致中間執(zhí)行回退,或者錯(cuò)誤前方,那得不償失狈醉。
需要極高穩(wěn)定性和可用性的方法。
對(duì)外提供的開放接口惠险,不管是RPC/API/HTTP接口苗傅。
敏感權(quán)限入口。
【參考】下列情形班巩,不需要進(jìn)行參數(shù)校驗(yàn):
極有可能被循環(huán)調(diào)用的方法渣慕。但在方法說明里必須注明外部參數(shù)檢查要求嘶炭。
底層調(diào)用頻度比較高的方法。畢竟是像純凈水過濾的最后一道逊桦,參數(shù)錯(cuò)誤不太可能到底層才會(huì)暴露問題眨猎。一般DAO層與Service層都在同一個(gè)應(yīng)用中,部署在同一臺(tái)服務(wù)器中强经,所以DAO的參數(shù)校驗(yàn)睡陪,可以省略。
被聲明成private只會(huì)被自己代碼所調(diào)用的方法匿情,如果能夠確定調(diào)用方法的代碼傳入?yún)?shù)已經(jīng)做過檢查或者肯定不會(huì)有問題兰迫,此時(shí)可以不校驗(yàn)參數(shù)
注釋規(guī)約
【強(qiáng)制】類稽莉、類屬性怒竿、類方法的注釋必須使用Javadoc規(guī)范,使用/*內(nèi)容/格式疼电,不得使用// xxx方式玲躯。
說明:在IDE編輯窗口中据德,Javadoc方式會(huì)提示相關(guān)注釋,生成Javadoc可以正確輸出相應(yīng)注釋跷车;在IDE中棘利,工程調(diào)用方法時(shí),不進(jìn)入方法即可懸浮提示方法朽缴、參數(shù)赡译、返回值的意義,提高閱讀效率不铆。
【強(qiáng)制】所有的類都必須添加創(chuàng)建者和創(chuàng)建日期。
【強(qiáng)制】方法內(nèi)部單行注釋裹唆,在被注釋語句上方另起一行誓斥,使用//注釋。方法內(nèi)部多行注釋使用/?/注釋许帐,注意與代碼對(duì)齊劳坑。
【強(qiáng)制】所有的枚舉類型字段必須要有注釋,說明每個(gè)數(shù)據(jù)項(xiàng)的用途成畦。
【推薦】與其“半吊子”英文來注釋距芬,不如用中文注釋把問題說清楚。專有名詞與關(guān)鍵字保持英文原文即可循帐。
反例:“TCP連接超時(shí)”解釋成“傳輸控制協(xié)議連接超時(shí)”框仔,理解反而費(fèi)腦筋。
【推薦】代碼修改的同時(shí)拄养,注釋也要進(jìn)行相應(yīng)的修改离斩,尤其是參數(shù)、返回值、異常跛梗、核心邏輯等的修改寻馏。
說明:代碼與注釋更新不同步,就像路網(wǎng)與導(dǎo)航軟件更新不同步一樣核偿,如果導(dǎo)航軟件嚴(yán)重滯后诚欠,就失去了導(dǎo)航的意義。
【參考】謹(jǐn)慎注釋掉代碼漾岳。在上方詳細(xì)說明轰绵,而不是簡(jiǎn)單地注釋掉。如果無用蝗羊,則刪除藏澳。
說明:代碼被注釋掉有兩種可能性:
1)后續(xù)會(huì)恢復(fù)此段代碼邏輯。
2)永久不用耀找。前者如果沒有備注信息翔悠,難以知曉注釋動(dòng)機(jī)。后者建議直接刪掉(代碼倉庫保存了歷史代碼)野芒。
【參考】對(duì)于注釋的要求:
第一蓄愁、能夠準(zhǔn)確反應(yīng)設(shè)計(jì)思想和代碼邏輯;
第二狞悲、能夠描述業(yè)務(wù)含義撮抓,使別的程序員能夠迅速了解到代碼背后的信息。完全沒有注釋的大段代碼對(duì)于閱讀者形同天書摇锋,注釋是給自己看的丹拯,即使隔很長時(shí)間,也能清晰理解當(dāng)時(shí)的思路荸恕;注釋也是給繼任者看的乖酬,使其能夠快速接替自己的工作。
【參考】好的命名融求、代碼結(jié)構(gòu)是自解釋的咬像,注釋力求精簡(jiǎn)準(zhǔn)確、表達(dá)到位生宛。避免出現(xiàn)注釋的一個(gè)極端:過多過濫的注釋县昂,代碼的邏輯一旦修改,修改注釋是相當(dāng)大的負(fù)擔(dān)陷舅。
反例:// put elephant into fridgeput(elephant, fridge);方法名put倒彰,加上兩個(gè)有意義的變量名elephant和fridge,已經(jīng)說明了這是在干什么莱睁,語義清晰的代碼不需要額外的注釋狸驳。
【參考】特殊注釋標(biāo)記预明,請(qǐng)注明標(biāo)記人與標(biāo)記時(shí)間。注意及時(shí)處理這些標(biāo)記耙箍,通過標(biāo)記掃描撰糠,經(jīng)常清理此類標(biāo)記。線上故障有時(shí)候就是來源于這些標(biāo)記處的代碼辩昆。
待辦事宜(TODO):( 標(biāo)記人阅酪,標(biāo)記時(shí)間,[預(yù)計(jì)處理時(shí)間]) 表示需要實(shí)現(xiàn)汁针,但目前還未實(shí)現(xiàn)的功能术辐。這實(shí)際上是一個(gè)Javadoc的標(biāo)簽,目前的Javadoc還沒有實(shí)現(xiàn)施无,但已經(jīng)被廣泛使用辉词。只能應(yīng)用于類,接口和方法(因?yàn)樗且粋€(gè)Javadoc標(biāo)簽)猾骡。
錯(cuò)誤瑞躺,不能工作(FIXME):(標(biāo)記人,標(biāo)記時(shí)間兴想,[預(yù)計(jì)處理時(shí)間]) 在注釋中用FIXME標(biāo)記某代碼是錯(cuò)誤的幢哨,而且不能工作,需要及時(shí)糾正的情況嫂便。
異常處理
【強(qiáng)制】Java 類庫中定義的可以通過預(yù)檢查方式規(guī)避的RuntimeException異常不應(yīng)該通過catch 的方式來處理捞镰,比如:NullPointerException,IndexOutOfBoundsException等等毙替。
說明:無法通過預(yù)檢查的異常除外岸售,比如,在解析字符串形式的數(shù)字時(shí)厂画,不得不通過catchNumberFormatException來實(shí)現(xiàn)冰评。 正例:if(obj !=null) {...}反例:try{ obj.method() }catch(NullPointerException e) {…}
【強(qiáng)制】異常不要用來做流程控制,條件控制木羹。
說明:異常設(shè)計(jì)的初衷是解決程序運(yùn)行中的各種意外情況,且異常的處理效率比條件判斷方式要低很多解孙。
【強(qiáng)制】catch時(shí)請(qǐng)分清穩(wěn)定代碼和非穩(wěn)定代碼坑填,穩(wěn)定代碼指的是無論如何不會(huì)出錯(cuò)的代碼。對(duì)于非穩(wěn)定代碼的catch盡可能進(jìn)行區(qū)分異常類型弛姜,再做對(duì)應(yīng)的異常處理脐瑰。
說明:對(duì)大段代碼進(jìn)行try-catch,使程序無法根據(jù)不同的異常做出正確的應(yīng)激反應(yīng)廷臼,也不利于定位問題苍在,這是一種不負(fù)責(zé)任的表現(xiàn)绝页。
【強(qiáng)制】捕獲異常是為了處理它,不要捕獲了卻什么都不處理而拋棄之寂恬,如果不想處理它续誉,請(qǐng)將該異常拋給它的調(diào)用者。最外層的業(yè)務(wù)使用者初肉,必須處理異常酷鸦,將其轉(zhuǎn)化為用戶可以理解的內(nèi)容.
【強(qiáng)制】有try塊放到了事務(wù)代碼中,catch異常后牙咏,如果需要回滾事務(wù)臼隔,一定要注意手動(dòng)回滾事務(wù)。
【強(qiáng)制】捕獲異常與拋異常妄壶,必須是完全匹配摔握,或者捕獲異常是拋異常的父類
【推薦】方法的返回值可以為null,不強(qiáng)制返回空集合丁寄,或者空對(duì)象等氨淌,必須添加注釋充分說明什么情況下會(huì)返回null值。
【推薦】防止NPE(編程語言中的空指針異常)狡逢,是程序員的基本修養(yǎng)宁舰,注意NPE產(chǎn)生的場(chǎng)景:
返回類型為基本數(shù)據(jù)類型,return包裝數(shù)據(jù)類型的對(duì)象時(shí)奢浑,自動(dòng)拆箱有可能產(chǎn)生NPE蛮艰。 反例:public int f() { return Integer對(duì)象}, 如果為null雀彼,自動(dòng)解箱拋NPE壤蚜。
數(shù)據(jù)庫的查詢結(jié)果可能為null。
集合里的元素即使isNotEmpty徊哑,取出的數(shù)據(jù)元素也可能為null袜刷。
遠(yuǎn)程調(diào)用返回對(duì)象時(shí),一律要求進(jìn)行空指針判斷莺丑,防止NPE著蟹。
對(duì)于Session中獲取的數(shù)據(jù),建議NPE檢查梢莽,避免空指針萧豆。
級(jí)聯(lián)調(diào)用obj.getA().getB().getC();一連串調(diào)用昏名,易產(chǎn)生NPE涮雷。
正例:使用JDK8的Optional類來防止NPE問題
【推薦】定義時(shí)區(qū)分unchecked / checked 異常,避免直接拋出new RuntimeException()轻局,更不允許拋出Exception或者Throwable洪鸭,應(yīng)使用有業(yè)務(wù)含義的自定義異常样刷。推薦業(yè)界已定義過的自定義異常,如:DAOException / ServiceException等览爵。
【參考】對(duì)于公司外的http/api開放接口必須使用“錯(cuò)誤碼”置鼻;而應(yīng)用內(nèi)部推薦異常拋出;跨應(yīng)用間RPC調(diào)用優(yōu)先考慮使用Result方式拾枣,封裝isSuccess()方法沃疮、“錯(cuò)誤碼”、“錯(cuò)誤簡(jiǎn)短信息”梅肤。
【參考】避免出現(xiàn)重復(fù)的代碼(Don’t Repeat Yourself)司蔬,即DRY原則。
說明:隨意復(fù)制和粘貼代碼姨蝴,必然會(huì)導(dǎo)致代碼的重復(fù)俊啼,在以后需要修改時(shí),需要修改所有的副本左医,容易遺漏授帕。必要時(shí)抽取共性方法,或者抽象公共類浮梢,甚至是組件化跛十。正例:一個(gè)類中有多個(gè)public方法,都需要進(jìn)行數(shù)行相同的參數(shù)校驗(yàn)操作秕硝,這個(gè)時(shí)候請(qǐng)抽冉嬗场:privatebooleancheckParam(DTO dto){...}
日志規(guī)約
【強(qiáng)制】應(yīng)用中不可直接使用日志系統(tǒng)(Log4j、Logback)中的API远豺,而應(yīng)依賴使用日志框架SLF4J中的API奈偏,使用門面模式的日志框架,有利于維護(hù)和各個(gè)類的日志處理方式統(tǒng)一躯护。
importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;privatestaticfinalLogger logger = LoggerFactory.getLogger(Abc.class);
【強(qiáng)制】日志文件推薦至少保存15天惊来,因?yàn)橛行┊惓>邆湟浴爸堋睘轭l次發(fā)生的特點(diǎn)。
【強(qiáng)制】應(yīng)用中的擴(kuò)展日志(如打點(diǎn)棺滞、臨時(shí)監(jiān)控裁蚁、訪問日志等)命名方式:
appName_logType_logName.log。logType:日志類型继准,推薦分類有stats/monitor/visit等枉证;logName:日志描述。這種命名的好處:通過文件名就可知道日志文件屬于什么應(yīng)用锰瘸,什么類型,什么目的昂灵,也有利于歸類查找避凝。 正例:mppserver應(yīng)用中單獨(dú)監(jiān)控時(shí)區(qū)轉(zhuǎn)換異常舞萄,如: mppserver_monitor_timeZoneConvert.log說明:推薦對(duì)日志進(jìn)行分類,如將錯(cuò)誤日志和業(yè)務(wù)日志分開存放管削,便于開發(fā)人員查看倒脓,也便于通過日志對(duì)系統(tǒng)進(jìn)行及時(shí)監(jiān)控。
【強(qiáng)制】對(duì)trace/debug/info級(jí)別的日志輸出含思,必須使用條件輸出形式或者使用占位符的方式崎弃。
正例:(條件)if(logger.isDebugEnabled()) {logger.debug("Processing trade with id: "+id+" and symbol: "+ symbol);}正例:(占位符)logger.debug("Processing trade with id: {} and symbol : {} ",id, symbol);
【強(qiáng)制】避免重復(fù)打印日志,浪費(fèi)磁盤空間含潘,務(wù)必在log4j.xml中設(shè)置additivity=false饲做。
正例:
【強(qiáng)制】異常信息應(yīng)該包括兩類信息:案發(fā)現(xiàn)場(chǎng)信息和異常堆棧信息。如果不處理遏弱,那么通過關(guān)鍵字throws往上拋出盆均。
正例:logger.error(各類參數(shù)或者對(duì)象toString+ "_" +e.getMessage(),e);
【推薦】謹(jǐn)慎地記錄日志。生產(chǎn)環(huán)境禁止輸出debug日志漱逸;有選擇地輸出info日志泪姨;如果使用warn來記錄剛上線時(shí)的業(yè)務(wù)行為信息,一定要注意日志輸出量的問題饰抒,避免把服務(wù)器磁盤撐爆肮砾,并記得及時(shí)刪除這些觀察日志。
說明:大量地輸出無效日志袋坑,不利于系統(tǒng)性能提升仗处,也不利于快速定位錯(cuò)誤點(diǎn)。記錄日志時(shí)請(qǐng)思考:這些日志真的有人看嗎咒彤?看到這條日志你能做什么疆柔?能不能給問題排查帶來好處?
【推薦】可以使用 warnwarn warn日志級(jí)別來記錄用戶輸入?yún)?shù)錯(cuò)誤的情況镶柱,避免投訴時(shí)無所適 從旷档。如非必要,請(qǐng)不在此場(chǎng)景打出 errorerror errorerror級(jí)別歇拆,避免頻繁報(bào)警鞋屈。 級(jí)
說明: 注意日志輸出的級(jí)別, errorerror errorerror級(jí)別只記錄系統(tǒng)邏輯出錯(cuò)故觅、異常 級(jí)別只記錄系統(tǒng)邏輯出錯(cuò)厂庇、異常 或者重要的錯(cuò)誤信息。
其他
【強(qiáng)制】在使用正則表達(dá)式時(shí)输吏,利用好其預(yù)編譯功能权旷,可以有效加快正則匹配速度。
【強(qiáng)制】velocity調(diào)用POJO類的屬性時(shí)贯溅,建議直接使用屬性名取值即可拄氯,模板引擎會(huì)自動(dòng)按規(guī)范調(diào)用POJO的getXxx()躲查,如果是boolean基本數(shù)據(jù)類型變量(boolean命名不需要加is前綴),會(huì)自動(dòng)調(diào)用isXxx()方法译柏。
說明:注意如果是Boolean包裝類對(duì)象镣煮,優(yōu)先調(diào)用getXxx()的方法。
【強(qiáng)制】注意 Math.random() 這個(gè)方法返回是double類型
注意取值的范圍 0≤x<1(能夠取到零值鄙麦,注意除零異常)典唇,如果想獲取整數(shù)類型的隨機(jī)數(shù),不要將x放大10的若干倍然后取整胯府,直接使用Random對(duì)象的nextInt或者nextLong方法介衔。
【強(qiáng)制】獲取當(dāng)前毫秒數(shù)System.currentTimeMillis(); 而不是new Date().getTime();
說明:如果想獲取更加精確的納秒級(jí)時(shí)間值,使用System.nanoTime()的方式盟劫。在JDK8中夜牡,針對(duì)統(tǒng)計(jì)時(shí)間等場(chǎng)景,推薦使用Instant類侣签。
【推薦】不要在視圖模板中加入任何復(fù)雜的邏輯塘装。
說明:根據(jù)MVC理論,視圖的職責(zé)是展示影所,不要搶模型和控制器的活蹦肴。
【推薦】任何數(shù)據(jù)結(jié)構(gòu)的構(gòu)造或初始化,都應(yīng)指定大小猴娩,避免數(shù)據(jù)結(jié)構(gòu)無限增長吃光內(nèi)存阴幌。
【推薦】及時(shí)清理不再使用的代碼段或配置信息。
說明:對(duì)于垃圾代碼或過時(shí)配置卷中,堅(jiān)決清理干凈矛双,避免程序過度臃腫,代碼冗余蟆豫。正例:對(duì)于暫時(shí)被注釋掉议忽,后續(xù)可能恢復(fù)使用的代碼片斷,在注釋代碼上方十减,統(tǒng)一規(guī)定使用三個(gè)斜杠(///)來說明注釋掉代碼的理由栈幸。? ?
MySQL數(shù)據(jù)庫
建表規(guī)約
【強(qiáng)制】表達(dá)是與否概念的字段,必須使用is_xxx的方式命名帮辟,數(shù)據(jù)類型是unsigned tinyint
正例: 表達(dá)邏輯刪除的字段名 is_deleted速址,1表示刪除, 0表示未刪除由驹。
【強(qiáng)制】表名芍锚、字段名必須使用小寫字母或數(shù)字,禁止出現(xiàn)數(shù)字開頭,禁止兩個(gè)下劃線中間只出現(xiàn)數(shù)字并炮。數(shù)據(jù)庫字段名的修改代價(jià)很大蒿赢,因?yàn)闊o法進(jìn)行預(yù)發(fā)布,所以字段名稱需要慎重考慮渣触。
說明: MySQLMySQLMySQLMySQL 在 WindowsWindows WindowsWindowsWindowsWindows下不區(qū)分大小寫,但在 下不區(qū)分大小寫壹若,但在 LinuxLinux Linux下默認(rèn)是區(qū)分大小寫嗅钻。因此,數(shù)據(jù)庫 下默認(rèn)是區(qū)分大小寫店展。因此养篓,數(shù)據(jù)庫 下默認(rèn)是區(qū)分大小寫。因此赂蕴,數(shù)據(jù)庫 名柳弄、表字段,都不允許出現(xiàn)任何大寫母避免節(jié)外生枝概说。
正例:aliyun_admin碧注,rdc_config,level3_name
反例:AliyunAdmin糖赔,rdcConfig萍丐,level_3_name
【強(qiáng)制】表名不使用復(fù)數(shù)名詞。
說明:表名應(yīng)該僅僅表示表里面的實(shí)體內(nèi)容放典,不應(yīng)該表示實(shí)體數(shù)量逝变,對(duì)應(yīng)于DO類名也是單數(shù)形式,符合表達(dá)習(xí)慣奋构。
【強(qiáng)制】禁用保留字壳影,如desc、range弥臼、match宴咧、delayed等,請(qǐng)參考MySQL官方保留字醋火。
【強(qiáng)制】主鍵索引名為pk_字段名悠汽;唯一索引名為uk_字段名;普通索引名則為idx_字段名芥驳。
說明:pk_即primary key柿冲;uk_即 unique key;idx_即index的簡(jiǎn)稱
【強(qiáng)制】小數(shù)類型為decimal兆旬,禁止使用float和double假抄。
說明:float和double在存儲(chǔ)的時(shí)候,存在精度損失的問題,很可能在值的比較時(shí)宿饱,得到不正確的結(jié)果熏瞄。如果存儲(chǔ)的數(shù)據(jù)范圍超過decimal的范圍,建議將數(shù)據(jù)拆成整數(shù)和小數(shù)分開存儲(chǔ)谬以。
【強(qiáng)制】如果存儲(chǔ)的字符串長度幾乎相等强饮,使用char定長字符串類型。
【強(qiáng)制】varchar是可變長字符串为黎,不預(yù)先分配存儲(chǔ)空間邮丰,長度不要超過5000,如果存儲(chǔ)長度大于此值铭乾,定義字段類型為text剪廉,獨(dú)立出來一張表,用主鍵來對(duì)應(yīng)炕檩,避免影響其它字段索引效率斗蒋。
【強(qiáng)制】表必備三字段:id, gmt_create, gmt_modified。
說明: 其中id必為 主鍵笛质,類型必為 主鍵泉沾,類型unsignedbigint、單表時(shí)自增步長為 妇押、單表時(shí)自增步長為1爆哑。gmt_create, gmt_modified的類型均為 的類型均為 datetime類型,前者現(xiàn) 類型舆吮,前者現(xiàn) 在時(shí)表示主動(dòng)創(chuàng)建揭朝,后者過去分詞被 動(dòng)
【推薦】表的命名最好是加上“業(yè)務(wù)名稱_表的作用”。
正例:alipay_task / force_project / trade_config
【推薦】庫名與應(yīng)用名稱盡量一致色冀。
【推薦】如果修改字段含義或?qū)ψ侄伪硎镜臓顟B(tài)追加時(shí)潭袱,需要及時(shí)更新字段注釋。
【推薦】字段允許適當(dāng)冗余锋恬,以提高查詢性能屯换,但必須考慮數(shù)據(jù)一致。冗余字段應(yīng)遵循:
不是頻繁修改的字段与学。
不是varchar超長字段彤悔,更不能是text字段。
【推薦】單表行數(shù)超過500萬行或者單表容量超過2GB索守,才推薦進(jìn)行分庫分表晕窑。
說明:如果預(yù)計(jì)三年后的數(shù)據(jù)量根本達(dá)不到這個(gè)級(jí)別,請(qǐng)不要在創(chuàng)建表時(shí)就分庫分表卵佛。https://blog.csdn.net/xlgen157387/article/details/53976153
【參考】合適的字符存儲(chǔ)長度杨赤,不但節(jié)約數(shù)據(jù)庫表空間敞斋、節(jié)約索引存儲(chǔ),更重要的是提升檢索速度疾牲。
索引規(guī)約
【強(qiáng)制】業(yè)務(wù)上具有唯一特性的字段植捎,即使是多個(gè)字段的組合,也必須建成唯一索引阳柔。
說明:不要以為唯一索引影響了insert速度焰枢,這個(gè)速度損耗可以忽略,但提高查找速度是明顯的舌剂;另外医咨,即使在應(yīng)用層做了非常完善的校驗(yàn)控制,只要沒有唯一索引架诞,根據(jù)墨菲定律,必然有臟數(shù)據(jù)產(chǎn)生干茉。
【強(qiáng)制】超過三個(gè)表禁止join谴忧。需要join的字段,數(shù)據(jù)類型必須絕對(duì)一致角虫;多表關(guān)聯(lián)查詢時(shí)沾谓,保證被關(guān)聯(lián)的字段需要有索引。
【強(qiáng)制】在varchar字段上建立索引時(shí)戳鹅,必須指定索引長度均驶,沒必要對(duì)全字段建立索引,根據(jù)實(shí)際文本區(qū)分度決定索引長度即可枫虏。
【強(qiáng)制】頁面搜索嚴(yán)禁左模糊或者全模糊妇穴,如果需要請(qǐng)走搜索引擎來解決。
【推薦】如果有order by的場(chǎng)景隶债,請(qǐng)注意利用索引的有序性腾它。order by 最后的字段是組合索引的一部分,并且放在索引組合順序的最后死讹,避免出現(xiàn)file_sort的情況瞒滴,影響查詢性能.
【推薦】利用覆蓋索引來進(jìn)行查詢操作,避免回表
說明:如果一本書需要知道第11章是什么標(biāo)題赞警,會(huì)翻開第11章對(duì)應(yīng)的那一頁嗎妓忍?目錄瀏覽一下就好,這個(gè)目錄就是起到覆蓋索引的作用愧旦。正例:能夠建立索引的種類分為主鍵索引世剖、唯一索引、普通索引三種笤虫,而覆蓋索引只是一種查詢的一種效果搁廓,用explain的結(jié)果引颈,extra列會(huì)出現(xiàn):usingindex。
【推薦】利用延遲關(guān)聯(lián)或者子查詢優(yōu)化超多分頁場(chǎng)景境蜕。
說明:MySQL并不是跳過offset行蝙场,而是取offset+N行,然后返回放棄前offset行粱年,返回N行售滤,那當(dāng)offset特別大的時(shí)候,效率就非常的低下台诗,要么控制返回的總頁數(shù)完箩,要么對(duì)超過特定閾值的頁數(shù)進(jìn)行SQL改寫。正例:先快速定位需要獲取的id段拉队,然后再關(guān)聯(lián):SELECTa.*FROM表1a, (selectidfrom表1where條件LIMIT100000,20) bwherea.id=b.id
【推薦】 SQL性能優(yōu)化的目標(biāo):至少要達(dá)到 range 級(jí)別弊知,要求是ref級(jí)別,如果可以是consts最好粱快。
說明: 1)consts 單表中最多只有一個(gè)匹配行(主鍵或者唯一索引)秩彤,在優(yōu)化階段即可讀取到數(shù)據(jù)。 2)ref 指的是使用普通的索引(normal index)事哭。3)range 對(duì)索引進(jìn)行范圍檢索漫雷。 反例:explain表的結(jié)果,type=index鳍咱,索引物理文件全掃描降盹,速度非常慢,這個(gè)index級(jí)別比較range還低谤辜,與全表掃描是小巫見大巫蓄坏。
【推薦】建組合索引的時(shí)候,區(qū)分度最高的在最左邊
正例:如果wherea=? and b=? 丑念,a列的幾乎接近于唯一值剑辫,那么只需要單建idx_a索引即可。 說明:存在非等號(hào)和等號(hào)混合判斷條件時(shí)渠欺,在建索引時(shí)妹蔽,請(qǐng)把等號(hào)條件的列前置。如:wherea>? and b=? 那么即使a的區(qū)分度更高挠将,也必須把b放在索引的最前列胳岂。
【推薦】防止因字段類型不同造成的隱式轉(zhuǎn)換,導(dǎo)致索引失效舔稀。
【參考】創(chuàng)建索引時(shí)避免有如下極端誤解:
寧濫勿缺乳丰。認(rèn)為一個(gè)查詢就需要建一個(gè)索引。
寧缺勿濫内贮。認(rèn)為索引會(huì)消耗空間产园、嚴(yán)重拖慢更新和新增速度汞斧。
抵制惟一索引。認(rèn)為業(yè)務(wù)的惟一性一律需要在應(yīng)用層通過“先查后插”方式解決什燕。
SQL語句
【強(qiáng)制】不要使用count(列名)或count(常量)來替代count()粘勒,count()是SQL92定義的標(biāo)準(zhǔn)統(tǒng)計(jì)行數(shù)的語法,跟數(shù)據(jù)庫無關(guān)屎即,跟NULL和非NULL無關(guān)庙睡。
說明:count(*)會(huì)統(tǒng)計(jì)值為NULL的行,而count(列名)不會(huì)統(tǒng)計(jì)此列為NULL值的行技俐。
【強(qiáng)制】count(distinct col) 計(jì)算該列除NULL之外的不重復(fù)行數(shù)乘陪,注意 count(distinct col1, col2) 如果其中一列全為NULL,那么即使另一列有不同的值雕擂,也返回為0啡邑。
【強(qiáng)制】當(dāng)某一列的值全是NULL時(shí),count(col)的返回結(jié)果為0井赌,但sum(col)的返回結(jié)果為NULL谤逼,因此使用sum()時(shí)需注意NPE問題。
正例:可以使用如下方式來避免sum的NPE問題:SELECTIF(ISNULL(SUM(g)),0,SUM(g))FROMtable;
【強(qiáng)制】使用ISNULL()來判斷是否為NULL值族展。
說明:NULL與任何值的直接比較都為NULL。NULL<>NULL的返回結(jié)果是NULL拔鹰,而不是false仪缸。NULL=NULL的返回結(jié)果是NULL,而不是true列肢。NULL<>1的返回結(jié)果是NULL恰画,而不是true。
【強(qiáng)制】 在代碼中寫分頁查詢邏輯時(shí)瓷马,若count為0應(yīng)直接返回拴还,避免執(zhí)行后面的分頁語句。
【強(qiáng)制】不得使用外鍵與級(jí)聯(lián)欧聘,一切外鍵概念必須在應(yīng)用層解決片林。
說明:以學(xué)生和成績(jī)的關(guān)系為例,學(xué)生表中的student_id是主鍵怀骤,那么成績(jī)表中的student_id則為外鍵费封。如果更新學(xué)生表中的student_id,同時(shí)觸發(fā)成績(jī)表中的student_id更新蒋伦,即為級(jí)聯(lián)更新弓摘。外鍵與級(jí)聯(lián)更新適用于單機(jī)低并發(fā),不適合分布式痕届、高并發(fā)集群韧献;級(jí)聯(lián)更新是強(qiáng)阻塞末患,存在數(shù)據(jù)庫更新風(fēng)暴的風(fēng)險(xiǎn);外鍵影響數(shù)據(jù)庫的插入速度锤窑。
【強(qiáng)制】禁止使用存儲(chǔ)過程璧针,存儲(chǔ)過程難以調(diào)試和擴(kuò)展,更沒有移植性果复。
【強(qiáng)制】數(shù)據(jù)訂正(特別是刪除陈莽、修改記錄操作)時(shí),要先select虽抄,避免出現(xiàn)誤刪除走搁,確認(rèn)無誤才能執(zhí)行更新語句。
【推薦】in操作能避免則避免迈窟,若實(shí)在避免不了私植,需要仔細(xì)評(píng)估in后邊的集合元素?cái)?shù)量,控制在1000個(gè)之內(nèi)车酣。
【參考】如果有全球化需要曲稼,所有的字符存儲(chǔ)與表示,均以u(píng)tf-8編碼湖员,注意字符統(tǒng)計(jì)函數(shù)的區(qū)別贫悄。
【參考】 TRUNCATE TABLE 比 DELETE 速度快,且使用的系統(tǒng)和事務(wù)日志資源少娘摔,但TRUNCATE無事務(wù)且不觸發(fā)trigger窄坦,有可能造成事故,故不建議在開發(fā)代碼中使用此語句凳寺。
說明:TRUNCATETABLE在功能上與不帶WHERE子句的DELETE語句相同鸭津。
ORM映射
【強(qiáng)制】在表查詢中,一律不要使用 * 作為查詢的字段列表肠缨,需要哪些字段必須明確寫明逆趋。 說明:1)增加查詢分析器解析成本。2)增減字段容易與resultMap配置不一致晒奕。
【強(qiáng)制】POJO類的布爾屬性不能加is闻书,而數(shù)據(jù)庫字段必須加is_,要求在resultMap中進(jìn)行字段與屬性之間的映射脑慧。
【強(qiáng)制】不要用resultClass當(dāng)返回參數(shù)惠窄,即使所有類屬性名與數(shù)據(jù)庫字段一一對(duì)應(yīng),也需要定義漾橙;反過來杆融,每一個(gè)表也必然有一個(gè)與之對(duì)應(yīng)。 說明:配置映射關(guān)系霜运,使字段與DO類解耦脾歇,方便維護(hù)蒋腮。
【強(qiáng)制】sql.xml配置參數(shù)使用:#{},#param# 不要使用${} 此種方式容易出現(xiàn)SQL注入藕各。
【強(qiáng)制】iBATIS自帶的queryForList(String statementName,int start,int size)不推薦使用池摧。
【強(qiáng)制】不允許直接拿HashMap與Hashtable作為查詢結(jié)果集的輸出。
說明:resultClass=”Hashtable”激况,會(huì)置入字段名和屬性值作彤,但是值的類型不可控。
【強(qiáng)制】更新數(shù)據(jù)表記錄時(shí)乌逐,必須同時(shí)更新記錄對(duì)應(yīng)的gmt_modified字段值為當(dāng)前時(shí)間竭讳。
【推薦】不要寫一個(gè)大而全的數(shù)據(jù)更新接口。傳入為POJO類浙踢,不管是不是自己的目標(biāo)更新字段绢慢,都進(jìn)行update table set c1=value1,c2=value2,c3=value3; 這是不對(duì)的。執(zhí)行SQL時(shí)洛波,不要更新無改動(dòng)的字段胰舆,一是易出錯(cuò);二是效率低蹬挤;三是增加binlog存儲(chǔ)缚窿。
【參考】@Transactional事務(wù)不要濫用。事務(wù)會(huì)影響數(shù)據(jù)庫的QPS焰扳,另外使用事務(wù)的地方需要考慮各方面的回滾方案倦零,包括緩存回滾、搜索引擎回滾蓝翰、消息補(bǔ)償光绕、統(tǒng)計(jì)修正等女嘲。
【參考】中的compareValue是與屬性值對(duì)比的常量,一般是數(shù)字,表示相等時(shí)帶上此條件古徒;表示不為空且不為null時(shí)執(zhí)行性穿;表示不為null值時(shí)執(zhí)行。
版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn)愕鼓,版權(quán)歸作者所有钙态,本社區(qū)不擁有所有權(quán),也不承擔(dān)相關(guān)法律責(zé)任菇晃。如果您發(fā)現(xiàn)本社區(qū)中有涉嫌抄襲的內(nèi)容册倒,歡迎發(fā)送郵件至:yqgroup@service.aliyun.com?進(jìn)行舉報(bào),并提供相關(guān)證據(jù)磺送,一經(jīng)查實(shí)驻子,本社區(qū)將立刻刪除涉嫌侵權(quán)內(nèi)容灿意。