任何一個傻瓜均可以寫出計算機能夠理解的代碼,惟有寫出人類容易理解的代碼,纔是優秀的程序員。程序員
——Martin Fowler 《重構》編程
面對運行緩慢的老系統;前任程序員遺留下亂成一團的代碼塊;迷宮式的超級大函數……你能怎麼辦?無外乎兩個選擇:要麼忍,要麼重構。安全
但,重構,是多少人心中的痛!架構
高手重構代碼,是這樣的:框架
而你重構代碼,倒是這樣的:編程語言
能力除外,人們抗拒重構的緣由還有不少:函數式編程
項目這麼急,能上線就不錯了,哪有時間重構?
涉及到的模塊太多太雜,重構,風險太大!
重構代碼吃力不討好,還要被同事嫌棄。
互聯網行業人員流動這麼快,下個月就離職了,重什麼構?
……函數
理由千千萬,究其根本,仍是對本身的編程技藝的要求不夠高。明明知道重構的重要性,卻迫於外部環境或形勢的壓力繳械投降。可是,正如電影《無間道》所說:「出來混,早晚是要還的。」如今不精進本身,練就紮實的重構本領,將來,代碼的壞味道定將施以報復。測試
恰逢重構20年,軟件開發界的不朽經典《重構:改善既有代碼的設計》一書作了重磅升級。《重構》一書的做者馬丁·福勒(Martin Fowler,世界軟件開發大師,全球知名技術諮詢公司ThoughtWorks首席科學家),在最近ThoughtWorks對他的訪談中,談了他對重構的認識及與重構理念相關的種種問題。看看高手如何給你支招。翻譯
Martin:須要重構代碼的緣由固然多種多樣。首先,當你沒法理解代碼時,一個明確的跡象是你花了很長時間想弄清楚一些代碼的目的或功能。還有一種狀況,借用我我的很喜歡的Ward Cunningham的說法:一旦你在腦海中對代碼功能有了必定的概念,就要把它從大腦中「拿」出來並放回代碼中,這樣下次你或其餘人再看到這些代碼,他們就能真正讀懂這些代碼。觸發重構的另外一個因素是開發者想改進代碼,但現有代碼的架構令改進難度又很大,在這種狀況下,重構提高了改進的速度、下降了難度,結構變簡單後,改進也就水到渠成了。仍是Kent Beck那句話說得好:首先讓代碼架構易於改變,而後再進行簡單的改進。對我而言,下面這些都是觸發重構的時機:當你發現代碼不夠清晰、難以理解時;當你對代碼功能有了一些瞭解,想把這些嵌入代碼中時。當你想要改進代碼時,比較容易的作法是先進行重構,再添加新功能。
Martin:我得認可,我不是一個超有說服力的人。我不會努力說服你們改進,我只是嘗試解釋該如何作事,但願他們本身領悟並嘗試最佳實踐。談到不修改代碼時,確定會涉及須要某種代碼庫來確保修改代碼時能夠輕鬆檢測到問題,這就是咱們很是重視進行嚴格測試的緣由,由於測試是一種很好的監測機制。還有一些來自項目的技術管理者會向下屬說明,改進代碼不要緊,但只能經過迭代和擴展來寫出有效的代碼。可是,有時開發者也會固步自封,我就遇到過有些團隊的開發者說「哦,咱們不應改變」,對上級主管也這樣說,而主管會很是詫異,連聲說「不對,我真的想重構」。像這種上下級理念徹底相反的狀況很常見。須要創造一種企業文化,容許你們說:「咱們能夠回到原點並改進代碼。」在測試方面咱們有必要的安全基礎,這樣開發者才能在錯誤出現時檢測到錯誤。
在開發的過程當中,一方面你須要爲軟件添加新功能,另外一方面你也須要重構,以確保軟件維持健康狀態,不然就沒法在軟件裏繼續添加新功能。保持二者的平衡很是重要,這要求開發者有良好的判斷力。像許多事情同樣,良好的判斷力確實是個關鍵元素,但遺憾的是,並無什麼捷徑來傳授判斷力。
Martin:僱主花錢僱咱們作好技術工做,並且這其中很大一部分就是使代碼庫保持健康狀態,這樣將來就能在代碼庫上持續添加新功能。若是不重構,嚴格來講咱們就辜負了僱主的指望,由於不重構會致使功能開發速度變慢。從經濟角度來看,咱們有責任讓代碼庫穩定處於健康狀態,重構固然是一種使關鍵代碼庫保持健康狀態的重要方法,若是不能令代碼庫保持在健康狀態,就至關於咱們從客戶和上司那裏「偷」錢。所以,從根本上說,咱們有責任進行重構。
在我看來,你永遠不應用諸如「這是咱們的職業責任」「這是正確的事情」或 「出於道義理由」等話術,我知道不少人都喜歡用這套說法,而當你濫用術語時,你已經迷失了。重構的惟一緣由是經濟緣由,重構的目的是更快地增長更多功能,以便更及時地響應各方需求的變化,而經濟緣由纔是重構的底層緣由。順便說一句:這也是明智的專業態度纔是正途的緣由,由於老闆花錢請開發人員用代碼快速生成功能,咱們也該站在這個立場上考慮重構問題。但嚴格來講,對管理者或企業而言,快速開發或新增功能,或者使代碼庫保持健康等因素並不重要。他們付錢給開發人員搞軟件開發正是爲了處理這些問題。
Martin:絕對能夠。重構的關鍵是理念:如何進行最細微的改變,而不是努力搞大的變化嘗試,並弄清楚如何作到這一點。經過重構就會發生不少細小的變化,而後將這些變化串聯起來,這就是重構思惟適用於這種狀況的核心。咱們如何將一個大變化拆分爲許多小變化,又在儘量多進行細微變化的同時,不改變系統的總體表現,而後隨時間推移,反覆練習並思考如何進行拆分。我書中的內容就是我經過重構框架思考問題的體驗,嘗試各類重構手法並作出決定。書裏有一整套機制讓我可以高效地進行重構,但主要時經過實踐進行重構。你嘗試了不一樣的重構手法,而後找出哪一個重構手法能生成理想序列,你嘗試識別出這種重構手法,一樣的邏輯也適用於更普遍的層面。
高手重「道」,Martin的分享更可能是從認知上告訴你,軟件大師或者一個高級開發人員是如何看待「重構」這件事的。那麼,如何修煉本身重構的功力?這就不得不向你們推薦《重構(第2版)》這本不朽經典的升級祕笈!
備受關注的《重構(第2版)》在第1版的基礎上作了全面修訂,反映了編程領域業已發生的許多變化。第2版中介紹的重構列表更加內聚,並用JavaScript語言重寫了代碼範例。此外,第2版中還新增了與函數式編程相關的重構範例,旨在教會讀者如何在沒有類的環境下開展重構。新版沿襲了第1版的結構,依次解釋什麼是重構,爲何要重構,如何經過「壞味道」識別出須要重構的代碼,以及如何在實踐中用任何編程語言均可以成功實施重構。
不少人關注到新版中代碼示例的使用從Java變成了JavaScript。Martin解釋道:重構背後的理念和架構適用於任何編程語言。我選擇JavaScript,只是由於我以爲它是一種應用普遍的語言。不管你使用哪一種語言編程,基本機制都是徹底相同的,語言與語言之間當然存在差別,但我認爲語言之間的共通之處遠比差別多。要知道,Java是一種很是嚴格的面向對象編程語言,第1版中全部的重構都是基於面向對象的。我想經過再版來講明你能夠用任何(編程)語言、在任何環境中、遵循書中提到的範例進行重構,這是我計劃再版這本書的另外一個理由,也是我再版這本書的源動力。若是此次內容更新得很是到位,能夠說再過20年我都不用再修訂這本書了。
壞味道、測試先行、行爲保持的變動動做,是重構的基本功。在《重構(第2版)》裏,重構手法的細節被再度打磨,重構過程比之第1版愈發流暢。細細品味重構手法中的先後步驟,琢磨做者是如何作到行爲保持,這是能啓發讀者觸類旁通的讀書法。舉保持對象完整重構手法爲例,第1版中的作法是在本來函數上新添參數;而第2版的作法則是先新建一個空函數,在其中作完想要的調整以後,再總體替換本來函數。兩相對比,無疑是新的作法更加可控、出錯時測試失敗的範圍更小。
對比先後兩版的重構列表,你會發現:第2版收錄的重構手法在用途上更加內聚,在操做上更加連貫,更重視重構手法之間的組合運用。第1版中佔了整章篇幅的「大型重構」,在第2版中全數刪去。一些較爲複雜的重構手法,例如複製「被監視數據」、塑造模板函數等,第2版也再也不收錄。而第2版中新增的重構手法,則可能是提煉變量、移動語句、拆分循環、拆分變量這樣更加細緻而微的操做。這些新增的手法看似簡單,但直指大規模遺留代碼中最多見的重構難點,正好補上了第1版中闕漏的細節。這一變化,正反映出Martin Fowler對於重構一事一向的態度:千里之行積於跬步,越是面對複雜多變的外部環境,越是要作好基本功、邁出紮實步。
修煉祕笈在此,最重要的仍是上手實踐。重構就像軟件開發的大多數工做同樣:除了動手作,別無他法。《重構》這本書確定能幫助那些初次接觸重構概念的人,但它也能幫助那些瞭解重構的人分享相關技能。Martin也提醒讀者:請記住重構的要義就是小步驟改進,確保你頻繁提交。若是出了什麼問題,你只需回滾到先前的提交記錄上,這就會下降重構的壓力。重構確定不會給你帶來太壞的影響,由於大不了你就回滾唄,這就是版本控制系統的用途。因此,趕忙上手重構吧,操做纔是關鍵。
做者:[美]馬丁·福勒(Martin Fowler)
譯者:熊節 林從羽
編輯推薦:
世界軟件開發大師MartinFowler的不朽經典
普通程序員進階到編程高手的修煉祕笈
它在世界範圍內暢銷不衰,被翻譯爲中、德、日、俄等衆多語言。
這本經典書20年後重磅升級,更新內容超30%,更新了衆多項目案例。
本書是經典著做《重構》出版20年後的更新版。書中清晰揭示了重構的過程,解釋了重構的原理和最佳實踐方式,並給出了什麼時候以及何地應該開始挖掘代碼以求改善。書中給出了60多個可行的重構,每一個重構都介紹了種通過驗證的代碼變換手法的動機和技術。本書提出的重構準則將幫助開發人員小步地修改代碼,從而減小了開發過程當中的風險。
-END-