又一次閱讀阿里編程規(guī)范,發(fā)現(xiàn)有不少條目又給忘了蒜撮,離上次閱讀大概一個(gè)多月。我的閱讀習(xí)慣應(yīng)該還不錯(cuò)跪呈,每次看書(shū)籍之類(lèi)的不會(huì)只看一遍段磨,因?yàn)橹暗慕?jīng)驗(yàn)發(fā)現(xiàn),只看一遍的內(nèi)容耗绿,會(huì)特別快的遺忘苹支,在腦子里只會(huì)留下淡淡的印象,知道看過(guò)哪塊的內(nèi)容误阻,但詳細(xì)的內(nèi)容就模糊了债蜜,面試時(shí)經(jīng)歷過(guò)這樣尷尬的場(chǎng)面...
現(xiàn)在我看書(shū),通常是第一遍通讀究反,了解大概寻定;第二遍細(xì)度核心知識(shí)點(diǎn),強(qiáng)化理解核心內(nèi)容精耐;然后在腦中回思書(shū)中的核心內(nèi)容狼速,有不明白的地方就再翻書(shū)看一遍,做到理解卦停,轉(zhuǎn)化為自己的知識(shí)向胡,效果來(lái)看還不錯(cuò)恼蓬,你也可以試下!
但發(fā)現(xiàn)在阿里編程規(guī)范這里還是會(huì)有問(wèn)題僵芹,條目太多处硬,按照順序記憶可以做到一段時(shí)間內(nèi)不忘記,但很多條目是日常編程不會(huì)用到的淮捆,時(shí)間稍長(zhǎng)就會(huì)出現(xiàn)遺忘的情形郁油,在編程的過(guò)程中萬(wàn)一不小心踩了雷就有點(diǎn)傷本股,所以嘗試從自己思考問(wèn)題的角度重新組織日常編碼需要的注意事項(xiàng)攀痊,爭(zhēng)取轉(zhuǎn)化為編程時(shí)的本能_
一、環(huán)境準(zhǔn)備
檢查下自己的IDE設(shè)置拄显,確保設(shè)置為以下內(nèi)容苟径,以mac eclipse為例。
- IDE的text file encoding設(shè)置為 UTF-8躬审;IDE中文件的換行符使用Unix格式棘街,不要使用 Windows 格式(Eclipse -> 偏好設(shè)置 -> General -> WorkSpace -> 設(shè)置Text file encoding 和New text file line delimiter)。
- 采用4個(gè)空格縮進(jìn)承边,禁止使用tab字符遭殉,如果使用tab縮進(jìn),必須設(shè)置1個(gè)tab為4個(gè)空格(Eclipse -> 偏好設(shè)置 -> General -> Editors -> Text Editors -> 設(shè)置Displayed tab width為4 -> 勾選Insert spaces for tabs)博助。
- Code Templates設(shè)置:為了統(tǒng)一編碼規(guī)范险污,通常團(tuán)隊(duì)會(huì)有一個(gè)通用的Code Templates,問(wèn)下同事富岳,讓他們導(dǎo)一份codetemplates.xml給你蛔糯,如果你需要自己構(gòu)建一個(gè),百度一下吧窖式,這里不再展開(kāi)了蚁飒。
- 安裝阿里云代碼規(guī)范插件,歷史代碼或新項(xiàng)目里面萝喘,通過(guò)插件掃碼淮逻,可以發(fā)現(xiàn)很多不規(guī)范的點(diǎn),個(gè)人認(rèn)為是java開(kāi)發(fā)必裝插件之一(eclipse插件中文安裝手冊(cè))阁簸;
二爬早、命名
通用約束
- 代碼中的命名均不能以下劃線或美元符號(hào)開(kāi)始,也不能以下劃線或美元符號(hào)結(jié)束强窖。
- 代碼中的命名嚴(yán)禁使用拼音與英文混合的方式凸椿,更不允許直接使用中文的方式。
- 杜絕完全不規(guī)范的縮寫(xiě)翅溺,避免望文不知義脑漫。反例:AbstractClass“縮寫(xiě)”命名成 AbsClass髓抑。
- 為了達(dá)到代碼自解釋的目標(biāo),任何自定義編程元素在命名時(shí)优幸,使用盡量完整的單詞組合來(lái)表達(dá)其意吨拍,如從遠(yuǎn)程倉(cāng)庫(kù)拉取代碼的類(lèi)命名為 PullCodeFromRemoteRepository。
- 如果模塊网杆、接口羹饰、類(lèi)、方法使用了設(shè)計(jì)模式碳却,在命名時(shí)體現(xiàn)出具體模式队秩。
在日常開(kāi)發(fā)中常見(jiàn)的涉及命名的點(diǎn)有:項(xiàng)目名稱(chēng)、包名昼浦、類(lèi)名馍资、方法名、變量名关噪、數(shù)據(jù)庫(kù)名鸟蟹、表名、字段名使兔、索引名稱(chēng)建钥、URL命名、文件名虐沥。
1. 項(xiàng)目名稱(chēng)
小寫(xiě)字母或數(shù)字熊经,不能使用數(shù)字開(kāi)頭,多個(gè)單詞之間使用中劃線連接置蜀,能準(zhǔn)確的表達(dá)出項(xiàng)目的核心作用奈搜,如code-generator。(個(gè)人推薦)
2. 包名
- 包名統(tǒng)一使用小寫(xiě)盯荤,點(diǎn)分隔符之間有且僅有一個(gè)自然語(yǔ)義的英語(yǔ)單詞馋吗。包名統(tǒng)一使用單數(shù)形式,但是類(lèi)名如果有復(fù)數(shù)含義秋秤,類(lèi)名可以使用復(fù)數(shù)形式宏粤。
- 如果表示版本關(guān)系等特殊情況,可以使用數(shù)字灼卢,如org.apache.commons.lang3.StringUtils
3. 類(lèi)名
- 類(lèi)名使用 UpperCamelCase 風(fēng)格绍哎,必須遵從駝峰形式,但以下情形例外:DO / BO / DTO / VO / AO鞋真。
- 抽象類(lèi)命名使用 Abstract 或 Base 開(kāi)頭;異常類(lèi)命名使用 Exception 結(jié)尾;測(cè)試類(lèi)命名以它要測(cè)試的類(lèi)的名稱(chēng)開(kāi)始崇堰,以 Test 結(jié)尾。
- 對(duì)于 Service 和 DAO 類(lèi),基于 SOA 的理念海诲,暴露出來(lái)的服務(wù)一定是接口繁莹,內(nèi)部的實(shí)現(xiàn)類(lèi)用 Impl 的后綴與接口區(qū)別。
- 枚舉類(lèi)名建議帶上 Enum 后綴特幔,枚舉成員名稱(chēng)需要全大寫(xiě)咨演,單詞間用下劃線隔開(kāi),如:枚舉名字為ProcessStatusEnum的成員名稱(chēng):SUCCESS / UNKOWN_REASON蚯斯。
- 禁止使用非字母字符薄风,特殊情況下可以使用2、4等數(shù)字拍嵌。
4. 屬性名
- 使用 lowerCamelCase 風(fēng)格遭赂,必須遵從駝峰形式。
- POJO類(lèi)中布爾類(lèi)型的變量撰茎,都不要加 is嵌牺,否則部分框架解析會(huì)引起序列化錯(cuò)誤打洼,如標(biāo)記刪除字段用deleted而不是isDeleted龄糊。
- 盡量不要使用非字母字符
5. 方法名
- 使用 lowerCamelCase 風(fēng)格,必須遵從駝峰形式募疮;
- Service/DAO層方法命名規(guī)約
- 獲取單個(gè)對(duì)象的方法用get做前綴炫惩。
- 獲取多個(gè)對(duì)象的方法用list做前綴。
- 獲取統(tǒng)計(jì)值的方法用count做前綴阿浓。
- 插入的方法用save/insert做前綴他嚷。
- 刪除的方法用remove/delete做前綴。
- 修改的方法用update做前綴芭毙。
- 盡量不要使用非字母字符筋蓖,如數(shù)字,下劃線退敦,中劃線等粘咖。
6. 參數(shù)名、變量名
使用 lowerCamelCase 風(fēng)格侈百,必須遵從駝峰形式瓮下。
7. 常量
- 常量命名全部大寫(xiě),單詞間用下劃線隔開(kāi)钝域,力求語(yǔ)義表達(dá)完整清楚讽坏,不要嫌名字長(zhǎng)。
- 不允許任何魔法值(即未經(jīng)定義的常量)直接出現(xiàn)在代碼中例证。反例:String key = "Id#taobao_" + tradeId;
8. 數(shù)據(jù)庫(kù)名
盡量和項(xiàng)目名稱(chēng)保持一致路呜,如出現(xiàn)特殊情況按照項(xiàng)目名稱(chēng)命名規(guī)則進(jìn)行命名。
9. 表名
- 必須使用小寫(xiě)字母或數(shù)字,禁止出現(xiàn)數(shù)字開(kāi)頭胀葱,禁止兩個(gè)下劃線中間只 出現(xiàn)數(shù)字党涕,不允許出現(xiàn)任何大寫(xiě)字母,建議將類(lèi)名內(nèi)不同單詞用下劃線分割作為表名巡社。
- 表名不使用復(fù)數(shù)名詞膛堤,表名應(yīng)該僅僅表示表里面的實(shí)體內(nèi)容,不應(yīng)該表示實(shí)體數(shù)量晌该,對(duì)應(yīng)于 DO 類(lèi)名也是單數(shù) 形式肥荔,符合表達(dá)習(xí)慣。
- 表的命名可以考慮加上“業(yè)務(wù)名稱(chēng)_表的作用”朝群,但需要規(guī)范統(tǒng)一命名燕耿,不要多種方式混合使用,如果表數(shù)據(jù)不是特別大姜胖,沒(méi)有必要使用誉帅。
- 禁用保留字,如 desc右莱、range蚜锨、match、delayed 等慢蜓,請(qǐng)參考 MySQL 官方保留字亚再。
10. 字段名
- 必須使用小寫(xiě)字母或數(shù)字,禁止出現(xiàn)數(shù)字開(kāi)頭晨抡,禁止兩個(gè)下劃線中間只 出現(xiàn)數(shù)字氛悬,不允許出現(xiàn)任何大寫(xiě)字母,建議將屬性名內(nèi)不同單詞用下劃線分割作為字段名耘柱。
- 禁用保留字如捅,如 desc、range调煎、match镜遣、delayed 等,請(qǐng)參考 MySQL 官方保留字汛蝙。
- 表達(dá)是與否概念的字段烈涮,必須使用 is_xxx 的方式命名,數(shù)據(jù)類(lèi)型是 unsigned tinyint ( 1表示是窖剑,0表示否)坚洽。如標(biāo)記刪除字段deleted對(duì)應(yīng)的字段名為is_deleted。
11. 索引名
- 主鍵索引名為 pk_字段名;
- 唯一索引名為 uk_字段名;
- 普通索引名則為 idx_字段名西土。
12. 文件名
必須使用小寫(xiě)字母或數(shù)字讶舰,禁止數(shù)字開(kāi)頭,多個(gè)單詞使用中劃線連接,涉及的內(nèi)容有:js文件跳昼、圖片般甲、css文件、jsp頁(yè)面等(個(gè)人推薦)鹅颊。
13. URL命名
- 必須使用小寫(xiě)字母或數(shù)字敷存,禁止數(shù)字開(kāi)頭,多個(gè)單詞使用中劃線連接堪伍。
- 限制URL層級(jí)不要太深(個(gè)人感覺(jué)3層以內(nèi)較好)锚烦。
三、代碼風(fēng)格
代碼風(fēng)格實(shí)際上就是合理使用縮進(jìn)帝雇、空格涮俄、換行,目的是讓代碼可讀性更強(qiáng)尸闸。大家記憶時(shí)記清楚用什么樣的縮進(jìn)彻亲,哪些時(shí)候使用空格,哪些時(shí)候使用換行吮廉,單行代碼不要太長(zhǎng)就可以苞尝,這部分內(nèi)容通過(guò)兩三次的回顧很容易養(yǎng)成習(xí)慣,因?yàn)槭蔷幋a中最長(zhǎng)用到的茧痕。
可參考以下代碼:
public static void main(String[] args) {
// 縮進(jìn) 4 個(gè)空格
String say = "hello";
// 運(yùn)算符的左右必須有一個(gè)空格
int flag = 0;
// 關(guān)鍵詞if/for/while/switch/do與括號(hào)之間必須有一個(gè)空格野来,括號(hào)內(nèi)的 flag 與左括號(hào),0 與右括號(hào)不需要空格
if (flag == 0) {
System.out.println(say);
}
// 左大括號(hào)前加空格且不換行;左大括號(hào)后換行
if (flag == 1) {
System.out.println("world");
// 右大括號(hào)前換行踪旷,右大括號(hào)后有 else,不用換行
} else {
System.out.println("ok");
// 在右大括號(hào)后直接結(jié)束豁辉,則必須換行
}
StringBuffer sb = new StringBuffer();
// 超過(guò)120個(gè)字符的情況下令野,換行縮進(jìn)4個(gè)空格,點(diǎn)號(hào)和方法名稱(chēng)一起換行
sb.append("zi").append("xin")...
.append("huang")...
.append("huang")...
.append("huang");
// 任何二目徽级、三目運(yùn)算符的左右兩邊都需要加一個(gè)空格
int result = flag == 0 ? 1 : 0;
}
下邊是另外幾點(diǎn)需要注意的:
- 注釋的雙斜線與注釋內(nèi)容之間有且僅有一個(gè)空格气破。
- 方法參數(shù)在定義和傳入時(shí),多個(gè)參數(shù)逗號(hào)后邊必須加空格餐抢,如method("a", "b")现使。
- 沒(méi)有必要增加若干空格來(lái)使某一行的字符與上一行對(duì)應(yīng)位置的字符對(duì)齊。
- 方法體內(nèi)的執(zhí)行語(yǔ)句組旷痕、變量的定義語(yǔ)句組碳锈、不同的業(yè)務(wù)邏輯之間或者不同的語(yǔ)義 之間插入一個(gè)空行。相同業(yè)務(wù)邏輯和語(yǔ)義之間不需要插入空行欺抗。沒(méi)有必要插入多個(gè)空行進(jìn)行隔開(kāi)售碳。
四、注釋
1. 項(xiàng)目
項(xiàng)目建議提供注釋?zhuān)f(shuō)明項(xiàng)目的作用,核心邏輯或需要注意的特別事項(xiàng)贸人,方便其他人快速對(duì)項(xiàng)目形成整體了解间景。添加方式有兩種:
- 在根目錄下創(chuàng)建README.md或README.txt
- 在根目錄下創(chuàng)建doc文件夾,在其創(chuàng)建README.md或README.txt艺智,還可以在該目錄下存儲(chǔ)一些初始化語(yǔ)句倘要、索引創(chuàng)建語(yǔ)句等內(nèi)容
2. 包
說(shuō)明該包的核心作用,注釋可在package-info.java內(nèi)設(shè)置十拣,建議在核心包上有選擇添加碗誉。
3. 類(lèi)
所有類(lèi)都需要添加注釋?zhuān)?lèi)注釋采用javadoc規(guī)范的方式( /** */ ),注釋包括:該類(lèi)的主要作用及使用時(shí)的一些注意事項(xiàng)、創(chuàng)建者和創(chuàng)建日期父晶,可通過(guò)codetemplate來(lái)統(tǒng)一格式哮缺。
4. 類(lèi)方法
類(lèi)方法注釋采用javadoc規(guī)范的方式( /** */ ),注釋包括:該方法的作用甲喝、使用注意事項(xiàng)尝苇、參數(shù)、返回值埠胖、拋出異常信息糠溜,可通過(guò)codetemplate來(lái)統(tǒng)一格式,添加注釋時(shí)可以模仿jdk內(nèi)方法的注釋直撤。
如果注釋的工作量太大非竿,對(duì)于私有方法,可以簡(jiǎn)化注釋?zhuān)龅侥芮逦f(shuō)明其作用即可谋竖。但是所有的抽象方法(包括接口中的方法)的注釋必須嚴(yán)格的按照javadoc規(guī)范進(jìn)行添加红柱,需要額外指出對(duì)子類(lèi)的實(shí)現(xiàn)要求,或者調(diào)用注意事項(xiàng)蓖乘。
當(dāng)然也會(huì)有例外情況锤悄,如controller內(nèi)使用swagger2提供在線文檔,那就沒(méi)必要再提供javadoc注釋了嘉抒。
5. 類(lèi)屬性
所有的類(lèi)屬性都需要添加注釋?zhuān)锌捎猛ㄟ^(guò)類(lèi)名.屬性零聚、對(duì)象實(shí)例.屬性調(diào)用的類(lèi)屬性都應(yīng)該使用javadoc進(jìn)行注釋?zhuān)绯A俊⒚杜e類(lèi)型字段些侍;POJO類(lèi)的屬性個(gè)人感覺(jué)使用行內(nèi)注釋會(huì)更合適一些隶症,普通實(shí)例變量建議使用javadoc方式。
6. 方法內(nèi)
方法內(nèi)部單行注釋?zhuān)诒蛔⑨屨Z(yǔ)句上方另起一行,使用//注釋。方法內(nèi)部多行注釋使用/* */注釋?zhuān)⒁馀c代碼對(duì)齊街氢。
可以這樣記憶// 和 /* */只在方法內(nèi)部和POJO內(nèi)使用,其他時(shí)候都使用javadoc方式的注釋颂龙。
7. 其他建議
- 注釋使用中文习蓬,專(zhuān)有名詞與關(guān)鍵字保持英文原文即可。
- 代碼修改的同時(shí)措嵌,注釋也要進(jìn)行相應(yīng)的修改躲叼。
- 如果一段代碼需要注釋掉,在上方詳細(xì)說(shuō)明企巢;如果代碼已無(wú)用枫慷,直接刪除更好。
- TODO(待辦事宜)浪规,F(xiàn)IXME(錯(cuò)誤或听,不能工作)這類(lèi)特殊注釋標(biāo)記,添加時(shí)留下添加人笋婿、時(shí)間誉裆、預(yù)計(jì)處理時(shí)間,并及時(shí)處理缸濒,不要寫(xiě)了就不管了足丢。
對(duì)于注釋的要求:第一、能夠準(zhǔn)確反應(yīng)設(shè)計(jì)思想和代碼邏輯;第二庇配、能夠描述業(yè)務(wù)含義斩跌,使別的程序員能夠迅速了解到代碼背后的信息。完全沒(méi)有注釋的大段代碼對(duì)于閱讀者形同天書(shū)捞慌,注釋是給自己看的耀鸦,即使隔很長(zhǎng)時(shí)間,也能清晰理解當(dāng)時(shí)的思路;注釋也是給繼任者看的啸澡,使其能夠快速接替自己的工作袖订。
額外的,好的命名锻霎、代碼結(jié)構(gòu)是自解釋的著角,注釋力求精簡(jiǎn)準(zhǔn)確、表達(dá)到位旋恼。避免出現(xiàn)注釋的一個(gè)極端:過(guò)多過(guò)濫的注釋?zhuān)a的邏輯一旦修改,修改注釋是相當(dāng)大的負(fù)擔(dān)奄容。
五冰更、日志
1.日志配置
主要有日志文件名稱(chēng)、日志輸出級(jí)別昂勒、日志是否向上層傳遞蜀细、日志保留時(shí)間。
- 日志文件推薦至少保存15天戈盈,因?yàn)橛行┊惓>邆湟浴爸堋睘轭l次發(fā)生的特點(diǎn)奠衔。
- 避免重復(fù)打印日志谆刨,浪費(fèi)磁盤(pán)空間,務(wù)必在 log4j.xml 中設(shè)置 additivity=false
- 謹(jǐn)慎地記錄日志归斤。生產(chǎn)環(huán)境禁止輸出 debug 日志;有選擇地輸出 info 日志;如果使 用 warn 來(lái)記錄剛上線時(shí)的業(yè)務(wù)行為信息痊夭,一定要注意日志輸出量的問(wèn)題,避免把服務(wù)器磁盤(pán) 撐爆脏里,并記得及時(shí)刪除這些觀察日志她我。
- 應(yīng)用中的擴(kuò)展日志(如打點(diǎn)、臨時(shí)監(jiān)控迫横、訪問(wèn)日志等)命名方式:appName_logType_logName.log番舆。logType:日志類(lèi)型,推薦分類(lèi)有stats/desc/monitor/visit 等;logName:日志描述矾踱。這種命名的好處:通過(guò)文件名就可知 道日志文件屬于什么應(yīng)用恨狈,什么類(lèi)型,什么目的呛讲,也有利于歸類(lèi)查找禾怠。
2.日志使用
- 應(yīng)用中不可直接使用日志系統(tǒng)(Log4j、Logback)中的 API圣蝎,而應(yīng)依賴使用日志框架SLF4J 中的 API刃宵,使用門(mén)面模式的日志框架,有利于維護(hù)和各個(gè)類(lèi)的日志處理方式統(tǒng)一徘公。
- 對(duì) trace/debug/info 級(jí)別的日志輸出牲证,必須使用條件輸出形式或者使用占位符的方式。
- 異常信息應(yīng)該包括兩類(lèi)信息:案發(fā)現(xiàn)場(chǎng)信息和異常堆棧信息关面。如果不處理坦袍,那么通過(guò) 關(guān)鍵字 throws 往上拋出。推薦
logger.error(各類(lèi)參數(shù)或者對(duì)象toString + "_" + e.getMessage(), e);
這種格式等太,不要簡(jiǎn)單的輸出e.getMessage()捂齐,那樣具體的錯(cuò)誤信息都被隱藏,很不利于排查問(wèn)題缩抡。 - 注意日志輸出級(jí)別和使用場(chǎng)景奠宜,避免大量調(diào)試日志被生成,最近就遇到過(guò)一次在高頻接口輸出調(diào)試信息瞻想,忘記清理压真,在調(diào)用高峰拖死了tomcat;在生成環(huán)境蘑险,盡量只記錄異常信息和較重要的業(yè)務(wù)信息滴肿,且控制其量。
- while佃迄、for循環(huán)等內(nèi)部的異常需要特別注意發(fā)生異常的條件泼差,曾經(jīng)遇到過(guò)while循環(huán)從redis隊(duì)列內(nèi)取值(事件)贵少,redis服務(wù)宕機(jī),結(jié)果異常日志刷爆磁盤(pán)的情況堆缘。
六滔灶、異常處理
主要涉及什么情況下添加異常處理,捕獲異常后的處理方式套啤,finally內(nèi)注意事項(xiàng)及其它幾點(diǎn)建議宽气。
1. 異常捕獲
- 不要捕獲IndexOutOfBoundsException、NullPointerException等運(yùn)行時(shí)異常潜沦,這類(lèi)異程蜒模可以通過(guò)條件判斷避免;也不要使用異常來(lái)做流程控制唆鸡,異常的處理效率比條件分支低涝影;
- 不要對(duì)大段代碼進(jìn)行try-catch,只在可能發(fā)生異常且需要對(duì)異常處理的場(chǎng)景有針對(duì)性的進(jìn)行try-catch捕獲異常争占;
2. 異常處理
- 捕獲異常后嚴(yán)禁什么也不做或者直接e.printStackTrace()輸出信息至控制臺(tái)燃逻;如果不想處理,將該異常拋給上層臂痕,最外層的業(yè)務(wù)使用者伯襟,必須處理異常,將其轉(zhuǎn)化為用戶可以理解的內(nèi)容握童;
- 在代碼中使用“拋異衬饭郑”還是“返回錯(cuò)誤碼”,對(duì)于公司外的 http/api 開(kāi)放接口必須 使用“錯(cuò)誤碼”;而應(yīng)用內(nèi)部推薦異常拋出;跨應(yīng)用間 RPC 調(diào)用優(yōu)先考慮使用 Result 方式澡绩,封 裝 isSuccess()方法稽揭、“錯(cuò)誤碼”、“錯(cuò)誤簡(jiǎn)短信息”肥卡。
- 定義時(shí)區(qū)分unchecked/checked 異常溪掀,避免直接拋出newRuntimeException(), 更不允許拋出 Exception 或者 Throwable步鉴,應(yīng)使用有業(yè)務(wù)含義的自定義異常揪胃。
3. finally使用
- 在finally塊中進(jìn)行資源回收(關(guān)閉資源對(duì)象、流對(duì)象)時(shí)氛琢,有異常也要做try-catch
- finally塊中不能使用return只嚣,finally塊中的Return返回后方法結(jié)束執(zhí)行,不會(huì)執(zhí)行try-catch塊中的return語(yǔ)句艺沼;
4. 其它建議
- 有 try 塊放到了事務(wù)代碼中,catch 異常后蕴掏,如果需要回滾事務(wù)障般,一定要注意手動(dòng)回 滾事務(wù)调鲸。
- 防止 NPE,是程序員的基本修養(yǎng)挽荡,注意 NPE 產(chǎn)生的場(chǎng)景藐石;
七、單元測(cè)試
1. 單元測(cè)試要求
- 單元測(cè)試代碼必須寫(xiě)在如下工程目錄:src/test/java定拟,不允許寫(xiě)在業(yè)務(wù)代碼目錄下
- 單元測(cè)試應(yīng)該是有測(cè)試框架定時(shí)自動(dòng)執(zhí)行的于微,不需要人工參與;單元測(cè)試用例之間不能互相調(diào)用青自,也不能依賴執(zhí)行的先后次序株依;單元測(cè)試時(shí)可以重復(fù)執(zhí)行的,不能受到外界環(huán)境的影響延窜。
- 單元測(cè)試通常是方法級(jí)別恋腕,至多類(lèi)級(jí)別。
- 單元測(cè)試作為一種質(zhì)量保障手段逆瑞,不建議項(xiàng)目發(fā)布后補(bǔ)充單元測(cè)試用例荠藤,建議在項(xiàng)目提測(cè)前完成單元測(cè)試。核心業(yè)務(wù)获高、核心應(yīng)用哈肖、核心模塊的增量代碼確保單元測(cè)試通過(guò).
- 在設(shè)計(jì)評(píng)審階段,開(kāi)發(fā)人員需要和測(cè)試人員一起確定單元測(cè)試范圍念秧,單元測(cè)試最好覆蓋所有測(cè)試用例(UC)淤井。
- 單元測(cè)試的基本目標(biāo):語(yǔ)句覆蓋率達(dá)到 70%;核心模塊的語(yǔ)句覆蓋率和分支覆蓋率都 要達(dá)到 100%
2. 單元測(cè)試實(shí)現(xiàn)建議
- 對(duì)于數(shù)據(jù)庫(kù)相關(guān)的查詢,更新出爹,刪除等操作庄吼,不能假設(shè)數(shù)據(jù)庫(kù)里的數(shù)據(jù)是存在的,或者直接操作數(shù)據(jù)庫(kù)把數(shù)據(jù)插入進(jìn)去严就,請(qǐng)使用程序插入或者導(dǎo)入數(shù)據(jù)的方式來(lái)準(zhǔn)備數(shù)據(jù)总寻。
- 和數(shù)據(jù)庫(kù)相關(guān)的單元測(cè)試,可以設(shè)定自動(dòng)回滾機(jī)制梢为,不給數(shù)據(jù)庫(kù)造成臟數(shù)據(jù)渐行。或者對(duì)單元測(cè)試產(chǎn)生的數(shù)據(jù)有明確的前后綴標(biāo)識(shí)铸董。
- 對(duì)于不可測(cè)的代碼建議做必要的重構(gòu)祟印,使代碼變得可測(cè),避免為了達(dá)到測(cè)試要求而 書(shū)寫(xiě)不規(guī)范測(cè)試代碼粟害。
- 編寫(xiě)單元測(cè)試代碼遵守 BCDE 原則蕴忆,以保證被測(cè)試模塊的交付質(zhì)量。
1)B:Border悲幅,邊界值測(cè)試套鹅,包括循環(huán)邊界站蝠、特殊取值、特殊時(shí)間點(diǎn)卓鹿、數(shù)據(jù)順序等菱魔。
2)C:Correct,正確的輸入吟孙,并得到預(yù)期的結(jié)果澜倦。
3)D:Design,與設(shè)計(jì)文檔相結(jié)合杰妓,來(lái)編寫(xiě)單元測(cè)試藻治。
4)E:Error,強(qiáng)制錯(cuò)誤信息輸入(如:非法數(shù)據(jù)稚失、異常流程栋艳、非業(yè)務(wù)允許輸入等),并得 到預(yù)期的結(jié)果句各。
ps:如何寫(xiě)出合格的單元測(cè)試代碼我也有點(diǎn)蒙吸占,目前是核心service代碼會(huì)寫(xiě)單元測(cè)試進(jìn)行功能驗(yàn)證,有相關(guān)經(jīng)驗(yàn)的朋友希望能給點(diǎn)建議凿宾。
八矾屯、安全規(guī)約
1. 操作權(quán)限
隸屬于用戶個(gè)人的頁(yè)面或者功能必須進(jìn)行權(quán)限控制校驗(yàn)。防止沒(méi)有做水平權(quán)限校驗(yàn)就可隨意訪問(wèn)初厚、修改件蚕、刪除別人的數(shù)據(jù),比如查看他人的私信 內(nèi)容产禾、修改他人的訂單排作。
2. XSS
跨站腳本攻擊(Cross Site Scripting),可以對(duì)用戶錄入內(nèi)容進(jìn)行白名單過(guò)濾亚情,去除非法信息妄痪。禁止向 HTML 頁(yè)面輸出未經(jīng)安全過(guò)濾或未正確轉(zhuǎn)義的用戶數(shù)據(jù)。
3. CSRF
CSRF(Cross-site request forgery)跨站請(qǐng)求偽造楞件,是一類(lèi)常見(jiàn)編程漏洞衫生。對(duì)于存在 CSRF 漏洞的應(yīng)用/網(wǎng)站,攻擊者可以事先構(gòu)造好URL土浸,只要受害者用戶一訪問(wèn)罪针,后臺(tái)便在用戶不知情情況下對(duì)數(shù)據(jù)庫(kù)中用戶參數(shù)進(jìn)行相應(yīng)修改。表單黄伊、AJAX提交必須執(zhí)行 CSRF 安全過(guò)濾泪酱,通常可以通過(guò)額外的token字段來(lái)實(shí)現(xiàn)。
4. SQL注入
用戶輸入的 SQL 參數(shù)嚴(yán)格使用參數(shù)綁定或者 METADATA 字段值限定西篓,防止 SQL 注入愈腾,禁止字符串拼接 SQL 訪問(wèn)數(shù)據(jù)庫(kù)。
5. 用戶請(qǐng)求參數(shù)有效性驗(yàn)證
忽略參數(shù)校驗(yàn)可能導(dǎo)致:
- page size 過(guò)大導(dǎo)致內(nèi)存溢出
- 惡意 order by 導(dǎo)致數(shù)據(jù)庫(kù)慢查詢
- 任意重定向
- SQL 注入
- 反序列化注入
- 正則輸入源串拒絕服務(wù) ReDoS岂津,Java 代碼用正則來(lái)驗(yàn)證客戶端的輸入,有些正則寫(xiě)法驗(yàn)證普通用戶輸入沒(méi)有問(wèn)題悦即,但是如果攻擊人員使用的是特殊構(gòu)造的字符串來(lái)驗(yàn)證吮成,有可能導(dǎo)致死循環(huán)的結(jié)果。
6. 防重放限制
在使用平臺(tái)資源辜梳,譬如短信粱甫、郵件、電話作瞄、下單茶宵、支付,必須實(shí)現(xiàn)正確的防重放限制宗挥, 如數(shù)量限制乌庶、疲勞度控制、驗(yàn)證碼校驗(yàn)契耿,避免被濫刷瞒大、資損。 如注冊(cè)時(shí)發(fā)送驗(yàn)證碼到手機(jī)搪桂,如果沒(méi)有限制次數(shù)和頻率透敌,那么可以利用此功能騷擾到其它用戶,并造成短信平臺(tái)資源浪費(fèi)(曾經(jīng)阿里云的短信被一晚上刷了幾百塊的...)踢械。
7. 防刷
發(fā)貼酗电、評(píng)論、發(fā)送即時(shí)消息等用戶生成內(nèi)容的場(chǎng)景必須實(shí)現(xiàn)防刷内列、文本內(nèi)容違禁詞過(guò)濾等風(fēng)控策略撵术,敏感詞過(guò)濾可以考慮阿里云的綠網(wǎng)服務(wù)。
8. 信息脫敏
用戶敏感數(shù)據(jù)禁止直接展示德绿,必須對(duì)展示數(shù)據(jù)進(jìn)行脫敏荷荤。 查看個(gè)人手機(jī)號(hào)碼會(huì)顯示成:158****9119,隱藏中間 4 位移稳,防止隱私泄露蕴纳。
MySQL和編程實(shí)踐(集合、并發(fā)處理)等部分后續(xù)另起一篇文章來(lái)寫(xiě)个粱。
仍建議先看幾遍《阿里巴巴Java開(kāi)發(fā)手冊(cè)(終極版)》,然后再以自己的方式理解記憶古毛。