《重構(gòu)》閱讀筆記-代碼的壞味道

決定何時(shí)重構(gòu)庇谆、何時(shí)停止和知道如何重構(gòu)一樣重要!

開發(fā)者必須通過(guò)實(shí)踐培養(yǎng)自己的經(jīng)驗(yàn)和直覺凭疮,培養(yǎng)出自己的判斷力:學(xué)會(huì)判斷一個(gè)類內(nèi)有多少個(gè)實(shí)例變量算是太大饭耳、學(xué)會(huì)判斷一個(gè)函數(shù)內(nèi)有多少行代碼才算太長(zhǎng)。

  1. 重復(fù)代碼(Duplicated Code)
    如果你在一個(gè)以上的地方看到相同的程序結(jié)構(gòu)执解,那么可以肯定:設(shè)法將它們合而為一寞肖,程序會(huì)變得更美好!你需要決定這個(gè)重復(fù)的代碼放在哪里比較合適衰腌,并確保它被安置之后就不會(huì)在別的地方再次出現(xiàn)新蟆。

  2. 過(guò)長(zhǎng)函數(shù)(Long Method)
    程序越長(zhǎng)越難以理解。現(xiàn)代OO語(yǔ)言幾乎完全免去了進(jìn)程內(nèi)的函數(shù)調(diào)用開銷右蕊,因此栅葡,你應(yīng)該積極地分解函數(shù)。我們應(yīng)該遵循原則:每當(dāng)需要以注釋來(lái)說(shuō)明點(diǎn)什么的時(shí)候尤泽,我們就需要把需要說(shuō)明的東西寫進(jìn)一個(gè)獨(dú)立函數(shù)中欣簇,并以其用途(而非實(shí)現(xiàn)手法)命名。如何確定需要提煉哪一段代碼:尋找注釋坯约、條件表達(dá)式熊咽、循環(huán)。

  3. 過(guò)大的類(Large Class)
    如果你發(fā)現(xiàn)一個(gè)類試圖做太多事情闹丐,其內(nèi)部就會(huì)出現(xiàn)很多不相關(guān)的實(shí)例變量横殴,此時(shí)這個(gè)類的職責(zé)就不明確了。

  4. 過(guò)長(zhǎng)參數(shù)列(Long Parameter List)
    太長(zhǎng)的參數(shù)隊(duì)列難以理解,太多參數(shù)的接口對(duì)于使用者來(lái)說(shuō)十分不友好衫仑,而且容易出錯(cuò)梨与。如果可以使用一個(gè)對(duì)象代替參數(shù)列表,那么就應(yīng)該這么做文狱。

  5. 發(fā)散式變化(Divergent Change) VS 霰彈式修改(Shotgun Surgery)
    一旦需要修改粥鞋,我們希望只在系統(tǒng)的一個(gè)地方進(jìn)行修改,否則瞄崇,就屬于兩種非常相似的壞味道的一種:如果某個(gè)類經(jīng)常因?yàn)椴煌脑蛟诓煌牡胤桨l(fā)生變化呻粹,那么Divergent Change就出現(xiàn)了;如果系統(tǒng)每遇到一個(gè)小變化苏研,就需要在多個(gè)不同的類內(nèi)進(jìn)行許多小修改等浊,這屬于Shotgun Surgery。Divergent Change是指“一個(gè)類受多種變化的影響”摹蘑,Shotgun Surgery則指的是“一種變化引發(fā)多個(gè)類的修改”筹燕。

  6. 平行繼承體系(Parallel Inheritance Hierarchies)
    這其實(shí)是Shotgun Surgery的特殊情況——每當(dāng)你為某個(gè)類添加一個(gè)子類,你也必須為它的兄弟類加一個(gè)子類衅鹿。如果你發(fā)現(xiàn)某個(gè)繼承體系的類名稱前綴和另一個(gè)繼承體系的類名稱前綴完全相同撒踪,就屬于這種情況。

  7. 依戀情結(jié)(Feature Envy)
    面向?qū)ο蟮木柙谟冢骸皩?shù)據(jù)和對(duì)數(shù)據(jù)的操作行為包裝在一起”塘安。有一種氣味是:函數(shù)對(duì)某個(gè)類的興趣高過(guò)自己所處的類的興趣糠涛。有很多時(shí)候援奢,我們看到一個(gè)函數(shù)為了計(jì)算某個(gè)值兼犯,從另一個(gè)對(duì)象那兒調(diào)用了幾乎半打的取值函數(shù)。最根本的原則是:將總是一起變化的東西放在一起集漾。

  8. 數(shù)據(jù)泥團(tuán)(Data Clumps)
    你常城星可以在很多地方看到相同的三四項(xiàng)數(shù)據(jù):兩個(gè)類中相同的字段、許多函數(shù)簽名中相同的參數(shù)具篇。這些綁在一起出現(xiàn)的數(shù)據(jù)真應(yīng)該擁有屬于它們自己的對(duì)象纬霞。減少字段和參數(shù)的個(gè)數(shù),當(dāng)然可以去除一些壞味道驱显,但更重要的是:一旦擁有新對(duì)象诗芜,你就有機(jī)會(huì)尋找Feature Envy,這可以幫你指出能夠移至新類中的種種方法埃疫。

  9. 基本類型偏執(zhí)(Primitive Obsession)
    對(duì)象技術(shù)的新手通常不愿意在小任務(wù)上運(yùn)用對(duì)象——例如結(jié)合數(shù)值和幣種的Money類伏恐、由一個(gè)起始值和一個(gè)結(jié)束值構(gòu)成的Range類、電話號(hào)碼或郵政號(hào)碼等的特殊字符串栓霜。

  10. switch語(yǔ)句(Switch Statements)
    從本質(zhì)上講翠桦,switch語(yǔ)句的問題在于重復(fù),面向?qū)ο蟮亩鄳B(tài)特性可以優(yōu)雅地解決這個(gè)問題胳蛮。如果你只是在單一函數(shù)內(nèi)有些選擇事例销凑,那么用多態(tài)就屬于殺雞用牛刀了丛晌,這種情況下Replace Parameter with Explicit Methods是個(gè)不錯(cuò)的選擇,如果你的選擇之一是null斗幼,記得使用Introduce Null Object澎蛛。

  11. 多余的類(Lazy Class)
    你所創(chuàng)建的每一個(gè)類,都得有人去理解它孟岛、維護(hù)它瓶竭,這些工作都是要花錢的。如果一個(gè)類的所得不值得其身價(jià)渠羞,就應(yīng)該消除這個(gè)類斤贰。

  12. 過(guò)度設(shè)計(jì)(Speculative Generality)
    當(dāng)有人說(shuō)“噢,我想我們有一天需要做這個(gè)事情”次询,并因此而企圖以各種各樣的鉤子和特殊情況來(lái)處理一些非必要的事情荧恍,這種壞味道就出現(xiàn)了。軟件設(shè)計(jì)不可過(guò)度設(shè)計(jì)屯吊,否則會(huì)使得系統(tǒng)難以理解和維護(hù)送巡。

  13. 令人迷惑的暫時(shí)字段(Temporary Field)
    有時(shí)你會(huì)看到這樣的現(xiàn)象:類內(nèi)的某個(gè)實(shí)例變量?jī)H為某種特定情況而設(shè)。這樣的代碼不易理解盒卸,因?yàn)橥ǔUJ(rèn)為對(duì)象在所有時(shí)候都需要它的所有變量骗爆。

  14. 過(guò)度耦合的消息鏈(Message Chains)
    如果你看到用戶向一個(gè)對(duì)象請(qǐng)求另一個(gè)對(duì)象,然后再向后者請(qǐng)求另一個(gè)對(duì)象蔽介,然后再請(qǐng)求另一個(gè)對(duì)象……這就是消息鏈摘投。實(shí)際代碼中你看到的可能是一長(zhǎng)串getXXX()調(diào)用,意味著客戶代碼將與查找目標(biāo)對(duì)象過(guò)程中的導(dǎo)航結(jié)構(gòu)緊密耦合虹蓄,一旦對(duì)象間的關(guān)系發(fā)生任何變化犀呼,客戶端就會(huì)受到影響。

  15. 中間人(Middle Man)
    對(duì)象的基本特征之一是封裝——對(duì)外部世界隱藏其內(nèi)部細(xì)節(jié)薇组。封裝往往伴隨著委托外臂,比如你問主管是否有時(shí)間參加一個(gè)會(huì)議,他就把這個(gè)消息“委托”給他的記事簿律胀,然后才能回答你——你沒有必要這位主管到底是使用傳統(tǒng)記事簿或電子記事簿或秘書來(lái)記錄自己的約會(huì)宋光。但是,不要過(guò)度使用委托——你也許會(huì)看到某個(gè)類有一半接口都委托給其他類炭菌。

  16. 狎昵關(guān)系(Inappropriate Intimacy)
    類與類之間過(guò)分緊密的關(guān)系必須拆散——可以引入第三方類或者利用委托罪佳。

  17. 異曲同工的類(Alternative Classes with Different Interfaces)
    如果兩個(gè)函數(shù)做同一件事,卻有著不同的簽名娃兽,請(qǐng)運(yùn)用Rename Method根據(jù)它們的用途重新命名菇民。但這往往不夠,請(qǐng)反復(fù)運(yùn)用Move Method將某些行為移入類,知道這兩個(gè)函數(shù)的協(xié)議一致為止第练。如果你必須移動(dòng)大量代碼才可以完成這個(gè)工作阔馋,那還不如直接構(gòu)建一個(gè)父類。

  18. 不完美的庫(kù)類(Incomplete Library Class)
    復(fù)用常常被認(rèn)為是面向?qū)ο蠹夹g(shù)的終極目標(biāo)娇掏。很多第三方庫(kù)提供的接口經(jīng)常不能恰如其分得滿足我們的需求呕寝,這時(shí)候就需要對(duì)第三方接口做一層轉(zhuǎn)換,或者給它添加一定的行為婴梧。

  19. 數(shù)據(jù)類(Data Class)
    所謂Data Class下梢,指的是:這種類擁有一些字段,以及用于訪問(讀塞蹭、寫)的函數(shù)孽江,除此之外啥都沒有。這樣的類只是一種不會(huì)說(shuō)話的數(shù)據(jù)容器番电,它們一定被其他類過(guò)分細(xì)碎得控制著岗屏。
    Data Class就像小孩子,作為一個(gè)起點(diǎn)很好漱办,但若要讓它們像成熟的對(duì)象那樣參與整個(gè)系統(tǒng)的工作这刷,它們就必須承擔(dān)一定責(zé)任。但是娩井,在Spring框架開發(fā)中暇屋,我們經(jīng)常需要定義很多domain對(duì)象。

  20. 被拒絕的遺囑(Refused Request)
    子類應(yīng)該繼承超類的函數(shù)和數(shù)據(jù)洞辣,但如果它們不想或者不需要繼承咐刨,又該怎么辦呢?按照傳統(tǒng)說(shuō)法屋彪,這就意味著繼承體系的設(shè)計(jì)錯(cuò)誤所宰。你需要為這個(gè)子類新建一個(gè)兄弟類绒尊,然后讓父類只包括兩個(gè)子類共享的部分畜挥。
    一般而言,這就足夠了婴谱,但是如果子類不愿意支持超類提供的接口蟹但,則說(shuō)明不能使用繼承處理,應(yīng)該使用委托谭羔。

  21. 過(guò)多的注釋(Comments)
    常常會(huì)有這樣的情況:你看到一段代碼有著長(zhǎng)長(zhǎng)的注釋华糖,然后發(fā)現(xiàn),這些注釋之所以存在乃是因?yàn)榇a很糟糕瘟裸。當(dāng)你需要些注釋時(shí)客叉,要先嘗試重構(gòu)下代碼,爭(zhēng)取讓代碼擁有自說(shuō)明性。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末兼搏,一起剝皮案震驚了整個(gè)濱河市卵慰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌佛呻,老刑警劉巖裳朋,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異吓著,居然都是意外死亡鲤嫡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門绑莺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)暖眼,“玉大人,你說(shuō)我怎么就攤上這事纺裁“盏矗” “怎么了?”我有些...
    開封第一講書人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵对扶,是天一觀的道長(zhǎng)区赵。 經(jīng)常有香客問我,道長(zhǎng)浪南,這世上最難降的妖魔是什么笼才? 我笑而不...
    開封第一講書人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮络凿,結(jié)果婚禮上骡送,老公的妹妹穿的比我還像新娘。我一直安慰自己絮记,他們只是感情好摔踱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著怨愤,像睡著了一般派敷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上撰洗,一...
    開封第一講書人閱讀 51,610評(píng)論 1 305
  • 那天篮愉,我揣著相機(jī)與錄音,去河邊找鬼差导。 笑死试躏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的设褐。 我是一名探鬼主播颠蕴,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼泣刹,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了犀被?” 一聲冷哼從身側(cè)響起项玛,我...
    開封第一講書人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎弱判,沒想到半個(gè)月后襟沮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡昌腰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年开伏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片遭商。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡固灵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出劫流,到底是詐尸還是另有隱情巫玻,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布祠汇,位于F島的核電站仍秤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏可很。R本人自食惡果不足惜诗力,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望我抠。 院中可真熱鬧苇本,春花似錦、人聲如沸菜拓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)纳鼎。三九已至俺夕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間喷橙,已是汗流浹背啥么。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工登舞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留贰逾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓菠秒,卻偏偏與公主長(zhǎng)得像疙剑,于是被迫代替她去往敵國(guó)和親氯迂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 何時(shí)重構(gòu)言缤、何時(shí)停止重構(gòu)學(xué)會(huì)判斷一個(gè)類內(nèi)有多少實(shí)例變量算是太大嚼蚀、一個(gè)函數(shù)內(nèi)有多少行代碼算太長(zhǎng) 下面是對(duì)各種壞味道的簡(jiǎn)...
    每天學(xué)點(diǎn)編程閱讀 1,500評(píng)論 0 4
  • 《重構(gòu)》讀書筆記 總覽 第一部分 第一章從實(shí)例程序出發(fā),展示設(shè)計(jì)的缺陷管挟,對(duì)其重構(gòu)可以了解重構(gòu)的過(guò)程和方法轿曙。 第二部...
    白樺葉閱讀 2,398評(píng)論 2 5
  • 如果是尿布抽了,就換掉它僻孝。 —— Beck奶奶 3.1 Duplicated Code 最單純的Dup...
    hklbird閱讀 843評(píng)論 0 0
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法导帝,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法穿铆,繼承相關(guān)的語(yǔ)法您单,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 31,639評(píng)論 18 399
  • 下了三天兩夜的雪總算是停了荞雏,難得的圓月虐秦。可風(fēng)還是好大凤优。本就身體不好的紅可怎么在夜里走出這山悦陋。 ...
    桑小晨7閱讀 478評(píng)論 2 2