前言:本文只摘要了24種代碼「壞味道」最核心的要點,也不準備貼代碼示例剿干,是因為Sheldon自己在寫的過程中蜂怎,自然就想起了很多自己寫的代碼「壞味道」。所以希望大家在看文章的過程中多回憶自己的代碼置尔,而不是被冗長的文字和大量代碼示例分散注意力杠步。
1. 神秘命名
命名是編程中最難的兩件事之一。正因為如此榜轿,修改命名可能是最常用的重構(gòu)方法幽歼。
如果你發(fā)現(xiàn)改名很難,那就說明代碼設計有問題谬盐。
當我們不能給一個模塊甸私,一個對象,一個函數(shù)飞傀,甚至一個變量找到合適名稱的時候皇型,往往說明我們對問題的理解還不夠透徹,需要重新去挖掘問題的本質(zhì)砸烦,對問題域進行重新分析和抽象弃鸦。
2. 重復代碼
同一類的兩個函數(shù)含有相同的表達式,就應該提煉幢痘。
3. 過長函數(shù)
活得最長寡键,最好的程序,其中函數(shù)一般都很短雪隧。
如果你覺得需要寫注釋西轩,大部分情況就代表這個東西需要寫進一個獨立的函數(shù)里面,然后根據(jù)用途來命名比較好脑沿。
條件表達式和循環(huán)往往也是提煉函數(shù)的信號藕畔。
4. 過長參數(shù)列表
使用類可以有效的縮短參數(shù)列表。如果多個函數(shù)有同樣的幾個參數(shù)庄拇,引入一個類就尤為有意義注服。
5. 全局數(shù)據(jù)
全局數(shù)據(jù)仍然是最刺鼻的壞味道之一。它的問題是措近,全局數(shù)據(jù)在任何地方都可以被修改溶弟。
所以正確的做法是將全局數(shù)據(jù)封裝起來,用函數(shù)將其包起來瞭郑,這樣就知道那些地方修改了它辜御。
有少量的全局數(shù)據(jù)或者無妨,但數(shù)量越多屈张,處理難度就會指數(shù)上升擒权。(良藥與毒藥的區(qū)別在于劑量)
6. 可變數(shù)據(jù)
核心是縮小作用域袱巨。
可以通過封裝變量來確保所有數(shù)據(jù)更新操作都通過很少幾個函數(shù)來進行,使其更容易被監(jiān)控碳抄。
7. 發(fā)散式變化
發(fā)散式變化指某個模塊因為不同的原因在不同的方向上發(fā)生變化愉老。
每次只關心一個上下文。
找到引起發(fā)散式變化的原因剖效,將它拆分出來嫉入。
8. 霰彈式修改
在每次修改的時候,應該只修改一處璧尸,而不是到處的修改咒林。因為一個需求,需要修改3處代碼逗宁,那么這就需要思考,這3處代碼是否應該抽離出來梦湘。
一個常用的策略就是使用內(nèi)聯(lián)(inline)重構(gòu)代碼把本不該分散的邏輯拽回一處瞎颗。
9. 依戀情結(jié)
模塊化,力求代碼分出區(qū)域捌议,最大化區(qū)域內(nèi)部交互哼拔,最小化區(qū)域間交互。
如果兩個模塊交互頻繁瓣颅,它們應該合并在一起倦逐。
10. 數(shù)據(jù)泥團
如果在多個類中,出現(xiàn)了很多相同項的數(shù)據(jù)宫补,你需要想想是否要通過將數(shù)據(jù)提煉成類檬姥,來抽離出一個獨立對象。
建議新建類而非簡單的結(jié)構(gòu)體粉怕。
11. 基本類型偏執(zhí)
很多程序員不愿意創(chuàng)建對自己的問題域有用的基本類型健民,如錢,坐標贫贝,范圍等秉犹。
比如有程序員用字符串來表示電話號碼,實際上你應該抽象出來一個電話號碼對象稚晚。
12. 重復的switch
盡量使用多態(tài)而非switch崇堵。
13. 循環(huán)語句
我們應該用管道操作(如filter和map)來替代循環(huán),這樣能更快的看清被處理的元素和處理他們的動作客燕。
14. 冗贅的元素
能簡單的代碼鸳劳,盡量簡單。未來變復雜的時候也搓,再去考慮它棍辕。
15. 夸夸其談的通用性
同上暮现,能簡單的代碼,盡量簡單楚昭。通用性栖袋?過早的優(yōu)化是萬惡之源
16. 臨時字段
臨時字段指內(nèi)部某個字段僅為某種特定情況而設。
臨時的字段不應該存在抚太。你需要給他們搬個新家塘幅,把所有和臨時變量相關的代碼搬至那里。
17. 過長的消息鏈
如果你看到用戶向一個對象請求另一個對象尿贫,然后再向后者請求另一個對象电媳,然后再請求另一個對象,這就是消息鏈庆亡。
消息鏈意味著客戶端會耦合消息鏈的查找過程匾乓。應該將查找過程獨立出一個函數(shù)。
18. 中間人
委托函數(shù)過多時又谋,減少委托拼缝,移除中間人,讓調(diào)用者直接訪問目標類進行操作彰亥。
19. 內(nèi)幕交易
減少模塊之間頻繁的數(shù)據(jù)交換咧七,并把這種交換放到明面上。
20. 過大的類
當一個類代碼行數(shù)太多或者功能職責太多的時候任斋,拆掉它继阻。
兩種拆分方法:
提取新類,當大類的部分行為可以分解為一個單獨的組件废酷,則可以使用提取類的方式拆分瘟檩。
提取子類,當大類的部分行為可以以不同的方式實現(xiàn)或在極少數(shù)情況下使用澈蟆,則可以使用提取子類方式拆分芒帕。
21. 異曲同工的類
兩個類有著相同的功能,但方法名稱不同丰介。
重命名方法背蟆,并去除掉不必要的重復代碼。
22. 純數(shù)據(jù)類
純數(shù)據(jù)類常常意味著行為被放在了錯誤的地方哮幢。處理數(shù)據(jù)的行為應該從客戶端移至純數(shù)據(jù)類中带膀。
23. 被拒絕的遺贈
如果子類復用了父類的實現(xiàn),就應該支持父類的接口橙垢。
24. 注釋
注釋是提示你垛叨,這個地方該重構(gòu)啦。
如果你覺得需要寫注釋的時候,請先重構(gòu)嗽元,試著讓所有注釋都變得多余敛纲。