摘要:無論如何,單元測試一直是一中非常重要卻常常被忽視的技能。在實踐中,重構的要求是很高的它需要有足夠詳盡的單元測試,需要有持續集成的環境,需要隨時隨地在小步伐地永遠讓代碼處于可工作狀態下去進行改善。
五月初的時候朋友和我說《重構》出第 2 版了,我才興沖沖地下單,花了一個禮拜時間一口氣把它讀完后,才有了這篇書評。掩卷沉思,我無比贊同豆瓣網友“天心一”的評論:
這本書雖然很流行,但是應該看它而沒有看的人,還是太多太多了。一個老讀者的自白
作為一個開發者,2012年初識本書的時候,我在寫 Java;2019年本書再版,我在寫 JavaScript。真是應了那句老話兒:“凡是可以用 JavaScript 來寫的應用,最終都會用 JavaScript 來寫。”
JavaScript 特別適合重構,因為它很容易寫的無法維護。?
當然這只是個玩笑,實際上作者也解釋過:重構背后的理念和架構適用于任何編程語言,選擇 JavaScript 只是因為它應用的比較廣泛。無論使用哪種編程語言都可以寫出優秀的或者糟糕的代碼,同樣也都可以以本書的思路和技巧進行重構。
使用 JavaScript 展示代碼范例,并不意味這本書中介紹的技巧只適用于JavaScript。
對比新舊兩版,作者“重構”了這本書:前幾章有所擴展,后幾章結構調整較大,移除了原來的 12-14 章。總的來說,重構后的第 2 版更接地氣、更適應時代:不再有“大型重構”,更多地聚焦操作的細節。
“Fowler 先生不僅沒有拔高,反而把功夫做得更扎實了。”——摘自譯者序
雖然本書的副標題是“改善既有代碼的設計”,但通讀全書之后,我覺得這本書對于設計新系統時如何避免“壞味道”也是很有指導意義的。
重構和敏捷開發是一對親兄弟提重構就不能不提敏捷開發,馬丁·福勒本身就是敏捷開發的發起者之一。敏捷作為“當紅炸子雞”,與重構有著很多相似的地方。
一是,這兩者都容易成為“掛羊頭,賣狗肉”中的“羊頭”,很多情況下,所謂的重構就是抽出時間來重寫現有的幾乎無法維護的代碼,就如同很多“敏捷”只做到了“不拒絕需求變更”而沒有真正做到響應變化;二是,它們實現起來都是一定難度且它們的實踐過程可以是交叉的——它們都著眼于具體細節而不是空架子,都歡迎變化,都強調小步快走、持續改進;三是,敏捷開發很重要的兩個環節就是設計與重構,兩者相輔相成,彼此互補,在實踐的過程中保持較強的適應力。
重構的技巧可以說,我在重構過程中遇到的問題大多都能在本書中找到答案。
我們看看作者對重構的定義:
重構(名詞):對軟件內部結構的一種調整,目的是在不改變軟件可觀察行為的前提下,提高其可理解性,降低其修改成本。重構(動詞):使用一系列重構手法,在不改變軟件可觀察行為的前提下,調整其結構。
為何重構、如何重構、重構的原則與手法,都可以在這本書中找到。從第 5 章起作者提供了多達 300 頁的重構名錄、60 余項重構的具體技巧(老版本是 70 多項,新版本移除了大規模項目的重構)。我覺得這一份非常詳盡的重構手法清單更接近于字典,適合粗讀之后在用到的時候再具體查閱。
至于什么時候能夠用到這份名錄,作者在第 3 章也有介紹:當代碼有了“壞味道”就可以著手進行重構了。所謂“壞味道”,我認為并非是一程不變的準則,而是需要根據團隊、項目、采用的技術棧等各方面綜合得出的一種無法定量描述的經驗。所以,作者用了“味道”這樣一種體驗來代指需要重構的地方。在作者列出的每種“壞味道”中,都給出了對應的重構手法。雖然作者羅列的 20 多種“壞味道”覆蓋面很廣,但是你和你的團隊仍然可以總結出自己的經驗來指導重構。實際上,與第 1 版相比,第 2 版中的“壞味道”增加了“神秘命名”“全局數據”“循環語句”,刪除了“不完美的庫類”。
我認為本書最重要也最容易被忽略的章節就是第 4 章——構筑測試體系。在第 4 章中,作者通過一個生產計劃的示例一步一步的構建了一個完整的單元測試體系。顯然,掌握單元測試是有一定成本的,這就導致有些開發者(尤其是前端領域)完全不注重單元測試。他們認為測試是QA的職責,自己只需要保證冒煙測試通過即可。然而反直覺的是,良好的單元測試不但是重構的先決條件和好幫手,而且能幫我們整理設計的思路,從而更好的寫出優秀的代碼。因為在寫單元測試的時候,我們會假設自己是一個“代碼破壞者”,思考如何破壞代碼的運行、尋找那些可能出錯的邊界條件。單元測試的編寫和運行可以在寫完代碼后進行,也可以在寫代碼之前動手。先寫單元測試再寫代碼的技巧叫作測試驅動開發(TDD),也是敏捷開發的基石之一。關于TDD的技藝,作者的好友 Kent Beck 專門寫了一本書,即《測試驅動開發》。
作者在第 1 章的示例中提到:“小步快走,代碼永遠處于可工作狀態。”而且作者特意強調:“每當我要進行重構的時候,第一個步驟永遠相同:我得確保即將修改的代碼擁有一組可靠的測試。”
對于單元測試,我有一點小小的心得可以與大家分享:盡量編寫純函數。純函數是沒有副作用的函數,給出同樣的參數值,純函數總是返回同樣的結果,它不依賴于參數以外的值。顯然,純函數更便于單元測試。
當然單元測試也不是萬能的,它不可能檢出所有的bug,而且單元測試集的覆蓋率也是一個見仁見智的指標,具體需要寫多少單元測試,覆蓋多少代碼,都是需要我們在開發中結合實際情況自己權衡的。無論如何,單元測試一直是一中非常重要卻常常被忽視的技能。
另外,我在開發實踐中堅持一個“432”的原則,供大家參考:
一個類包括注釋代碼不要超過400行;
一個純函數最好不要超過30行;
函數內循環嵌套最多2層。
重構的現狀有些朋友對“重構”是不支持甚至是深惡痛絕的。
一部分開發者不愿意把精力“浪費”在重構上
他們覺得重構是“給飛行中的飛機修引擎”,有可能出現很多問題卻帶不來多少拿得出手的成績;重構總是會在“不經意間”破壞原有功能,帶來的麻煩很多,投入與收益完全不成比例,也很少會是面試的重點,花精力在這上面實在是費力不討好。
許多leader反對盲目重構
在創業公司里基本不會有重構的呼聲,原因無須贅言;而在一些大企業里,leader們也不是都喜歡重構,因為花時間重構意味著占用了開發新功能的時間,在代碼還能跑起來甚至看起來跑得還不錯的時候去重構無疑是畫蛇添足;與重構帶來的風險相比,重構帶來的好處就不是那么有說服力了。
大部分QA對重構持謹慎的質疑態度
代碼的變動意味著需要進行回歸測試,而敏捷當道的時代,每個迭代中QA的關注重點都在新功能上,能夠分配給回歸測試的精力很有限,而在測試通過后的重構極有可能導致此次變更對QA不透明,無形中增加了上線的風險。
我認為以上幾種反對重構的場景都是不恰當的重構導致的。
大家只是越來越接納“重構”這個詞,因為這個詞聽起來很好,有一種積極應對變化的感覺,但真正在做的還是跟以前一樣,毫無規矩的修改。
在實踐中,重構的要求是很高的:它需要有足夠詳盡的單元測試,需要有持續集成的環境,需要隨時隨地在“小步伐地永遠讓代碼處于可工作狀態”下去進行改善。正是因為許多項目的“重構”是在并不滿足以上條件也沒有經過成本估算、策略規劃的情況下進行的,自然很容易導致失敗。
水土不服
實際上,還有一部分開發者雖然認識到了重構是提升代碼質量的有效手段,是諸如“在當下努力工作,以免日后有更多的活兒”此類觀念的具現。然而在某種程度上說,這在當前996.icu大環境下是不適用的。關于這一點就只能見仁見智、自己衡量了。
沒有銀彈
最后,我想說一句: 沒有銀彈。
重構和設計模式一樣,是對于最佳實踐的提煉,是一系列技巧的集合,它不是打通任督二脈的靈丹妙藥。如果你是一個有追求但卻從來沒有系統地了解過重構的程序員(當然我不相信世界上會有這種程序員),那你會發現,你在日常工作中不經意間已經用過了這本書中提到的各種重構手法。
重構是注重實踐的技藝,僅僅了解其理念而忽視實踐則有如摶沙作飯,白費心思;而企圖把它當做“萬金油”來解決所有問題也只會陷入不恰當重構的陷阱,最終得不償失。只有在合適的場景下恰當的實踐,才會實現其應有的價值。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/104392.html
摘要:壞的味道指的是應該被修改,被重構的代碼,不具有可讀性,復用性,判斷邏輯復雜,冗余代碼。它們通常能指出代碼用途和實現手法之間的語義距離。把所有和這個變量相關的代碼新建一個類放入。但這往往不夠,請反復運用將某些行為移入類,直到者的協議一致為止。 壞的味道:指的是應該被修改,被重構的代碼,不具有可讀性,復用性,判斷邏輯復雜,冗余代碼。應該使用各種重構的手法去改變它! Duplicated...
摘要:如何才能成為一名專業的開發者資深開發者在其博客上分享了一些心得。要想成為一個專業的程序員,首先要成為一個中級程序員。永遠不要低估陪伴的力量結論當你專注于實踐上面所提到各種方法的時候,你就在成為專業開發者的路上。 如何才能成為一名專業的PHP開發者?資深Web開發者Bruno Skvorc在其博客上分享了一些心得。 showImg(http://segmentfault.com/img...
摘要:類型檢測類型檢測也是一種讓代碼簡潔的小技巧。上文中,我們只是嘗試搜集了一些例子,在這些例子里,你只需做出一點小的努力,就可以讓你的代碼變得更好更簡潔。 showImg(https://segmentfault.com/img/remote/1460000013847223); 保持代碼簡潔和高可讀性遠遠要比我們想象的要難,有時候甚至比持續架構設計都要難。這里收集了一些可能對你重構代碼有...
摘要:生成你的明星臉介紹,叫做生成對抗網絡。改進損失函數為了訓練過程穩定,生成高質量的圖像,論文中采用自定義梯度懲罰來代替對抗誤差損失其中表示真實和生成圖像之間均勻采樣的直線,試驗時。 StarGAN——生成你的明星臉 1 GAN 介紹 GAN,叫做生成對抗網絡 (Generative Adversarial Network) 。其基本原理是生成器網絡 G(Generator) 和判別器網...
閱讀 2743·2021-10-26 09:50
閱讀 2385·2021-10-11 11:08
閱讀 2128·2019-08-30 15:53
閱讀 1906·2019-08-30 15:44
閱讀 2382·2019-08-28 18:12
閱讀 2519·2019-08-26 13:59
閱讀 2852·2019-08-26 12:19
閱讀 2751·2019-08-26 12:09