重構(gòu)的范疇應(yīng)該受你需要實行的代碼變更或代碼修改來決議——為了讓代碼變更更安全和更簡練,你應(yīng)該做些什么?換句話說:不要為了重構(gòu)而重構(gòu)。不要對那些你不打算進行變更或不會變更的代碼進行重構(gòu)。 不要惦念著復查或測試這些改動。這是為了讓你的重構(gòu)疾速的推動——這能讓這些代碼以及它們的運行原理在你的大腦里產(chǎn)生一個快捷但不齊備的原型。從中學習,然后丟掉它們。簡略重構(gòu)還能讓你嘗試各種不同的重構(gòu)道路,學到更多的重構(gòu)技能。Michael Feathers倡議說,在這個過程中要留心那些看起來沒什么用途、或者特別有用的東西,這樣當你完成此訓練后、要真正修改它們時,能力把事情做正確——修改時一點一點來,講求方法,邊修改邊測試。 重構(gòu)很簡略。盡可能在寫代碼前先寫測試可能避免你犯過錯。小范圍的、獨破的、穩(wěn)當?shù)膶Υa進行構(gòu)造上的調(diào)整,每次調(diào)劑完后都要進行測試,確保你不轉(zhuǎn)變代碼的行動特點——功效跟以前一樣,只是代碼上看著不同。重構(gòu)模式和古代化的IDE里的重構(gòu)工具使重構(gòu)變得輕易、保險和代價低廉。 Michael Feather的《Working Effectively with Legacy Code》這本書里提到了簡單重構(gòu)(Scratch Refactoring)的概念;Martin Fowler稱之為“為理解而重構(gòu)”。這是用來湊合那些你不理解的(或不能忍耐的)代碼,清算它們,這樣在你盤算真正著手修正它前,你能對它們是干什么的有了更好的理解,同樣也對你debug這些代碼有贊助。一旦你能明白了一個變量或方式的真正用意,重命名它們,給它們一個更適合的名稱,刪除那些你不喜歡看的(或感到?jīng)]有用的)代碼,拆解龐雜的前提語句,把長程序分解成數(shù)個容易懂得的小程序。 --> 有時候,會有程序員跑到我這里說他們不喜歡某個貨色的設(shè)計,“咱們需要給它來個全面的重構(gòu)”,來糾正里面的毛病。哦,哦。這聽起來可不是個好主張。而且這聽起來也不是重構(gòu)…你不是為了重構(gòu)而重構(gòu),你重構(gòu)是因為你想做其它的事情,而重構(gòu)能輔助你實現(xiàn)這些事件。 對代碼進行簡單的但又顯著的重構(gòu):打消重復,修改變量和方法名稱使其更有意義,提煉方法使代碼更易懂、更易復用,簡化條件邏輯,把無意思的數(shù)字換成命名的變量,把類似的代碼集中到一起。通過這些重構(gòu),在代碼的可理解性和可維護性上,你能得到宏大的回報。 而且在開發(fā)新代碼的同時你還要維護舊代碼,這使得代碼版本把持很麻煩,變革起來不便利,以致代碼很懦弱,易出錯——這正和重構(gòu)所預期的目標南轅北轍。有時這樣的情形會始終連續(xù)下去——這種新舊代碼交替的進程永遠不能完成,因為能取得最大好處的局部都是最先完成,或者因為最初帶來這個主意的參謀已經(jīng)干別的去了,或者是估算被消減,而且你也厭惡保護這樣一個拖沓的名目。 有些人愛好把對一個系統(tǒng)的重新設(shè)計或重寫或從新搭建平臺或返工叫“大規(guī)模重構(gòu)”。由于技巧上講,這些并不改變軟件功能特征——業(yè)務(wù)邏輯、軟件輸入和輸出仍和以前一樣,“只是”設(shè)計和代碼實現(xiàn)變了。它和慣例重構(gòu)的差別看起來就是:一個是重寫了一段代碼,一個是重寫了一個體系,只有你是一步一步做下來的,你都能夠稱之為“重構(gòu)”——不論你是終年累月被困于將一個老系統(tǒng)換成新代碼,仍是對系統(tǒng)架構(gòu)進行大規(guī)模的改革。 重構(gòu)可以、也應(yīng)該融入到你寫代碼或維護代碼的過程中——作為日常開發(fā)/品質(zhì)管理的組成部分,就像寫測試和代碼審查一樣。重構(gòu)應(yīng)該被寧靜的,持續(xù)的和低調(diào)的完成。它需要我們把工作精神分出一部分給它,它需要在我們的工期評估微風險評估中斟酌到它的存在。假如做的準確,你不需要去說明或向外人驗證這部分工作。 這些是重構(gòu)——那些不是 在這個過程中發(fā)明了bug、修改bug,這不是重構(gòu)。優(yōu)化不是重構(gòu)。強化異樣捕獲、增添防備性代碼不是重構(gòu)。讓代碼更容易測試不是重構(gòu)——只管重構(gòu)能到達雷同的后果。這些所有的事都是有利的。但這些都不是重構(gòu)。 重構(gòu)(Refactoring)這個詞最初由Martin Fowler 和 Kent Beck給下的定義,它是 花幾分鐘、一兩個小時做重構(gòu),就像是你開發(fā)過程中的一種修改,是工作的一部分。如果它讓你花了數(shù)天時光,或者更長,那不是重構(gòu);那是重寫,或重新設(shè)計。如果你需要明白的留出一部分時間(或全部sprint周期)來重構(gòu)代碼,如果需要為清理代碼而申請同意,或把清理代碼作為一個開發(fā)需要,那你不是在重構(gòu)——即便你用了重構(gòu)的技術(shù)和工具,你依然做的是另外一種工作。 在這種重型的項目開發(fā)過程中混入重構(gòu)的概念是錯誤的。它們從根本上就是另外一種工作,帶有完整不同的開發(fā)本錢和風險。它混雜了人們對什么是重構(gòu)、重構(gòu)能干什么的意識。 什么是“大規(guī)模”重構(gòu)? 重構(gòu)的成果是援用了快捷方法、去除了反復代碼和逝世代碼,使設(shè)計和邏輯更加清晰。是在更好的、更聰慧的應(yīng)用編程語言。是在上風應(yīng)用你當初知道、但當時的開發(fā)程序員并不曉得——或并沒有加以利用的信息。一直的簡化代碼,讓它們更容易理解。不斷的使它們在未來的變更變得更容易、更安全。 一種修改,使軟件的內(nèi)部結(jié)構(gòu)更容易理解,在不改變軟件的可見行為方法條件下使軟件更容易變更…它是一種有節(jié) 制的收拾代碼、使bug發(fā)生多少率最小化的方法。 “大規(guī)模重構(gòu)”會變的很蹩腳。你可能需要花數(shù)周、數(shù)月(甚至數(shù)年)才干完成,需要你對軟件的良多部門進行修改。軟件會因而不能運行,需要分屢次宣布這些變更,需要你做常設(shè)的臺架(scaffolding)和變通計劃——尤其是你采取短周期的迅速開發(fā)方法時。這時Branch by Abstraction這樣的實踐方法就派上用處了,它能幫你在長周期內(nèi)治理代碼中的變更。 程序員,特殊是做維護工作的程序員,清理代碼是他們的日常工作之一。這是基礎(chǔ)工作,是必需要做的。Martin Fowler等人的奉獻是使重構(gòu)代碼的最佳實際辦法格局化,并把常見的、證實切實有效的重構(gòu)模式——重構(gòu)的目的和重構(gòu)的步驟——進行歸檔分類。 相對這些較小的、行內(nèi)的重構(gòu),更加重大的設(shè)計上的重構(gòu)與之有顯明差別——這就是Martin Fowler所指的”大型重構(gòu)”。大的、代價很高的變動,附帶有大批的技術(shù)危險。這不是你編程過程中的清理代碼和設(shè)計改良:這是根天性的重新設(shè)計。 不要為了重構(gòu)而重構(gòu) 重構(gòu)可以被當成一種能給你的代碼變更帶來幫助的辦法。代碼重構(gòu)應(yīng)當在你進行代碼變更前進行,這樣能讓你確信你對代碼理解了,使你更容易、更平安的把變更引入代碼。對你的重構(gòu)動作進行回歸測試。然落后行改正或變更。再次測試。之后可能須要對更多的代碼進行重構(gòu),使你代碼變更的意圖變得更加清楚。再次進行全面測試。重構(gòu),再變更?;蜃兏?,而后重構(gòu)。 為理解而做簡略重構(gòu)(Scratch Refactoring) 有些程序員以為對代碼進行基本的、重大的修改是他們的權(quán)力和任務(wù),在重構(gòu)的名義下進行重新設(shè)計、重寫,為了將來,也不辜負本人的技能。重新設(shè)計和重寫有時候是你正確的該做的事情。但出于坦誠和表述清晰,請不要把這些運動賦以重構(gòu)的名義。 相關(guān)的主題文章:
|