代碼重構(gòu)

一携丁、為什么要代碼重構(gòu)(Refactoring)

在不改變系統(tǒng)功能的情況下,改變系統(tǒng)的實(shí)現(xiàn)方式谆甜。為什么要這么做?投入精力不用來滿足客戶關(guān)心的需求集绰,而是僅僅改變了軟件的實(shí)現(xiàn)方式规辱,這是否是在浪費(fèi)客戶的投資呢?

代碼重構(gòu)的重要性要從軟件的生命周期說起栽燕。軟件不同與普通的產(chǎn)品罕袋,他是一種智力產(chǎn)品,沒有具體的物理形態(tài)纫谅。一個(gè)軟件不可能發(fā)生物理損耗炫贤,界面上的按鈕永遠(yuǎn)不會因?yàn)榘磩哟螖?shù)太多而發(fā)生接觸不良。那么為什么一個(gè)軟件制造出來以后付秕,卻不能永遠(yuǎn)使用下去呢兰珍?

對軟件的生命造成威脅的因素只有一個(gè):需求的變更。一個(gè)軟件總是為解決某種特定的需求而產(chǎn)生询吴,時(shí)代在發(fā)展掠河,客戶的業(yè)務(wù)也在發(fā)生變化亮元。有的需求相對穩(wěn)定一些,有的需求變化的比較劇烈唠摹,還有的需求已經(jīng)消失了爆捞,或者轉(zhuǎn)化成了別的需求。在這種情況下勾拉,軟件必須相應(yīng)的改變煮甥。

考慮到成本和時(shí)間等因素,當(dāng)然不是所有的需求變化都要在軟件系統(tǒng)中實(shí)現(xiàn)藕赞。但是總的說來成肘,軟件要適應(yīng)需求的變化,以保持自己的生命力斧蜕。

這就產(chǎn)生了一種糟糕的現(xiàn)象:軟件產(chǎn)品最初制造出來双霍,是經(jīng)過精心的設(shè)計(jì),具有良好架構(gòu)的批销。但是隨著時(shí)間的發(fā)展洒闸、需求的變化,必須不斷的修改原有的功能均芽、追加新的功能丘逸,還免不了有一些缺陷需要修改。為了實(shí)現(xiàn)變更骡技,不可避免的要違反最初的設(shè)計(jì)構(gòu)架鸣个。經(jīng)過一段時(shí)間以后,軟件的架構(gòu)就千瘡百孔了布朦。bug越來越多囤萤,越來越難維護(hù),新的需求越來越難實(shí)現(xiàn)是趴,軟件的構(gòu)架對新的需求漸漸的失去支持能力涛舍,而是成為一種制約。最后新需求的開發(fā)成本會超過開發(fā)一個(gè)新的軟件的成本唆途,這就是這個(gè)軟件系統(tǒng)的生命走到盡頭的時(shí)候富雅。

代碼重構(gòu)就能夠最大限度的避免這樣一種現(xiàn)象。系統(tǒng)發(fā)展到一定階段后肛搬,使用重構(gòu)的方式没佑,不改變系統(tǒng)的外部功能,只對內(nèi)部的結(jié)構(gòu)進(jìn)行重新的整理温赔。通過重構(gòu)蛤奢,不斷的調(diào)整系統(tǒng)的結(jié)構(gòu),使系統(tǒng)對于需求的變更始終具有較強(qiáng)的適應(yīng)能力。

二啤贩、通過代碼重構(gòu)可以達(dá)到以下的目標(biāo)
2.1 持續(xù)偏糾和改進(jìn)軟件設(shè)計(jì)

重構(gòu)和設(shè)計(jì)是相輔相成的待秃,它和設(shè)計(jì)彼此互補(bǔ)。有了重構(gòu)痹屹,你仍然必須做預(yù)先的設(shè)計(jì)章郁,但是不必是最優(yōu)的設(shè)計(jì),只需要一個(gè)合理的解決方案就夠了志衍,如果沒有重構(gòu)暖庄、程序設(shè)計(jì)會逐漸腐敗變質(zhì),愈來愈像斷線的風(fēng)箏足画,脫韁的野馬無法控制雄驹。重構(gòu)其實(shí)就是整理代碼,讓所有帶著發(fā)散傾向的代碼回歸本位淹辞。

2.2 使代碼更易為人所理解

軟件的生命周期往往需要多批程序員來維護(hù),我們往往忽略了這些后來人俘侠。為了使代碼容易被他人理解象缀,需要在實(shí)現(xiàn)軟件功能時(shí)做許多額外的事件,如清晰的排版布局爷速,簡明扼要的注釋央星,其中命名也是一個(gè)重要的方面。一個(gè)很好的辦法就是采用暗喻命名惫东,即以對象實(shí)現(xiàn)的功能的依據(jù)莉给,用形象化或擬人化的手法進(jìn)行命名,一個(gè)很好的態(tài)度就是將每個(gè)代碼元素像新生兒一樣命名廉沮,也許筆者有點(diǎn)命名偏執(zhí)狂的傾向颓遏,如能榮此雅號,將深以此為幸滞时。

