一沼本、整潔代碼
A.混亂的代價
1.有些團(tuán)隊在項目初期進(jìn)展迅速噩峦,但有那么一兩年的時間卻慢去蝸行。對代碼的每次修改都影響到其他兩三處代碼
2.花時間保持代碼整潔不但有關(guān)效率抽兆,還有關(guān)生存
3.程序員遵從不了解混亂風(fēng)險經(jīng)理的意愿识补,也是不專業(yè)的做法
4.Bjarne Stroustrup,C++發(fā)明者:我喜歡優(yōu)雅和高效的代碼辫红。代碼邏輯應(yīng)該直接了當(dāng)凭涂,叫缺陷難以隱藏;盡量減少依賴關(guān)系贴妻,使之便于維護(hù)切油;依據(jù)某種分層戰(zhàn)略完善錯誤處理代碼;性能調(diào)至最優(yōu)名惩,省得引誘別人做沒規(guī)矩的優(yōu)化澎胡,搞出一堆混亂來娩鹉。整潔的代碼只做好一件事弯予。
5.Grady Booch阁苞,《面向分析與設(shè)計》:整潔的代碼簡單直接那槽。整潔的代碼如同優(yōu)美的散文骚灸。整潔的代碼從不隱藏設(shè)計者的意圖甚牲,充滿了干凈利落的抽象和直接了當(dāng)?shù)目刂普Z句。
6.Dave Thomas雏赦,OTI公司創(chuàng)始人:整潔的代碼應(yīng)可由作者之外的開發(fā)者閱讀和增補星岗。它應(yīng)有單元測試和驗收測試。它使用有意義的命名寥掐。它只提供一種而非多種做一件事的途徑召耘。它只有盡量少的依賴關(guān)系,而且要明確地定義和提供清晰妓灌、盡量少的API祥山。代碼應(yīng)通過其字面表達(dá)含義缝呕,因為不同的語言導(dǎo)致并非所有必須信息均可通過代碼自身清晰表達(dá)摊聋。
7.Michael Feathers麻裁,《修改代碼的藝術(shù)》:我可以列出我留意到的整潔代碼的所有特點,但其中有一條是根本性的手销。整潔的代碼總是看起來像是某位特別在意它的人寫的锋拖。幾乎沒有改進(jìn)的余地。代碼作者什么都想到了讲仰,如果你企圖改進(jìn)它鄙陡,總會回到原點,贊嘆某人留給你的代碼——全心投入的某人留下的代碼毫捣。
8.Ron Jeffries蔓同,《極限編程實施》:簡單代碼,依其重要順序:能通過所有測試则北;沒有重復(fù)代碼尚揣;體現(xiàn)系統(tǒng)中的全部設(shè)計理念蒿辙;包括盡量少的實體,比如類恭取、方法蜈垮、函數(shù)等
9.Ward Cunningham,Wiki發(fā)明者:如果每個例程都讓你感到深合已意惠猿,那就是整潔代碼。如果代碼讓編程語言看起來像是專為解決那個問題而存在趾访,就可以稱之為漂亮的代碼扼鞋。
B.思想流派
1.讀與寫花費時間的比例起過10:1
C.童子軍軍規(guī)
1.“讓營地比你來時更干凈”
2.如果每次簽入時,代碼都比簽出時干凈盘寡,那么代碼就不會腐壞
二竿痰、有意義的命名
A.名副其實
1.變量变隔、函數(shù)或類的名稱應(yīng)該已經(jīng)答復(fù)了所有的大問題匣缘,如果名稱需要注釋來補充,那就不算名副其實
2.代碼的模糊度:即上下文在代碼中未被明確體現(xiàn)的程度
B.避免誤導(dǎo)
1.程序員必須避免留下掩藏代碼本意的錯誤線索柑爸。應(yīng)當(dāng)避免使用與本意相悖的詞
2.以同樣的方式拼寫出同樣的概念才是信息,拼寫前后不一致就是誤導(dǎo)
3.要注意使用小寫字母i和大寫字母O作為變量名譬圣,看起來像“壹”和“零”
C.做有意義的區(qū)分
1.同一作用范圍內(nèi)兩樣不同的東西不能重名厘熟,如果名稱必須相異,那其意思也應(yīng)該不同才對
2.廢話是另一種沒意義的區(qū)分就缆。假設(shè)你有一個Product類,如果還有一個ProductInfo或ProductData類切揭,那它們的名稱雖然不同廓旬,意思卻無區(qū)別
3.只要體現(xiàn)出有意義的區(qū)分涩盾,使用a和the這樣的前綴就沒錯
4.廢話都是冗余。Variable一詞記錄不應(yīng)當(dāng)出現(xiàn)在變量名中址儒,Table一詞永遠(yuǎn)不應(yīng)當(dāng)出現(xiàn)在表名中
D.使用讀得出來的名稱
E.使用可搜索的名稱
1.單字母名稱和數(shù)字常量有個問題莲趣,就是很難在一大篇文字中找出來
F.避免使用編碼
1.把類型或作用域編進(jìn)名稱里面,徒然增加了解碼的負(fù)擔(dān)
2.也不必用m_前綴來標(biāo)明成員變量,應(yīng)當(dāng)把類和函數(shù)做得足夠小嗽上,消除對成員前綴的需要
3.不加修飾的接口兽愤,不要用前導(dǎo)字母I
G.避免思維映射
1.不應(yīng)當(dāng)讓讀者在腦中把你的名稱翻譯為他們熟知的名稱,單字母變量名就是個問題
2.專業(yè)程序員了解洼畅,明確是王道
H.類名
1.類名和對象名應(yīng)該是名詞或名詞短語,類名不應(yīng)當(dāng)是動詞
I.方法名
1.方法名應(yīng)該是動詞或動詞短語丧肴。屬性訪問器芋浮、修改器和斷言應(yīng)該根據(jù)其值命名镇草,并依Javabean標(biāo)準(zhǔn)加上get陶夜、set和is前綴
2.可以考慮將相應(yīng)構(gòu)造器設(shè)置為private,強制使用這種命名手段
J.別扮可愛
1.言到意到羽嫡,意到言到
K.別用雙關(guān)語
1.避免將同一單詞用于不同目的
2.應(yīng)盡力寫出易于理解的代碼,把代碼寫得讓別人能一目盡覽而不必殫精竭慮地研究
L.使用解決方案領(lǐng)域名稱
1.盡管用那些計算機科學(xué)術(shù)語魂爪、算法名滓侍、模式名、數(shù)學(xué)術(shù)語
M.使用源自所涉問題領(lǐng)域的名稱
1.如果不能用程序員熟悉的術(shù)語來給手頭的工作命名夕冲,就采用從所涉問題領(lǐng)域而來的名稱
2.優(yōu)秀的程序員和設(shè)計師歹鱼,其工作之一就是分離解決方案領(lǐng)域和問題領(lǐng)域的概念
N.添加有意義的語境
1.你需要用有良好命名的類、函數(shù)或名稱空間來放置名稱蚁阳,給讀者提供語境
2.如果沒這么做螺捐,給名稱添加前綴就是最后一招了
O.不要添加沒用的語境
1.只要短名稱足夠清楚赔癌,就要比長名稱好
P.最后的話
1.取好名字最難的地方在于需要良好的描述技巧和共有文化背景
三、函數(shù)
A.短小
1.函數(shù)的第一規(guī)則是要短小刊苍,第二條規(guī)則是還要更短小
2.if語句正什、else語句、while語句等主经,其中的代碼塊應(yīng)該只有一行旨怠,該行大抵是一個函數(shù)調(diào)用語句
3.函數(shù)不應(yīng)該大到足以容納嵌套結(jié)構(gòu),所以,函數(shù)的縮進(jìn)層級不該多于一層或兩層
B.只做一件事
1.函數(shù)應(yīng)該做一件事器一。做好這件事祈秕,只做這一件事
2.要判斷函數(shù)是否不止做了一件事,就是看看是否能再拆出一個函數(shù)方仿,該函數(shù)不僅只是單純地重新詮釋其實現(xiàn)
3.只做一件事的函數(shù)無法被合理地切分為多個區(qū)段
C.每個函數(shù)一個抽象層級
1.要確保函數(shù)只做一件事仙蚜,函數(shù)中的語句都要在同一抽象層級上
2.自頂向下讀代碼:向下規(guī)則呜师,讓代碼擁有自頂向下的閱讀順序汁汗,讓每個函數(shù)后面都跟著下一抽象層級的函數(shù)
D.switch語句
1.寫出短小的switch語句很維,寫出只做一件事的switch語句也很難送爸,Switch天生要做N件事
2.將switch語句埋到抽象工廠底下球匕,不讓任何人看到
3.如果只出現(xiàn)一次橄杨,用于創(chuàng)建多態(tài)對象式矫,而且隱藏在某個繼承關(guān)系中,在系統(tǒng)其他部分看不到瞬痘,就還能容忍
E.使用描述性的名稱
1.沃德原則:“如果每個例程都讓你感到深合已意察绷,那就是整潔代碼”
2.函數(shù)越短小克婶,功能越集中鸭蛙,就越便于取個好名字
3.別害怕長名稱,長而具有描述性的名稱肪获,要比短而令人費解的名稱好
4.命名方式要保持一致孝赫。使用與模塊名一脈相承的短語、名詞和動詞給函數(shù)命名
F.函數(shù)參數(shù)
1.最理想的參數(shù)數(shù)量是零致开,有足夠的理由才能用三個以上參數(shù)
2.事件:在這種形式中,有輸入?yún)?shù)而無輸出參數(shù)飒货,程序?qū)⒑瘮?shù)看作一個事件,使用該參數(shù)修改系統(tǒng)狀態(tài)
3.對于轉(zhuǎn)換,使用輸出參數(shù)而非返回值令人迷惑毅访,如果函數(shù)要對輸入?yún)?shù)進(jìn)行轉(zhuǎn)換操作,轉(zhuǎn)換結(jié)果就該體現(xiàn)為返回值
4.向函數(shù)傳入布爾值會使方法簽名立刻變得復(fù)雜起來守呜,大聲宣布函數(shù)不止做一件事
5.如果函數(shù)看來需要兩個弥喉、三個或三個以上參數(shù)由境,就說明其中一些參數(shù)應(yīng)該封裝為類了
6.有可變參數(shù)的函數(shù)可能是一元、二元甚至三元纺阔,超過這個數(shù)量就可能要犯錯了
7.對于一元函數(shù)低零,函數(shù)和參數(shù)應(yīng)當(dāng)形成一種非常良好的動詞/名詞對形式
G.無副作用
1.函數(shù)承諾只做一件事啃奴,但還是會做其他被藏起來的事,會導(dǎo)致古怪的時序性耦合及順序依賴
2.參數(shù)多數(shù)會被自然而希地看作是函數(shù)的輸入
H.分隔指令與詢問
1.函數(shù)要么做什么事瘟则,要么回答什么事枝秤,但二者不可得兼
I.使用異步替代返回錯誤碼
1.從指令式函數(shù)返回錯誤碼輕微違反了指令與詢問分隔的規(guī)則醋拧。它鼓勵了在if語句判斷中把指令當(dāng)作表達(dá)式使用
2.try/catch代碼塊把錯誤處理與正常流程混為一談,最好把try和catch代碼塊的主體部分抽離出來淀弹,另外形成函數(shù)
3.錯誤處理就是一件事丹壕,處理錯誤的函數(shù)不該做其他事
4.依賴磁鐵(dependency magnet):其他許多類都得導(dǎo)入和使用它
J.別重復(fù)自己
1.重復(fù)可能是軟件中一切邪惡的根源,許多原則與實踐規(guī)則都是為控制與消除重復(fù)而創(chuàng)建
K.結(jié)構(gòu)化編程
1.每個函數(shù)薇溃、函數(shù)中的每個代碼塊都應(yīng)該有一個入口、一個出口。遵循這些規(guī)則,意味著在每個函數(shù)中只該有一個return語句脑题,循環(huán)中不能有break或者continue語句痊末,而且永永遠(yuǎn)遠(yuǎn)不能有任何的goto語句
2.只有在大函數(shù)中這些規(guī)則才會有明顯好處,因為,只要函數(shù)保持短小里伯,偶爾出現(xiàn)的return、break或continue語句沒有壞處,goto語句盡量避免
L.如何寫出這樣的函數(shù)
1.打磨代碼岩瘦,分解函數(shù)握爷、修改名稱、消除重復(fù)
2.縮短和重新安置方法、拆散類涵叮、保持測試通過
四、注釋
1.若編程語言足夠有表達(dá)力,就不需要注釋
2.注釋的恰當(dāng)用法是彌補我們在用代碼表達(dá)意圖時遭遇的失敗备图。注釋總是一種失敗
3.程序員應(yīng)當(dāng)負(fù)責(zé)將注釋保持在可維護(hù)、有關(guān)聯(lián)汰聋、精確的高度,更應(yīng)該把力氣用在寫清楚代碼上搔扁,直接保證無須編寫注釋
4.不準(zhǔn)確的注釋要比沒注釋壞得多
A.注釋不能美化糟糕的代碼
1.帶有少量注釋的整潔而有表達(dá)力的代碼,要比帶有大量注釋的零碎而復(fù)雜的代碼像樣得多
2.與其花時間編寫解釋你搞出的糟糕的代碼的注釋,不如花時間清潔那堆糟糕的代碼
B.用代碼來闡述
1.用代碼解釋你大部分的意圖,很多時候,簡單到只需要創(chuàng)建一個描述與注釋所言同一事物的函數(shù)即可
C.好注釋
1.法律信息
2.提供信息的注釋
3.對意圖的解釋:提供某個決定后面的意圖
4.闡釋:注釋把某些晦澀難懂的參數(shù)或返回值的意義翻譯為某種可讀形式
5.警示
6.TODO注釋:注意要清理
7.放大:放大某種看來不合理之物的重要性
8.公共API中的Javadoc
D.壞注釋
1.喃喃自語
2.多余的注釋
3.誤導(dǎo)性注釋
4.循規(guī)式注釋
5.日志式注釋
6.廢話注釋
7.可怕的廢話
8.能用函數(shù)或變量時就別用注釋
9.位置標(biāo)記:如果標(biāo)記欄不多缸棵,就會顯而易見,所以,盡量少用標(biāo)記欄宇挫,只在特別有價值的時候用
10.括號后面的注釋
11.歸屬與署名
12.注釋掉的代碼
13.HTML注釋
14.非本地信息
15.信息過多
16.不明顯的聯(lián)系
17.函數(shù)頭
18.非公共代碼中的Javadoc
19.范例
五历帚、格式
A.格式的目的
1.代碼格式關(guān)乎溝通,而溝通是專業(yè)開發(fā)者的頭等大事
B.垂直格式
1.短文件通常比長文件易于理解
2.源文件也要像報紙文章那樣 ,名稱應(yīng)當(dāng)簡單且一目了然,最頂部應(yīng)該給出高層次概念和算法殴胧,細(xì)節(jié)應(yīng)該往下漸次展開
3.幾乎所有的代碼都是從上往下讀,從左往右讀茎匠。每行展現(xiàn)一個表達(dá)式或一個子句煤伟,每代碼行展示一條完整的思路稿湿。這些思路用空白行區(qū)隔開來元镀。
4.如果說空白行隔開了概念雇寇,靠近的代碼行則暗示了它們之間的緊密關(guān)系
5.除非有很好的理由官册,否則就不要把關(guān)系密切的概念放到不同的文件中挤聘,實際上,這也是避免使用protected變量的理由之一,應(yīng)避免迫使讀者在源文件和類中跳來跳去
6.變量聲明應(yīng)盡可能靠近其使用位置缝其,在函數(shù)頂部出現(xiàn)谍失,循環(huán)的控制變量總是在循環(huán)語句中聲明
7.實體變量在類的頂部聲明
8.相關(guān)函數(shù)逗旁,若某個函數(shù)調(diào)用了另外一個,就應(yīng)該把它們放到一起片效,而且調(diào)用者應(yīng)該盡可能放在被調(diào)用者上面
9.概念相關(guān)的代碼應(yīng)該放到一起仓洼,相關(guān)性越強,彼此之間的距離就該越短
10.我們想自上向下展示函數(shù)調(diào)用依賴順序堤舒,被調(diào)用的函數(shù)應(yīng)該放在執(zhí)行調(diào)用的函數(shù)下面色建,這就建立了一種自頂向下貫穿源代碼模塊的良好信息流
C.橫向格式
1.盡力保持代碼行短小,遵循無需拖動滾動條到右邊的原則舌缤,最好不超過120個
2.我們使用空格字符將彼此緊密相關(guān)的事物連接到一起箕戳,也用空格字符把相關(guān)性較弱的事物分隔開
3.對齊某残,像是在強調(diào)不重要的東西,把目光從真正的意義上拉開
4.如果有較長的列表需要做對齊處理陵吸,那問題就是在列表的長度上而不是對齊上
5.程序員相當(dāng)依賴縮進(jìn)模式
6.有時玻墅,while或for語句的語句體為空,如果無法避免壮虫,就確卑南幔空范圍體的縮進(jìn),用括號包圍起來
D.團(tuán)隊規(guī)則
1.一組開發(fā)者應(yīng)當(dāng)認(rèn)同一種模式風(fēng)格囚似,每個成員都應(yīng)該采用那種風(fēng)格
2.好的軟件系統(tǒng)是由一系列讀起來不錯的代碼文件組成的剩拢,需要擁有一致和順暢的風(fēng)格
六、對象和數(shù)據(jù)結(jié)構(gòu)
A.數(shù)據(jù)抽象
1.隱藏實現(xiàn)關(guān)乎抽象饶唤,類并不簡單地用取值器和賦值器將其變量推向外部徐伐,而是曝露抽象接口,以便用戶無需了解數(shù)據(jù)的實現(xiàn)就能操作數(shù)據(jù)本體
B.數(shù)據(jù)募狂、對象的反對稱性
1.對象把數(shù)據(jù)隱藏于抽象之后办素,曝露操作數(shù)據(jù)的函數(shù)。數(shù)據(jù)結(jié)構(gòu)曝露其數(shù)據(jù)祸穷,并沒有提供有意義的函數(shù)
2.對象與數(shù)據(jù)結(jié)構(gòu)之間的二分原理:
* 過程式代碼(使用數(shù)據(jù)結(jié)構(gòu)的代碼)便于在不改動既有數(shù)據(jù)結(jié)構(gòu)的前提下添加新函數(shù)性穿。面向?qū)ο蟠a便于在不改動既有函數(shù)的前提下添加新類
* 過程式代碼難以添加新數(shù)據(jù)結(jié)構(gòu),因為必須修改所有函數(shù)雷滚。面向?qū)ο蟠a難以添加新函數(shù)需曾,因為必須修改所有類
C.得墨忒耳律
1.得墨忒耳律(The Law of Demeter):模塊不應(yīng)了解它所操作對象的內(nèi)部情形,意味著對象不應(yīng)通過存取器曝露其內(nèi)部結(jié)構(gòu)揭措,因為這樣更像是曝露而非隱藏其內(nèi)部結(jié)構(gòu)
2.混合結(jié)構(gòu),一半是對象刻蚯,一半是數(shù)據(jù)結(jié)構(gòu)绊含,應(yīng)避免這種結(jié)構(gòu)
D.數(shù)據(jù)傳送對象
1.最為精練的數(shù)據(jù)結(jié)構(gòu)罪治,是一個只有公共變量渗鬼、沒有函數(shù)的類,這種被稱為數(shù)據(jù)傳送對象脾歧,或DTO(Data Transfer Objects)讨便。在與數(shù)據(jù)庫通信充甚、或解析套接字傳遞的消息之類場景中
2.JavaBean或Active Record
3.不要塞進(jìn)業(yè)務(wù)規(guī)則方法,把Active Record當(dāng)做數(shù)據(jù)結(jié)構(gòu)霸褒,并創(chuàng)建包含業(yè)務(wù)規(guī)則伴找、隱藏內(nèi)部數(shù)據(jù)(可能就是Active Record的實體)的獨立對象
七、錯誤處理
1.錯誤處理很重要废菱,但如果它搞亂了代碼邏輯技矮,就是錯誤的做法
A.使用異常而非返回碼
1.遇到錯誤時抖誉,最好拋出一個異常。調(diào)用代碼很整潔衰倦,其邏輯不會被錯誤處理搞亂
B.先寫Try-Catch-Finally語句
1.異常的妙處之一是袒炉,它們在程序中定義了一個范圍。執(zhí)行try-catch-finally語句中try部分的代碼時樊零,你是在表明可隨時取消執(zhí)行我磁,并在catch語句中接續(xù)
2.在某種意義上,try代碼塊就像是事務(wù)驻襟,catch代碼塊將程序維持在一種持續(xù)狀態(tài)
3.在編寫可能拋出異常的代碼時夺艰,最好先寫try-catch-finally語句,能幫你定義代碼的用戶應(yīng)該期待什么塑悼,無論try代碼塊中執(zhí)行的代碼出什么錯都一樣
C.使用不可控異常
1.可控異常的代價就是違反開放/閉合原則劲适,得在catch語句和拋出異常處之間的每個方法簽名中聲明該異常
2.可控異常意味著對軟件中較低層級的修改,都將波及較高層級的簽名
D.給出異常發(fā)生的環(huán)境說明
1.拋出的每個異常厢蒜,都應(yīng)當(dāng)提供足夠的環(huán)境說明,以便判斷錯誤的來源和處所
2.應(yīng)創(chuàng)建信息充分的錯誤消息斑鸦,并和異常一起傳遞出去
E.依調(diào)用者需要定義異常類
1.最重要的考慮是它們?nèi)绾伪徊东@
2.將第三方API打包是個良好的實踐手段愕贡,降低了對每個第三方的依賴,也有助于模擬第三方調(diào)用
F.定義常規(guī)流程
1.特例模式(SPECIAL CASE PATTERN,[Fowler])巷屿,創(chuàng)建一個類或配置一個對象固以,用來處理特例,異常行為被封裝到特例對象中
G.別返回null值
1.返回null值嘱巾,基本是在給自己增加工作量憨琳,也是在給調(diào)用者添亂,只要有一處沒檢查null值旬昭,應(yīng)用程序就會失控
H.別傳遞null值
1.將null值傳遞給其他方法更糟糕篙螟,除非API要求你向它傳遞null值,否則就要盡可能避免傳遞null值
八问拘、邊界
A.使用第三方代碼
1.第三方程序包和框架提供者追求普適性遍略,這樣就能在多個環(huán)境中工作,吸引廣泛的用戶
2.我們建議不要將Map(或在邊界上的其他接口)在系統(tǒng)中傳遞骤坐,把它保留在類或近親類中绪杏,避免從API中返回邊界接口,或?qū)⒔涌谧鳛閰?shù)傳遞給公共API
B.瀏覽和學(xué)習(xí)邊界
C.學(xué)習(xí)性測試的好處不只是免費
1.學(xué)習(xí)性測試毫無成本纽绍,編寫測試是獲得這些知識(要使用的API)的容易而不會影響其他工作的途徑
2.學(xué)習(xí)性測試確保第三方程序包按照我們想要的方式工作
D.使用尚不存在的代碼
1.編寫我們想得到的接口蕾久,好處之一是它在我們控制之下,有助于保持客戶代碼更可讀拌夏,且集中于它該完成的工作
E.整潔的邊界
1.邊界上的改動腔彰,有良好的軟件設(shè)計叫编,無需巨大投入和重寫即可進(jìn)行修改
2.邊界上的代碼需要清晰的分割和定義了期望的測試。依靠你能控制的東西霹抛,好過依靠你控制不了的東西搓逾,免得日后受它控制
3.可以使用ADAPTER模式將我們的接口轉(zhuǎn)換為第三方提供的接口
九、單元測試
A.TDD三定律
1.在編寫能通過的單元測試前杯拐,不可編寫生產(chǎn)代碼
2.只可編寫剛好無法通過的單元測試霞篡,不能編譯也算不通過
3.只可編寫剛好足以通過當(dāng)前失敗測試的生產(chǎn)代碼
B.保持測試整潔
1.臟測試等同于沒測試,測試必須隨生產(chǎn)代碼的演進(jìn)而修改端逼,測試越臟朗兵,就越難修改
2.測試代碼和生產(chǎn)代碼一樣重要,它需要被思考顶滩、被設(shè)計和被照料余掖,它該像生產(chǎn)代碼一般保持整潔
3.如果測試不能保持整潔,你就會失去它們礁鲁,沒有了測試盐欺,你就會失去保證生產(chǎn)代碼可擴(kuò)展的一切要素
C.整潔的測試
1.三個要素:可讀性、可讀性和可讀性仅醇,明確冗美、簡潔還有足夠的表達(dá)力
2.構(gòu)造-操作-檢驗(BUILD-OPERATE-CHECK)模式,第一個環(huán)節(jié)構(gòu)造測試數(shù)據(jù)析二,第二個環(huán)節(jié)操作測試數(shù)據(jù)粉洼,第三個部分檢驗操作是否得到期望的結(jié)果
3.守規(guī)矩的開發(fā)者也將他們的測試代碼重構(gòu)為更簡潔和具有表達(dá)力的形式
D.每個測試一個斷言
1.JUnit中每個測試函數(shù)都應(yīng)該有且只有一個斷言語句
2.最好的說法是單個測試中的斷言數(shù)量應(yīng)該最小化
3.更好一些的規(guī)則或許是每個測試函數(shù)中只測試一個概念
4.最佳規(guī)則是應(yīng)該盡可能減少每個概念的斷言數(shù)量,每個測試函數(shù)只測試一個概念
E.F.I.R.S.T
1.快速(Fast)測試應(yīng)該夠快
2.獨立(Independent)測試應(yīng)該相互獨立
3.可重復(fù)(Repeatable)測試應(yīng)當(dāng)可在任何環(huán)境中重復(fù)通過
4.自足驗證(Self-Validating)測試應(yīng)該有布爾值輸出
5.及時(Timely)測試應(yīng)及時編寫
十叶摄、類
A.類的組織
1.類應(yīng)該從一級變量列表開始属韧,如果有公共靜態(tài)變量,應(yīng)該先出現(xiàn)蛤吓,然后是私有靜態(tài)變量宵喂,以及實體變量,很少會有公共變量
2.公共函數(shù)應(yīng)該跟在變量列表之后
3.保持變量和工具函數(shù)的私有性柱衔,但并不執(zhí)著于此
B.類應(yīng)該短小
1.第一規(guī)則是類應(yīng)該短小樊破,第二規(guī)則是還要更短小
2.衡量方法愉棱,計算權(quán)責(zé)(responsibility)
3.類的名稱應(yīng)當(dāng)描述其權(quán)責(zé)唆铐,如果無法為某個類命以精確的名稱,這個類大概就太長了奔滑,類名越含混艾岂,該類越有可能擁有過多權(quán)責(zé)
4.單一權(quán)責(zé)原則(SRP)認(rèn)為,類或模塊應(yīng)有且只有一條加以修改的理由
5.系統(tǒng)應(yīng)該由許多短小的類而不是少量巨大的類組成朋其,每個小類封裝一個權(quán)責(zé)王浴,只有一個修改的原因脆炎,并與少數(shù)其他類一起協(xié)同達(dá)成期望的系統(tǒng)行為
6.方法操作的變量越多,就越黏聚到類上氓辣,如果一個類的每個變量都被每個方法所使用秒裕,則該類具有最大的內(nèi)聚性
7.保持函數(shù)和參數(shù)列表短小的策略,有時會導(dǎo)致為一組子集方法所用的實體變量數(shù)量增加钞啸。出現(xiàn)這種情況時几蜻,往往意味著至少有一個類要從大類中掙扎出來。你應(yīng)當(dāng)嘗試將這些變量和方法分拆到兩個或多個類中体斩,讓新的類更為內(nèi)聚
8.將大函數(shù)拆為許多小函數(shù)梭稚,往往也是將類拆分為多個小類的時機
C.為了修改而組織
1.在整潔的系統(tǒng)中,我們對類加以組織絮吵,以降低修改的風(fēng)險
2.開放-閉合原則(OCP):類應(yīng)當(dāng)對擴(kuò)展開放弧烤,對修改封閉
3.在理想系統(tǒng)中,我們通過擴(kuò)展系統(tǒng)而非修改現(xiàn)有代碼來添加新特性
4.依賴倒置原則(Dependency Inversion Principle,DIP)蹬敲,類應(yīng)該依賴于抽象而不是依賴于具體細(xì)節(jié)
十一暇昂、系統(tǒng)
A.如何建造一個城市
1.每個城市都有一組人管理不同的部分,有人負(fù)責(zé)全局粱栖,其他人負(fù)責(zé)細(xì)節(jié)
2.深化出恰當(dāng)?shù)某橄蟮燃壓湍K话浇,好讓個人和他們所管理的“組件”即便在不了解全局時也能有效地運轉(zhuǎn)
B.將系統(tǒng)的構(gòu)造與使用分開
1.構(gòu)造與使用是非常不一樣的過程
2.軟件系統(tǒng)應(yīng)將啟始過程和啟始過程之后的運行時邏輯分離開,在啟始過程中構(gòu)建應(yīng)用對象闹究,也會存在互相纏結(jié)的依賴關(guān)系
3.將構(gòu)造與使用分開的方法之一是將全部構(gòu)造過程搬遷到main或被稱為main的模塊中幔崖,設(shè)計系統(tǒng)的其余部分時,假設(shè)所有對象都已正確構(gòu)造和設(shè)置
4.可以使用抽象工廠模式讓應(yīng)用自行控制何時創(chuàng)建對象渣淤,但構(gòu)造的細(xì)節(jié)卻隔離于應(yīng)用程序代碼之外
5.控制反轉(zhuǎn)將第二權(quán)責(zé)從對象中拿出來赏寇,轉(zhuǎn)移到另一個專注于此的對象中,從而遵循了單一權(quán)責(zé)原則价认。在依賴管理情景中嗅定,對象不應(yīng)負(fù)責(zé)實體化對自身的依賴,反之用踩,它應(yīng)當(dāng)將這份權(quán)責(zé)移交給其他“有權(quán)力”的機制渠退,從而實現(xiàn)控制的反轉(zhuǎn)
C.擴(kuò)容
1.“一開始就做對系統(tǒng)”純屬神話,反之脐彩,我們應(yīng)該只去實現(xiàn)今天的用戶故事碎乃,然后重構(gòu),明天再擴(kuò)展系統(tǒng)惠奸、實現(xiàn)新的用戶故事梅誓,這就是迭代和增量敏捷的精髓所在。測試驅(qū)動開發(fā)、重構(gòu)以及它們打造出的整潔代碼梗掰,在代碼層面保證了這個過程的實現(xiàn)
2.軟件系統(tǒng)與物理系統(tǒng)可以類比嵌言。它們的架構(gòu)都可以遞增式的增長,只要我們持續(xù)將關(guān)注面恰當(dāng)?shù)厍蟹?/p>
3.持久化之類關(guān)注面傾向于橫貫?zāi)硞€領(lǐng)域的天然對象邊界
D.Java代理
1.適用于簡單情況及穗,例如在單獨的對象或類中包裝方法調(diào)用
2.舊式的Java對象(Plain-Old Java Object, POJO)
E.純Java AOP框架
F.AspectJ的方面
G.測試驅(qū)動系統(tǒng)架構(gòu)
1.通過方面式(AOP)的手段切分關(guān)注面的威力不可低估摧茴。假使你能用POJO編寫應(yīng)用程序的領(lǐng)域邏輯,在代碼層面與架構(gòu)關(guān)注面分離開埂陆,就有可能真正地用測試來驅(qū)動架構(gòu)
2.沒必要先做大設(shè)計(Big Design Up Front蓬蝶,BDUF),BDUF甚至是有害的猜惋,它阻礙改進(jìn)丸氛,因為心理上會抵制丟棄即成之事,也因為架構(gòu)上的方案選擇影響到后續(xù)的設(shè)計思路
3.我們可以從“簡單自然”但切分良好的架構(gòu)開始做軟件項目著摔,快速交付可工作的用戶故事缓窜,隨著規(guī)模的增長添加更多基礎(chǔ)架構(gòu)
4.最佳的系統(tǒng)架構(gòu)由模塊化的關(guān)注面領(lǐng)域組成,每個關(guān)注面均用純Java(或其他語言)對象實現(xiàn)谍咆,不同的領(lǐng)域之間用最不具有侵害性的方面或類方面工具整合起來禾锤,這種架構(gòu)能測試驅(qū)動,就像代碼一樣
H.優(yōu)化決策
1.模塊化和關(guān)注面切分成就了分散化管理和決策
2.延遲決策至最后一刻也是好手段摹察,它讓我們能夠基于最有可能的信息做出選擇
3.擁有模塊化關(guān)注面的POJO系統(tǒng)提供的敏捷能力恩掷,允許我們基于最新的知識做出優(yōu)化的、時機剛好的決策供嚎,決策的復(fù)雜性也降低了
I.明智使用添加了可論證價值的標(biāo)準(zhǔn)
1.有了標(biāo)準(zhǔn)黄娘,就更易復(fù)用想法和組件、雇用擁有相關(guān)經(jīng)驗的人才克滴、封裝好點子逼争,以及將組件連接起來。不過劝赔,創(chuàng)立標(biāo)準(zhǔn)的過程有時卻漫長到行業(yè)等不及的程度誓焦,有些標(biāo)準(zhǔn)沒能與它要服務(wù)的采用者的真實需求相結(jié)合
J.系統(tǒng)需要領(lǐng)域特定語言
1.領(lǐng)域特定語言(Domain-Specific Language, DSL)是一種單獨的小型腳本語言或以標(biāo)準(zhǔn)語言寫就的API,領(lǐng)域?qū)<铱梢杂盟帉懽x像是組織嚴(yán)謹(jǐn)?shù)纳⑽囊话愕拇a
2.領(lǐng)域特定語言允許所有抽象層級和應(yīng)用程序中的所有領(lǐng)域着帽,從高級策略到底層細(xì)節(jié)杂伟,使用POJO來表達(dá)
十二、迭進(jìn)
A.通過迭進(jìn)設(shè)計達(dá)到整潔目的
1.“簡單規(guī)則”:
* 運行所有測試
* 不可重復(fù)
* 表達(dá)了程序員的意圖
* 盡可能減少類和方法的數(shù)量
* 以上規(guī)則按其重要程序排列
B.簡單設(shè)計原則1:運行所有測試
1.設(shè)計必須制造出如預(yù)期一般工作的系統(tǒng)仍翰,這是首要因素
2.全面測試并持續(xù)通過所有測試的系統(tǒng)赫粥,就是可測試的系統(tǒng),不可驗證的系統(tǒng)歉备,絕不應(yīng)部署
3.只要系統(tǒng)可測試傅是,就會導(dǎo)向保持類短小且目的單一的設(shè)計方案
4.緊耦合的代碼難以編寫測試
5.遵循有關(guān)編寫測試并持續(xù)運行測試的簡單匪燕、明確的規(guī)則蕾羊,系統(tǒng)就會更貼近OO低耦合度喧笔、高內(nèi)聚度的目標(biāo),編寫測試引致更好的設(shè)計
C.簡單設(shè)計原則2-4:重構(gòu)
1.有了測試龟再,就能保持代碼和類的整潔书闸,方法就是遞增式地重構(gòu)代碼
2.測試消除了對清理代碼就會破壞代碼的恐懼
D.不可重復(fù)
1.重復(fù)是擁有良好設(shè)計系統(tǒng)的大敵
2.極其雷同的代碼行當(dāng)然是重復(fù),還有實現(xiàn)上的重復(fù)等其他一些形態(tài)
3.“小規(guī)模復(fù)用”可大量降低系統(tǒng)復(fù)雜性利凑,要想實現(xiàn)大規(guī)模復(fù)用浆劲,必須理解如何實現(xiàn)小規(guī)模復(fù)用
4.模板方法模式是一種移除高層級重復(fù)的通用技巧
E.表達(dá)力
1.軟件項目的主要成本在于長期維護(hù),代碼應(yīng)當(dāng)清晰地表達(dá)其作者的意圖
2.可以通過選用好名稱來表達(dá)
3.可以通過保持函數(shù)和類尺寸短小來表達(dá)
4.可以通過采用標(biāo)準(zhǔn)命名法來表達(dá)
5.編寫良好的單元測試也具有表達(dá)性
6.做到有表達(dá)力的最重要方式是嘗試
F.盡可能少的類和方法
1.類和方法的數(shù)量太多哀澈,有時是由毫無意義的教條主義導(dǎo)致的牌借,應(yīng)該采用更實用的手段
2.目標(biāo)是在保持函數(shù)和類短小的同時,保持整個系統(tǒng)短小精悍
十三割按、并發(fā)編程
A.為什么要并發(fā)
1.并發(fā)是一種解耦策略膨报,它幫助我們把做什么(目的)和何時(時機)做分解開
2.解耦目的與時機能明顯地改進(jìn)應(yīng)用程序的吞吐量和結(jié)構(gòu)
3.單線程程序許多時間花在等待web套接字I/O結(jié)束上面,通過采用同時訪問多個站點的多線程算法适荣,就能改進(jìn)性能
4.常見的迷思和誤解
* 并發(fā)總能改進(jìn)性能:只在多個線程或處理器之間能分享大量等待時間的時候管用
* 編寫并發(fā)程序無需修改設(shè)計:可能與單線程系統(tǒng)的設(shè)計極不相同
* 在采用web或ejb容器時现柠,理解并發(fā)問題并不重要
5.有關(guān)編寫并發(fā)軟件的中肯的說法:
* 并發(fā)會在性能和編寫額外代碼上增加一些開銷
* 正確的并發(fā)是復(fù)雜的,即使對于簡單的問題也是如此
* 并發(fā)缺陷并非總能重現(xiàn)弛矛,所以常被看做偶發(fā)事件而忽略够吩,未被當(dāng)做真的缺陷看待
* 并發(fā)常常需要對設(shè)計策略的根本性修改
B.挑戰(zhàn)
1.線程在執(zhí)行代碼時有許多可能路徑可行,有些路徑會產(chǎn)生錯誤的結(jié)果
C.并發(fā)防御原則
1.單一權(quán)責(zé)原則(SRP):方法/類/組件應(yīng)當(dāng)只有一個修改的理由
* 并發(fā)相關(guān)代碼有自己的開發(fā)丈氓、修改和調(diào)優(yōu)生命周期
* 開發(fā)相關(guān)代碼有自己要對付的挑戰(zhàn)周循,和非并發(fā)相關(guān)代碼不同
* 即使沒有周邊應(yīng)用程序增加的負(fù)擔(dān),寫得不好的并發(fā)代碼可能的出錯方式數(shù)量也已經(jīng)足具有挑戰(zhàn)性
* 建議:分離并發(fā)相關(guān)代碼與其他代碼
2.推論:限制數(shù)據(jù)作用域
* 采用synchronized關(guān)鍵字在代碼中保護(hù)一塊使用共享對象的臨界區(qū)(critical section)
* 建議:謹(jǐn)記數(shù)據(jù)封閉万俗;嚴(yán)格限制對可能被共享的數(shù)據(jù)的訪問
3.推論:使用數(shù)據(jù)復(fù)本
* 一開始就避免共享數(shù)據(jù)鱼鼓,復(fù)制對象并以只讀方式對待,或復(fù)制對象该编,從多個線程收集所有復(fù)本的結(jié)果迄本,并在單個線程中合并這些結(jié)果
4.推論:線程應(yīng)盡可能地獨立
* 讓每個線程在自己的世界中存在,不與其他線程共享數(shù)據(jù)
* 建議:嘗試將數(shù)據(jù)分解到可被獨立線程(可能在不同處理器上)操作的獨立子集
D.了解Java庫
?1.要注意:
* 使用類庫提供的線程安全群集
* 使用executor框架(executor framework)執(zhí)行無關(guān)任務(wù)
* 盡可能使用非鎖定解決方案
* 有幾個類并不是線程安全的
E.了解執(zhí)行模型
1.一些基礎(chǔ)定義
* 限定資源:并發(fā)環(huán)境中有著固定尺寸或數(shù)量的資源
* 互斥:每一時刻僅有一個線程能訪問共享數(shù)據(jù)或共享資源
* 線程饑餓:一個或一組線程在很長時間內(nèi)或永久被禁止
* 死鎖:兩個或多個線程互相等待執(zhí)行結(jié)束课竣。每個線程都擁有其他線程需要的資源嘉赎,行不到其他線程擁有的資源,就無法終止
* 活鎖:執(zhí)行次序一致的線程于樟,每個都想要起步公条,但發(fā)現(xiàn)其他線程已經(jīng)“在路上”。由于競步的原因迂曲,線程會持續(xù)嘗試起步靶橱,但在很長時間內(nèi)卻無法如愿,甚至永遠(yuǎn)無法啟動
2.生產(chǎn)者-消費者模型:一個或多個生產(chǎn)者線程創(chuàng)建某些工作,并置于緩存或隊列中关霸。一個或多個消費者線程從隊列中獲取并完成這些工作传黄。生產(chǎn)者消費者之間的隊列是一種限定資源
3.讀者-作者模型:協(xié)調(diào)讀者線程,不去讀作者線程正在更新的信息(反之亦然)队寇,這是一種辛苦的平衡工作膘掰,作者線程傾向于長期鎖定許多讀者純種,從而導(dǎo)致吞吐量問題
4.宴席哲學(xué)家
5.建議學(xué)習(xí)這些基礎(chǔ)算法佳遣,理解其解決方案
F.警惕同步方法之間的依賴
1.同步方法之間的依賴會導(dǎo)致并發(fā)代碼中的狡猾缺陷识埋,建議避免使用一個共享對象的多個方法
2.基于客戶端的鎖定:客戶端代碼在調(diào)用第一個方法前鎖定服務(wù)端,確保鎖的范圍覆蓋了調(diào)用最后一個方法的代碼
3.基于服務(wù)端的鎖定:在服務(wù)端內(nèi)創(chuàng)建鎖定服務(wù)端的方法零渐,調(diào)用所有方法窒舟,然后解鎖。讓客戶端代碼調(diào)用新方法
4.適配服務(wù)端:創(chuàng)建執(zhí)行鎖定的中間層诵盼。這是一種基于服務(wù)端的鎖定的例子辜纲,但不修改原始服務(wù)端代碼
G.保持同步區(qū)域微小
1.同一個鎖維護(hù)的所有代碼區(qū)域在任一時刻保證只有一個線程執(zhí)行,因為它們帶來了延遲和額外開銷拦耐,臨界區(qū)應(yīng)該被保護(hù)起來耕腾,應(yīng)該盡可能少地設(shè)計臨界區(qū)
H.很維編寫正確的關(guān)閉代碼
1.平靜關(guān)閉很難做到,常見問題與死鎖有關(guān)杀糯,線程一直等待永遠(yuǎn)不會到來的信號
2.建議:盡早考慮關(guān)閉問題扫俺,盡早令其工作正常
I.測試線程代碼
1.建議:編寫有潛力曝露問題的測試,在不同的編程配置固翰、系統(tǒng)配置和負(fù)載條件下頻繁運行狼纬。如果測試失敗,跟蹤錯誤骂际。別因為后來測試通過了后來的運行就忽略失敗
2.將偽失敗看作可能的線程問題:線程代碼導(dǎo)致“不可能失敗的”失敗疗琉,不要將系統(tǒng)錯誤歸咎于偶發(fā)事件
3.先使非線程代碼可工作:不要同時追蹤非線程缺陷和線程缺陷,確保代碼在線程之外可工作
4.編寫可插拔的線程代碼歉铝,能在不同的配置環(huán)境下運行
5.編寫可調(diào)整的線程代碼:允許線程依據(jù)吞吐量和系統(tǒng)使用率自我調(diào)整
6.運行多于處理器數(shù)量的線程:任務(wù)交換越頻繁盈简,越有可能找到錯過臨界區(qū)域?qū)е滤梨i的代碼
7.在不同平臺上運行:盡早并經(jīng)常地在所有目標(biāo)平臺上運行線程代碼
8.裝置試錯代碼:增加對Object.wait()、Object.sleep()太示、Object.yield()柠贤、Object.priority()等方法的調(diào)用,改變代碼執(zhí)行順序类缤,硬編碼或自動化
十四臼勉、逐步改進(jìn)
1.要編寫清潔代碼,必須先寫骯臟代碼餐弱,然后再清理它
2.毀壞程序的最好方法之一就是以改進(jìn)之名大動其結(jié)構(gòu)
十五宴霸、JUnit內(nèi)幕
十六囱晴、重構(gòu)SerialDate
十七、味道與啟發(fā)
A.注釋
1.不恰當(dāng)?shù)男畔ⅲ鹤⑨屩粦?yīng)該描述有關(guān)代碼和設(shè)計的技術(shù)性信息
2.廢棄的注釋
3.冗余的注釋
4.糟糕的注釋:別閑扯瓢谢,別畫蛇添足畸写,保持簡潔
5.注釋掉的代碼:刪除它
B.環(huán)境
1.需要多步才能實現(xiàn)的構(gòu)建:構(gòu)建系統(tǒng)應(yīng)該是單步的小操作
2.需要多步才能做到的測試:應(yīng)當(dāng)能夠發(fā)出單個指令就可以運行全部單元測試
C.函數(shù)
1.過多的參數(shù):參數(shù)量應(yīng)該少,三個以上的參數(shù)非常值得質(zhì)疑
2.輸出參數(shù):輸出參數(shù)違反直覺恩闻,直接修改它所有對象的狀態(tài)
3.標(biāo)識參數(shù):布爾值參數(shù)大聲宣告函數(shù)做了不止一件事,應(yīng)該消滅掉
4.死函數(shù):永不被調(diào)用的方法應(yīng)該丟棄
D.一般性問題:
1.一個源文件中存在多種語言:盡力減少源文件中額外語言的數(shù)量和范圍
2.明顯的行為未被實現(xiàn):遵循“最小驚異原則”(The principle of Least Surprise)剧董,函數(shù)或類應(yīng)該實現(xiàn)其他程序員有理由期待的行為?
3.不正確的邊界行為:別依賴直覺幢尚,追索每種邊界條件,并編寫測試
4.忽視安全
5.重復(fù):看到重復(fù)代碼翅楼,都代表遺漏了抽象
6.在錯誤的抽象層級上的代碼:創(chuàng)建分離較高層級一般性概念(抽象類)與較低層級細(xì)節(jié)概念(派生類)的抽象模型
7.基類依賴于派生類:基類對派生類應(yīng)該一無所知
8.信息過多:設(shè)計良好的模塊有著非常小的接口尉剩,限制類或模塊中暴露的接口數(shù)量,類中的方法越少越好毅臊,隱藏你的數(shù)據(jù)理茎,隱藏你的工具函數(shù),隱藏常量和臨時變量
9.死代碼:刪除掉
10.垂直分隔:變量和函數(shù)應(yīng)該在靠近被使用的地方定義管嬉,垂直距離要短
11.前后不一致:從一而終皂林,可以追溯到最小驚異原則,讓代碼更加易于閱讀和修改
12.混淆視聽:保持源文件整潔蚯撩,良好地組織础倍,不被搞亂
13.人為耦合:不互相依賴的東西不該耦合
14.特性依戀:類的方法只應(yīng)對其所屬類中的變量和函數(shù)感興趣,不該垂青其他類中的變量和函數(shù)
15.選擇算子參數(shù):使用多個函數(shù)胎挎,通常優(yōu)于向單個函數(shù)傳遞某些代碼來選擇函數(shù)行為?
16.晦澀的意圖:代碼要盡可能具有表達(dá)力
17.位置錯誤的權(quán)責(zé):代碼應(yīng)該放在讀者自然而然期待它所有的地方
18.不恰當(dāng)?shù)撵o態(tài)方法:如果的確需要靜態(tài)函數(shù)沟启,確保沒機會打算讓它有多態(tài)行為
19.使用解釋性變量:讓程序可讀的最有力方法之一就是將計算過程打散成用有意義的單詞命名的變量中放置的中間值
20.函數(shù)名稱應(yīng)該表達(dá)其行為
21.理解算法:在你認(rèn)為自己完成某個函數(shù)之前,確認(rèn)自己理解了它是怎么工作的犹菇,你必須知道解決方案是正確的
22.把邏輯依賴改為物理依賴:依賴模塊不應(yīng)對被依賴者模塊有假定德迹,它應(yīng)當(dāng)明確地詢問后者全部信息
23.用多態(tài)替代if/Else或Switch/Case,“單個switch”規(guī)則:對于給定的選擇類型揭芍,不應(yīng)有多于一個switch語句
24.遵循標(biāo)準(zhǔn)約定胳搞,遵循基于通用行業(yè)規(guī)范的一套編碼標(biāo)準(zhǔn)
25.用命名常量替代魔術(shù)數(shù),在代碼中出現(xiàn)原始形態(tài)數(shù)字通常來說是壞現(xiàn)象称杨,有些常量與非常具有自我解釋能力的代碼協(xié)同工作時流酬,就不必總是需要命名常量來隱藏了×辛恚“魔術(shù)數(shù)”泛指任何不能自我描述的符號
26.準(zhǔn)確芽腾,在代碼中做決定時,確認(rèn)自己足夠準(zhǔn)確页衙,明確自己為何要這么做摊滔,如果遇到異常情況如何處理
27.結(jié)構(gòu)甚于約定
28.封裝條件阴绢,如果沒有if或while語句的上下文,布爾邏輯就難以理解艰躺,應(yīng)該把解釋了條件意圖的函數(shù)抽離出來
29.避免否定性條件呻袭,盡可能將條件表示為肯定形式
30.函數(shù)只該做一件事
31.掩蔽時序耦合,排列函數(shù)參數(shù)腺兴,好讓它們被調(diào)用的次序顯而易見
32.別隨意左电,構(gòu)建代碼需要理由,而且理由應(yīng)與代碼結(jié)構(gòu)相契合
33.封裝邊界條件页响,把處理邊界條件的代碼集中到一處篓足,不要散落于代碼中
34.函數(shù)應(yīng)該只在一個抽象層級上,函數(shù)中的語句應(yīng)該在同一抽象層級上闰蚕,該層級應(yīng)該是函數(shù)名所示操作的下一層
35.在較高層級放置可配置數(shù)據(jù)栈拖,如果你有個已知并該在較高抽象層級的默認(rèn)常量或配置值,不要將它埋藏到較低層級的函數(shù)中
36.避免傳遞瀏覽没陡,讓直接協(xié)作者提供所需的全部服務(wù)涩哟,不必逛遍系統(tǒng)的對象全圖,搜尋我們要調(diào)用的方法
E.Java
1.通過使用通配符避免過長的導(dǎo)入清單
2.不要繼承常量盼玄,應(yīng)該直接導(dǎo)入常量類
3.常量 vs. 枚舉贴彼,放心使用枚舉
F.名稱
1.采用描述性名稱,事物的意義隨著軟件的演化而變化埃儿,要經(jīng)常性地重新估量名稱是否恰當(dāng)
2.名稱應(yīng)與抽象層級相符锻弓,不要取溝通實現(xiàn)的名稱;取反映類或函數(shù)抽象層級的名稱
3.盡可能使用標(biāo)準(zhǔn)命名法
4.無歧義的名稱蝌箍,選用不會混淆函數(shù)或變量意義的名稱
5.為較大作用范圍選用較長名稱
6.避免編碼青灼,不要用匈牙利命名法污染你的名稱
7.名稱應(yīng)該說明副作用
G.測試
1.測試不足,一套測試應(yīng)該測到所有可能失敗的東西
2.使用覆蓋率工具妓盲,能匯報你測試策略中的缺口
3.別略過小測試
4.被忽略的測試就是對不確定事物的疑問
5.測試邊界條件
6.全面測試相近的缺陷
7.測試失敗的模式有啟發(fā)性杂拨,完整的測試用例,按合理的順序排列悯衬,能暴露出模式
8.測試覆蓋率的模式有啟發(fā)性
9.測試應(yīng)該快速