第2章 有意義的命名
名副其實(shí)
避免誤導(dǎo)
有意義的區(qū)分。不要有廢話定枷,不要有僅靠數(shù)字的標(biāo)識(shí)蟀瞧,名稱之間有區(qū)分度沉颂。
名稱長(zhǎng)端應(yīng)與其作用域大小相對(duì)應(yīng)条摸。
給每個(gè)抽象概念選一個(gè)詞,并且一以貫之铸屉。
只要短名稱足夠清楚钉蒲,就比長(zhǎng)名稱好。
第3章 函數(shù)
短小彻坛,更短小顷啼。
只做一件事。
語句要在同一抽象層上昌屉。
函數(shù)參數(shù)盡量不超過2個(gè)钙蒙;不要有標(biāo)識(shí)參數(shù)。
無副作用间驮。
使用異常替代返回錯(cuò)誤碼仪搔。
最好把try catch代碼的主題部分抽離形成另一個(gè)函數(shù)。錯(cuò)誤處理就是一件事蜻牢。
不要重復(fù)烤咧。
第4章 注釋
用代碼來闡述而不是用注釋
好注釋:提供信息、對(duì)意圖的解釋抢呆、警示煮嫌、TODO
壞注釋:多余、誤導(dǎo)抱虐、不必都包含javadoc昌阿、日志式、廢話恳邀、信息過多懦冰、包含的聯(lián)系并不明顯
能用函數(shù)或變量表達(dá)含義就別用注釋
注釋掉的代碼,不應(yīng)該存在谣沸。
第5章 格式
垂直格式:概念間垂直方向上間隔刷钢、變量聲明應(yīng)盡可能靠近其使用位置、函數(shù)間調(diào)用則最好將函數(shù)放在相近位置
橫向格式:使用空格將緊密事物連接到一起乳附,也將相關(guān)性較弱的事物區(qū)隔開内地。
第6章 對(duì)象和數(shù)據(jù)結(jié)構(gòu)
我們不愿意暴露數(shù)據(jù)細(xì)節(jié)而更愿意以抽象形態(tài)表述數(shù)據(jù)
public interface Vehicle {
double getFuelTankCapacityInGallons();
double getGallonsOfGasoline();
}
public interface Vehicle {
double getPercentFuelRemaining();
}
過程式代碼便于在不改動(dòng)既有數(shù)據(jù)結(jié)構(gòu)的前提下添加新函數(shù);面向?qū)ο蟠a便于在不改動(dòng)既有函數(shù)的前提下添加新類赋除。
模塊不應(yīng)了解它所操作對(duì)象的內(nèi)部情形阱缓,不過如果是數(shù)據(jù)結(jié)構(gòu),可能會(huì)了解举农。
對(duì)象暴露行為荆针,隱藏?cái)?shù)據(jù),便于添加新對(duì)象類型而無須修改既有行為,同時(shí)難以在既有對(duì)象中添加新行為航背;數(shù)據(jù)結(jié)構(gòu)暴露數(shù)據(jù)秸妥,沒有明顯行為,便于向既有數(shù)據(jù)結(jié)構(gòu)添加新行為沃粗,同時(shí)難以向既有函數(shù)添加新數(shù)據(jù)結(jié)構(gòu)粥惧。
第7章 錯(cuò)誤處理
某種意義try代碼塊就像是事務(wù),catch代碼塊將程序維持在一種持續(xù)狀態(tài)最盅。
已檢查的代價(jià)就是違反開閉原則突雪,使用未檢異常RuntimeException
不返回null值,也不傳遞null值
在業(yè)務(wù)邏輯和錯(cuò)誤處理代碼之間有良好的區(qū)隔
第8章 邊界
避免從公共API中返回邊界接口涡贱,或?qū)⑦吔缃涌谧鳛閰?shù)傳遞給公共API
例如在系統(tǒng)中不受限制地傳遞Map<String, Sensor>的實(shí)體咏删,以為著當(dāng)Map接口被修改時(shí),有許多地方都要跟著改问词。
// 這樣能稍微好一點(diǎn)
publc class Sensors {
private Map sensors = new HashMap();
public Sensor getById(String id) {return (Sensor) sensors.get(id);}
}
編寫測(cè)試來遍覽和理解第三方代碼督函。
邊界上的代碼需要清晰地分割和定義了期望的測(cè)試。應(yīng)該避免我們的代碼過多地了解第三方代碼中的特定信息激挪。
第9章 單元測(cè)試
測(cè)試直達(dá)辰狡,只用到那些真正需要的數(shù)據(jù)類型和函數(shù)。
每個(gè)測(cè)試函數(shù)中只測(cè)試一個(gè)概念垄分。
FIRST原則宛篇,快、獨(dú)立薄湿、可重復(fù)叫倍、自足驗(yàn)證(有布爾值輸出,不應(yīng)該通過查看日志文件來確認(rèn)是否通過)豺瘤、及時(shí)
第10章 類
單一權(quán)責(zé)吆倦,類或模塊應(yīng)該有且只有一條加以修改的理由
如果一個(gè)類中的每個(gè)變量都被每個(gè)方法所使用,則該類具有最大的內(nèi)聚性
保持內(nèi)聚性就會(huì)得到許多短小的類
為了修改而組織坐求,對(duì)類加以組織蚕泽,降低修改的風(fēng)險(xiǎn)。依賴接口而不是依賴實(shí)現(xiàn)瞻赶。
第11章 系統(tǒng)
將系統(tǒng)的構(gòu)造與使用分開赛糟,每個(gè)應(yīng)用程序都應(yīng)該留意起始過程 (工廠)
擴(kuò)充,提到了代理砸逊、AOP
最佳的系統(tǒng)架構(gòu)由模塊化的關(guān)注面領(lǐng)域組成,每個(gè)關(guān)注面均用純Java對(duì)象實(shí)現(xiàn)掌逛。不同的領(lǐng)域之間用最不具有侵害性的方面或類方面工具整合起來师逸。
延遲決策至最后一刻也是好手段。
第12章 迭進(jìn)
通過迭進(jìn)設(shè)計(jì)達(dá)到整潔目的豆混。
運(yùn)行所有測(cè)試
遞增式地重構(gòu)代碼
不可重復(fù)
表達(dá)了程序員的意圖
盡可能減少類和方法的數(shù)量篓像。
第13章
并發(fā)防御原則
分離并發(fā)相關(guān)代碼與其他代碼
限制臨界區(qū)數(shù)量
使用數(shù)據(jù)副本避免共享數(shù)據(jù)
線程應(yīng)盡可能地獨(dú)立动知。每個(gè)線程處理一個(gè)客戶端請(qǐng)求,從不共享的源頭接納所有請(qǐng)求數(shù)據(jù)员辩,存儲(chǔ)為本地變量盒粮。
警惕同步方法之間的依賴
避免使用一個(gè)共享對(duì)象的多個(gè)方法
保持同步區(qū)域微小
很難編寫正確的關(guān)閉代碼
測(cè)試線程代碼
偶發(fā)失敗都需要注意奠滑,最好假設(shè)偶發(fā)錯(cuò)誤根本不應(yīng)該存在
不要同時(shí)追蹤非線程缺陷和線程缺陷丹皱。
編寫可插拔的線程代碼,在不同的配置環(huán)境下運(yùn)行
允許線程數(shù)量可調(diào)整
運(yùn)行多余處理器或處理器核心數(shù)量的線程
裝置代碼宋税,增加對(duì)Object.wait() Object.sleep()等方法調(diào)用摊崭,改變代碼執(zhí)行順序測(cè)試并發(fā)代碼中的缺陷。
第14章
毀壞程序的最好方法之一就是以改進(jìn)之名大動(dòng)其結(jié)構(gòu)杰赛。
每次修改都必須保證系統(tǒng)能像以前一樣工作呢簸。
第17章 味道與啟發(fā)
注釋
不恰當(dāng)?shù)男畔?/li>
廢棄的注釋
冗余注釋
注釋代碼
環(huán)境
需要多步才能實(shí)現(xiàn)的構(gòu)建
需要多步才能做到的測(cè)試
函數(shù)
過多地參數(shù)
輸出參數(shù)
用作標(biāo)識(shí)的參數(shù)
死函數(shù)
一般性問題
重復(fù)
不正確的邊界行為。別依賴直覺乏屯,追索每種邊界條件根时,并編寫測(cè)試。
在錯(cuò)誤的抽象層級(jí)上的代碼辰晕。創(chuàng)建分離較高層級(jí)一般性概念與較低層級(jí)細(xì)節(jié)概念的抽象模型啸箫。
基類依賴派生類
信息過多。限制類或模塊中暴露的接口數(shù)量伞芹。
垂直分隔忘苛。 變量和函數(shù)應(yīng)該靠近被使用的地方定義。
前后不一致唱较。命名扎唾、約定保持一致。
人為耦合南缓。 不互相依賴的東西不該耦合胸遇。
特性依戀。類的方法只應(yīng)對(duì)其所屬類中的變量和函數(shù)感興趣汉形,不該垂青其他類中的變量和函數(shù)纸镊。
晦澀的意圖。
位置錯(cuò)誤的權(quán)責(zé)概疆。
不恰當(dāng)?shù)撵o態(tài)方法逗威。靜態(tài)方法應(yīng)當(dāng)只在當(dāng)個(gè)實(shí)體上操作,不在任何特定對(duì)象上操作岔冀。
理解算法凯旭,而不是使用大量的if else
把邏輯依賴改為物理依賴,依賴者模塊不應(yīng)該對(duì)被依賴者模塊有假定,它應(yīng)當(dāng)明確地詢問后者全部信息罐呼。
public class HourlyReporter {
private HourlyReportFormatter formatter;
private List<LineItem> page;
private final int PAGE_SIZE = 55; // 這是假定知道頁(yè)面尺寸鞠柄,是一種邏輯依賴〖挡瘢可以改成getMaxPageSize()的新方法來物理化依賴厌杜。
public HourlyRepoter(HourlyReportFormatter formatter) {}
}
用多態(tài)替代if else
用命名常量替代魔術(shù)數(shù)
準(zhǔn)確。確認(rèn)自己足夠準(zhǔn)確计螺。明確自己為何要這么做夯尽。
封裝條件。把解釋了條件意圖的函數(shù)抽離出來危尿。
避免否定性條件呐萌。
函數(shù)值該做一件事。
掩蔽時(shí)序耦合谊娇。有必要使用時(shí)序耦合時(shí)肺孤,不應(yīng)該掩蔽它。
封裝邊界條件济欢。 把處理邊界條件的代碼集中到一處赠堵。
函數(shù)應(yīng)該只在一個(gè)抽象層級(jí)上。
public String render() throws Exception {
StringBuffer html = new StringBuffer("<hr");
if (size > 0) html.append(" size=\").append(size + 1).append("\");
return html.toString();
}
public String render() throws Exception {
HtmlTag hr = new HtmlTag("hr");
if(extraDashes > 0) hr.addAttribtue("size", hrSize(extraDashes));
return hr.html();
}
在較高抽象層級(jí)的默認(rèn)常量或配置值法褥,不要將它埋藏到較低層級(jí)的函數(shù)中茫叭。
避免傳遞瀏覽。 a.getB().getC()
除非里面有數(shù)據(jù)結(jié)構(gòu)類半等,否則不應(yīng)該傳遞揍愁。
名稱
采用描述性名稱
名稱應(yīng)與抽象層級(jí)相符
無歧義名稱
為較大作用范圍選用較長(zhǎng)名稱
避免編碼
測(cè)試
全面測(cè)試相近的缺陷
測(cè)試失敗的模式有啟發(fā)性
最后編輯于 :2023.07.17 17:53:50
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者