對于那些讓人充滿迷茫感甚至誤導(dǎo)性的命名叁幢,需要果決地、大刀闊斧地整容坪稽,永遠(yuǎn)不要手下留情曼玩!

2.3 幫助發(fā)現(xiàn)隱藏的代碼缺陷

重構(gòu)代碼時(shí)逼迫你加深理解原先所寫的代碼。筆者常有寫下程序后窒百,卻發(fā)生對自己的程序邏輯不甚理解的情景酥泛,曾為此驚悚過,后來發(fā)現(xiàn)這種癥狀居然是許多程序員橙鹦牛患的"感冒"逆航。當(dāng)你也發(fā)生這樣的情形時(shí),通過重構(gòu)代碼可以加深對原設(shè)計(jì)的理解,發(fā)現(xiàn)其中的問題和隱患窟她,構(gòu)建出更好的代碼陈症。

2.4 從長遠(yuǎn)來看,有助于提高編程效率

當(dāng)你發(fā)現(xiàn)解決一個(gè)問題變得異常復(fù)雜時(shí)震糖,往往不是問題本身造成的录肯,而是你用錯(cuò)了方法,拙劣的設(shè)計(jì)往往導(dǎo)致臃腫的編碼吊说。

改善設(shè)計(jì)论咏、提高可讀性、減少缺陷都是為了穩(wěn)住陣腳颁井。良好的設(shè)計(jì)是成功的一半厅贪,停下來通過重構(gòu)改進(jìn)設(shè)計(jì),或許會在當(dāng)前減緩速度雅宾,但它帶來的后發(fā)優(yōu)勢卻是不可低估的养涮。

三、哪些情況需要考慮代碼重構(gòu)

3.1 臃腫的類

類之所以會臃腫眉抬,是因?yàn)殚_發(fā)者缺乏對最基本的編碼原則贯吓,即“單一職責(zé)原則”(SRP)的理解。這些類往往會變得很臃腫蜀变,是由于不同的且在功能上缺少關(guān)聯(lián)的方法都放在了相同的類里面悄谐。

3.2 長方法

方法之所以會變得很長主要是有以下幾個(gè)原因:

  • 1: 許多沒有關(guān)聯(lián)性的、功能復(fù)雜的模塊的代碼都放在相同的方法內(nèi)库北。這主要是開發(fā)者缺乏SRP的概念
  • 2: 多種條件都放在同一個(gè)方法內(nèi)爬舰,這在長方法內(nèi)經(jīng)常會發(fā)生的。這是由于缺乏McCabe代碼復(fù)雜度和SRP的概念的比較寒瓦。
3.3 大量的傳參

我經(jīng)常遇到這幾種情況情屹,一些方法跟另一些方法進(jìn)行交互,或者調(diào)用另一些方法的時(shí)候傳入大量的參數(shù)孵构。這就會出現(xiàn)如果更改了其中一個(gè)參數(shù)屁商,就得在多個(gè)方法內(nèi)進(jìn)行更改。

3.4 常量值無處不在

經(jīng)常會發(fā)現(xiàn)開發(fā)者(尤其是新手)會使用一些具有明確含義的常量值(主要是魔鬼數(shù)字)颈墅,但沒有給它們賦予合適的常量變量蜡镶。這會降低代碼的可讀性和可理解性。

3.5 模糊的方法名

許多時(shí)候恤筛,以下取的方法名會影響代碼的可讀性和可理解性:

  • 1: 模糊的不具有任何意義的方法名
  • 2: 技術(shù)性的官还,卻沒有提及相關(guān)領(lǐng)域的名稱

四、重構(gòu)的方法

4.1 提取類/抽離方法

正如上面提到的毒坛,像“臃腫的類”(一個(gè)類提供了本該有幾個(gè)類提供的功能)這種代碼異味應(yīng)該將原有類中的方法和屬性移動到適當(dāng)數(shù)目的新類中去望伦。舊類中對應(yīng)新類的方法和屬性應(yīng)該被移除林说。另外,有時(shí)候一些類過于臃腫是因?yàn)樗吮黄渌愂褂帽緫?yīng)該是其他類的成員方法的成員方法屯伞。這些方法也應(yīng)該被遷移到合適的類中腿箩。

4.2 提取方法

像上面提到的“過長的方法”這種代碼異味可以通過從舊方法中提取代碼到一個(gè)或多個(gè)新方法中消除。

4.3 分離條件

許多時(shí)候劣摇,一個(gè)方法很長是因?yàn)榘脦讉€(gè)分支語句(if-else)珠移。這些分支條件可以被提取和移動到幾個(gè)單獨(dú)的方法中。這確實(shí)能大大改善代碼可讀性和可理解性末融。

4.4 引入?yún)?shù)對象/保留全局對象

在我做代碼審查時(shí)發(fā)現(xiàn)另外一個(gè)很常見的情況 - 好幾個(gè)參數(shù)被傳入方法钧惧。問題主要與需要從已有方法中增加或者移除一個(gè)方法參數(shù)有關(guān)。在這種場景勾习,建議將相關(guān)方法參數(shù)組成一個(gè)對象(引入?yún)?shù)對象)浓瞪,讓方法傳遞這些對象而不是每個(gè)單獨(dú)的參數(shù)。

