Part 1 實例
- 將大的函數(shù)拆分成小函數(shù) (快捷鍵 command+option+M)
2.變量以及方法命名
3.函數(shù)應(yīng)該放在它所使用的數(shù)據(jù)所屬的對象內(nèi)(這個方法用了哪些數(shù)據(jù)鸡捐,就放在數(shù)據(jù)對應(yīng)的類下面)
4.盡量減少臨時變量
5.多態(tài)取代switch
Part 2 概念
1.重構(gòu)和新增功能不同時進行
2.何時重構(gòu):
1》.隨時重構(gòu),當你想做某個功能,重構(gòu)可以讓這個功能更方便癞揉,或者說做的更好
2》.第三次寫重復(fù)代碼就可以重構(gòu)
3》.添加功能的時候
4》.bug的時候
5》.Code Review的時候
Part 3 代碼的壞味道
1.duplicated code
2.long Method :
解決方式: 1. 提煉 注釋的地方
2. 提煉循環(huán)
3.Large Class
4.Long Parameter List
5.Divergent Change (發(fā)散式變化) ——一個類受多個變化影響
6.Shotgun Surgery (霰彈式變化) ——一種變化影響多個類修改
7.Feature Envy (依戀情節(jié)) —— 一個類使用了多份數(shù)據(jù)渗勘,就放在用的數(shù)據(jù)最多的那個類里
8.Data Clumps (數(shù)據(jù)泥團)
9.Primitive obsession(基本類型偏執(zhí))
10.switch statement
解決方式:多態(tài)
11.Parallel Inheritance Hierarchies (平行繼承體系)—— 當給某個類增加了子類呼胚,必須發(fā)給其他類也增加子類
解決方式:讓一個繼承體系實例引用另一個繼承體系的實例
12.Lazy Class(冗贅類)—— 就是意義不大的類
13.Speculative Generality(夸夸其談未來性)—— 過多設(shè)計導(dǎo)致的東西
14.Temporary Field
15.message Chain(過度耦合的消息鏈)
16.middle man(中間人)—— 過度委托
解決方式:1.去掉過度委托,直接調(diào)用
2. 如果middle man 有其他行為孝扛,可以優(yōu)化成子類
- Inappropriate Intimacy (狎昵關(guān)系)——類之間的過于依賴
18.Alternative Classes with Different Interfaces(異曲同工的類)
解決方式:1.Extract Superclass
19.Incomplete Library Class (不完美的庫類)
20.Data CLass(純稚的數(shù)據(jù)類)
21.refused bequest(被拒絕的遺贈) - Comments(過多的注釋)
解決方式:1.好的方法命名代替注釋
2.introduce assertion
Part 4 關(guān)于測試的一些思考
1.開發(fā)應(yīng)該專注于單元測試,假設(shè)其他包都正常幽崩,對每個包單獨測試
2.當功能測試出現(xiàn)bug的時候苦始,不僅僅應(yīng)該修改bug,還需要用一個單元測試來暴露這個bug
3.尋找邊界條件
Part 6
1.Extract Method
- Inline Method
- Inline Temp(內(nèi)聯(lián)臨時變量)——用方法代替臨時變量
eg: 1. if中的條件判斷 應(yīng)該提煉成一個方法 - replace temp with query(以查詢?nèi)〈R時變量)
eg:臨時變量只被賦值一次(如何檢查:1.將目標臨時對象聲明為final) - Introduce Explaining Variable(引入解釋性變量)—— 復(fù)雜的表達式用臨時變量代替(但是也可以用Extract Method,區(qū)別:局部變量使用多慌申,提取成本較大就用Introduce Explaining Variable)
- Split Temporary Variable(分解臨時變量)—— 除了循環(huán)用的臨時變量陌选,一般的臨時變量應(yīng)該只被賦值一次,如果有多次蹄溉,需要判斷意義是否一樣咨油,不一樣應(yīng)該用一個新的臨時變量去裝載
- Remove Assignments to Parameters(移除對參數(shù)的賦值)—— 用臨時變量去裝這個賦值
- Replace Method with Method Object —— 把一個復(fù)雜函數(shù)(用了太多臨時變量的函數(shù))提取成一個class< A class >, 把所有臨時變量都放入final 字段里柒爵。然后再原來方法調(diào)用的地方役电,使用委托的方式,讓新的類的方法被調(diào)用<eg:new A().getContant()>, 然后就可以在A class 里面進行Extract Method
- Substitute Algorithm(替換算法)—— 將復(fù)雜的算法 用簡單的算法餐弱,更加易讀的算法代替
Part 7
- move Method—— 當一個類的行為過多宴霸,或者一個類和另外一個類高度耦合,就可以使用這個方式
- move field
- Extract Class—— 根據(jù)不同的責(zé)任劃分類
- Inline Class
- Hide delegate(隱藏委托關(guān)系)—— 對外部隱藏某個調(diào)用關(guān)系
- Remove Middle Man —— 移除過多的委托關(guān)系(出現(xiàn)大量委托關(guān)系的時候膏蚓,可以直接暴露相關(guān)對象)
- Introduce Foreign Method(引入外加函數(shù))—— 當出現(xiàn)大量對某個函數(shù)的調(diào)用使用同一個值瓢谢,且參數(shù)較多的情況,可以將這個調(diào)用過程Extract Method 驮瞧,這個函數(shù)叫做被調(diào)用函數(shù)的外加函數(shù)
- Introduce Local extension(引入本地擴展)—— 當 外加函數(shù)較多的時候氓扛,應(yīng)該使用Introduce Local extension,有2種做法:① 子類 繼承论笔,super() ② 包裝類 使用 委托
Part 8
- Self Encapsulate Field(自封裝字段)—— 在類內(nèi)部也使用使用get set方法獲取字段的值
- Replace Data Value with Object(以對象取代數(shù)據(jù)值)—— 數(shù)據(jù)對象復(fù)雜采郎,或者數(shù)據(jù)關(guān)系較多,應(yīng)該封裝成一個對象
- Change Value to Reference (將值對象改為引用對象)
- Change Reference to Value (將引用對象改為值對象)
- Replace Array with Object —— 數(shù)組應(yīng)該用于“以某種順序容納一組相似對象”狂魔,如果涉及到一個東西的多個屬性蒜埋,多個對象 就應(yīng)該改為object
- Duplicate Observe Data (復(fù)制被監(jiān)視的數(shù)據(jù))
- Change Unidirectional Association to Bidirectional(將單項關(guān)聯(lián)改為雙向關(guān)聯(lián))
- Change Bidirectional Association to Unidirectional(將雙向關(guān)聯(lián)改為單項關(guān)聯(lián))
- Replace Magic Number with Symbolic Constant(用字面常亮取代魔法數(shù))—— 就是用 static final + 類型+ 名稱 = 魔法數(shù)
- Encapsulate Field(封裝字段)—— 把public 字段設(shè)置為private,使用get set函數(shù)公開出去
- Encapsulate Collection(封裝集合)—— 不要把整個集合公開出去最楷,只是把需要公開的 add 方法公開出去整份,比如 新增集合里的一個元素待错,對外的應(yīng)該只有
public void addCourse(object obj){
courses.add(obj);
}
只會把obj 扔出去,
- Replace Record with Data Class(以數(shù)據(jù)類代替記錄)
- Replace Type Code with Class(以類取代類型碼)
- Replace Type Code with Subclasses —— 面對swich 這種判斷需要的就可以把type code 使用子類來重構(gòu)
- Replace Type Code with State/Strategy
- Replace Subclass with Fields(用字段取代子類)—— 子類中如只有一個常量函數(shù)烈评,那么久沒有必要用子類火俄。可以直接用字段來代替
Part 9
- Decompose Conditional(分解條件表達式)—— 把 if讲冠,then瓜客, else中的條件語句提取出來
- Consolidate Condition Expression(合并條件表達式)—— 就是把結(jié)果一致的條件放在一起
- Consolidate Duplicate Conditional Fragments(合并重復(fù)的條件片段)—— 有共同的執(zhí)行提取出來
- Remove Control Flag—— 用 break or continue 代替
- Replace Nested Conditional with Guard Clauses(以衛(wèi)語句取代嵌套條件表達式)—— 衛(wèi)語句:單獨的某個檢查,如果為真立刻返回竿开。檢查提前谱仪,對特殊情況單獨處理
- Replace Conditional with Polymorphism(以多態(tài)取代條件表達式)—— 繼承代替switch
- Introduce Null Object (引入null對象)—— 把返回null的地方用一個空對象代替, 這個空對象可以處理默認值
- Introduce Assertion(引入斷言)—— 作為調(diào)試和輔助開發(fā),提前判斷結(jié)果德迹,最后會刪除
Part 10
- Rename Method —— 良好的命名方式
- Add Parameter
- Remove Parameter
- Separate Query from Modifier (分離查詢函數(shù)和修改函數(shù))—— 把修改對象的方法和僅是查詢數(shù)據(jù)的方法分開
- Parameterize Method (令函數(shù)攜帶參數(shù))—— 用參數(shù)減少重復(fù)代碼
- Replace Parameter with Explicit Method (用明確函數(shù)取代參數(shù))—— 用多個函數(shù)取代 帶有多個意義的單個函數(shù)芽卿,當某個函數(shù)出現(xiàn)大量if else類似的判斷就需要用這種方式重構(gòu)
- Preserve Whole Object(保持對象完整)—— 當某個函數(shù)大量用到調(diào)用方的某個對象的參數(shù)的時候,應(yīng)該使用對象胳搞,而不是拆解出來的多個值
- Replace Parameter with Methods(用函數(shù)取代參數(shù))—— 當某個參數(shù)是從其他函數(shù)取得的時候,應(yīng)該直接在方法函數(shù)內(nèi)部自行調(diào)用称杨,不要從參數(shù)傳入
- Introduce Parameter Object(引入?yún)?shù)對象)—— 當某一組參數(shù)被大量傳遞肌毅,應(yīng)該用個類把他們包裹起來傳遞
- Remove Setting Method (移除設(shè)值函數(shù))—— 如果不對外公開set方法,該值僅通過構(gòu)造方法設(shè)值有效姑原, 就移除set參數(shù)
- Hide Method—— 不必要的函數(shù)設(shè)置為private
- Replace Constructor with Factory Method(工廠模式代替構(gòu)造函數(shù))—— Class.forName
- Encapsulate Downcast(封裝向下轉(zhuǎn)型)—— 將向下轉(zhuǎn)型的動作移到方法里
- Replace Error Code with Exception(用異常取代錯誤碼)
- Replace Exception with Test(用測試取代異常)—— 異常應(yīng)該是用于罕見悬而,異常的行為,而不是使用在條件檢查的地方锭汛,把某些正常行為的處理笨奠,使用條件語句放在前面
Part 11
- Pull Up Field(字段上移)—— 子類公有的字段可以移到超類
- Pull Up Method(函數(shù)上移)—— 子類中完全相同結(jié)果的函數(shù)可以移到超類
- Pull Up Constructor Body (構(gòu)造函數(shù)本體上移) —— 子類中相同的構(gòu)造函數(shù)移動到超類
- Push Down Method (函數(shù)下移)—— 當超類中的某個函數(shù)只于部分子類相關(guān)
- Push Down Field(字段下移)—— 當超類中某個字段只于特定子類相關(guān)
- Extract Subclass (提煉子類)—— 某些特性 只被部分實例使用,應(yīng)該移到子類中去
- Extract Superclass (提煉超類)—— 兩個類有相似特性類唤殴,可以提煉出公共部分般婆,移到超類里去
- Extract Interface (提煉接口)—— 多個類提供相同功能的時候(比如租借接口,然后電腦和磁帶實現(xiàn)該接口朵逝,提供不同的計算方式)
- Collapse Hierarchy (折疊繼承體系)—— 超類和子類區(qū)別不大的時候蔚袍,應(yīng)該合并
- Form Template Method (塑造模板函數(shù))—— 就是多個類流程一致,但是每個流程實現(xiàn)方式不一致的時候配名,用 ’模板方法模式‘ 代替(父類規(guī)定一個invoke 函數(shù)啤咽,和其他抽象函數(shù),子類實現(xiàn)不同的抽象函數(shù))
- Replace Inheritance with Delegate(委托取代繼承)—— 子類只使用超類中的一部分數(shù)據(jù)渠脉,而且不需要繼承的數(shù)據(jù)
- Replace Delegate with Inheritance(繼承取代委托)—— 兩個類之間屬于委托關(guān)系宇整,但是大部分是簡單的委托函數(shù),類似直接調(diào)用被委托的類的函數(shù)(但是如果沒有使用到受托類的所有函數(shù)就應(yīng)不應(yīng)該使用該方法)
Part 12
- Tease Apart Inheritance(梳理并分解繼承體系)
- Convert Procedural Design to Objects(將過程化設(shè)計轉(zhuǎn)為對象設(shè)計)
- Separate Domain from Presentation (將領(lǐng)域和表述/顯示分離)
- Extract Hierarchy (提煉繼承體系)