4.5 用符號常量替換魔法數(shù)字

對于有意義的并且到處被使用的字面常量巧婶,應(yīng)該為它們分配一個(gè)命名常量乾颁。這能大大增強(qiáng)代碼可讀性和可理解性。

4.6 重命名方法

正如上面提到的艺栈,模糊不清的方法名會影響代碼的可使用性钮孵。這些模糊不清的名稱應(yīng)該重命名為有意義的可能與業(yè)務(wù)術(shù)語有關(guān)的名稱,來幫助開發(fā)者通過業(yè)務(wù)上下文更好地理解代碼眼滤。這很需要技巧并且要求開發(fā)者與業(yè)務(wù)專家一起協(xié)作來理清代碼需要滿足的業(yè)務(wù)需求。有趣的是历涝,這種重構(gòu)方法看起來似乎非常容易理解诅需,但是常常被許多開發(fā)者忽視,雖然在Eclipse這種IDE的refactor菜單項(xiàng)中經(jīng)常出現(xiàn)這一項(xiàng)荧库。

五堰塌、當(dāng)重構(gòu)沒有現(xiàn)成的明顯的方向時(shí),我們可以遵循下面的原則

1分衫、當(dāng)屬性场刑、方法或類存在任何的需要復(fù)用的意向時(shí),歸納提煉它們蚪战。

2牵现、不要低估小方法對代碼整潔的作用。使用小方法能讓你節(jié)省很多筆墨邀桑。

3瞎疼、用封裝控制可見度。

4壁畸、消除依賴贼急。

5茅茂、簡化構(gòu)造方法——即使這樣做會使代碼變復(fù)雜。

6太抓、不確定時(shí)空闲,將計(jì)算操作移入到這些數(shù)據(jù)的所有者對象里,或?qū)?shù)據(jù)移動到執(zhí)行計(jì)算操作的對象里(也就是迪米特法則(Law of Demeter))走敌。

7碴倾、使用小對象,松耦合悔常,避免大對象影斑,高聚合。

8机打、使用代理對象矫户,模擬對象和輔助對象來隔離網(wǎng)絡(luò),數(shù)據(jù)庫残邀,文件和用戶接口皆辽。

9、不確定時(shí)芥挣,盡量在model里添加代碼驱闷,必要時(shí)才往controler添加代碼。view里添加的都應(yīng)該是便捷功能和簡寫方法空免,但不要局限于此空另。

代碼重構(gòu)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蹋砚,隨后出現(xiàn)的幾起案子扼菠,更是在濱河造成了極大的恐慌,老刑警劉巖坝咐,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件循榆,死亡現(xiàn)場離奇詭異,居然都是意外死亡墨坚,警方通過查閱死者的電腦和手機(jī)秧饮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泽篮,“玉大人盗尸,你說我怎么就攤上這事∵淙瑁” “怎么了振劳?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長油狂。 經(jīng)常有香客問我历恐,道長寸癌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任弱贼,我火速辦了婚禮蒸苇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吮旅。我一直安慰自己溪烤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布庇勃。 她就那樣靜靜地躺著檬嘀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪责嚷。 梳的紋絲不亂的頭發(fā)上鸳兽,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機(jī)與錄音罕拂,去河邊找鬼揍异。 笑死,一個(gè)胖子當(dāng)著我的面吹牛爆班,可吹牛的內(nèi)容都是我干的衷掷。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼柿菩,長吁一口氣:“原來是場噩夢啊……” “哼戚嗅!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起枢舶,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤渡处,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后祟辟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡侣肄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年旧困,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稼锅。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡吼具,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出矩距,到底是詐尸還是另有隱情拗盒,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布锥债,位于F島的核電站陡蝇,受9級特大地震影響痊臭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜登夫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一广匙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧恼策,春花似錦鸦致、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至狮斗,卻和暖如春绽乔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背情龄。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工迄汛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人骤视。 一個(gè)月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓鞍爱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親专酗。 傳聞我的和親對象是個(gè)殘疾皇子睹逃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

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

  • 代碼重構(gòu)簡介:(英語:Code refactoring)重構(gòu)就是在不改變軟件系統(tǒng)外部行為的前提下沉填,改善它的內(nèi)部結(jié)構(gòu)...
    TaiXiang閱讀 2,960評論 0 2
  • 閱讀《重構(gòu)》的筆記獻(xiàn)上翼闹。 重構(gòu)的定義 重構(gòu)是在不改變軟件可觀察行為的前提下改善其內(nèi)部結(jié)構(gòu)。 重構(gòu)的節(jié)奏 以微小的步...
    陳宇明閱讀 11,641評論 13 64
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,167評論 25 707
  • 寫在文前:大部分程序員都能寫出計(jì)算機(jī)可以理解的代碼蒋纬,唯有優(yōu)秀的程序員才能寫出讓人容易理解的代碼 最近幾個(gè)月被分配了...
    niknowzcd閱讀 1,995評論 8 5
  • 夜未安閱讀 195評論 0 1