Information for details

軟件開發“教父”教你如何重構軟件開發模式?如何重塑軟件開發者思維?

       

       Martin Fowler,世界級軟件開發大師,敏捷開發的開拓者和創始人全球知名的面向對象分析設計、UML、模式等專業領域的領頭羊,首創敏捷開發方法論,被譽為軟件開發“教父”,現任職于全球知名技術咨詢公司ThoughtWorks,首席科學家。


                                                                                                                                        Martin Fowler

       坊間流傳著這樣一句話,如果有一本編程技術類書籍能夠讓讀者在工作或實踐多年后,還在反復咀嚼玩味、愛不釋手、引導著讀者前進著,那個必定是Martin Fowler的《重構》。

Martin還是IT領域的知名作家,他撰寫的七本有關軟件開發的書廣受程序員們的喜愛,包括重構、企業應用程序體系結構模式和UML Distilled等領域。其中《重構》風靡國內外,擁有數百萬讀者,國內豆瓣評分高達9.5分。


Object Technology International, Inc,Erich Gamma 曾這樣評價Martin:

      Martin Fowler清楚地揭示了重構過程,他為面向對象軟件開發所做的貢獻難以估量。他解釋了重構的原理和最佳實踐,并指出何時何地你應該開始挖掘你的代碼以求改善。

因此,我極力推薦你試試Martin Fowler的重構手法,你和你的程序都將因此更美好。

 

                                                                                                     軟件開發“教父”的重構生涯


      Martin Fowler,1963年出生在英格蘭的沃爾索耳,正是編程世界剛剛起步的年代。

      Martin 在80年代初開始接觸軟件行業,那時候Smalltalk還是一門很火的語言,大家都在學習這門語言,而Martin也剛開始從事軟件工作——關于信息系統對象建模方面的顧問。

       那個年代沒有任何有關面向對象分析和設計的書籍,大家都是用一種簡單的圖符表示法,然后提出一個簡單的建模過程,最后用幾個簡單的示例來加以說明。但Martin認為不應該把重點放在過程——即如何建模,而是把重點放在過程的結果——即模型本身,盡管這與當時大環境下的創建方式是相悖的。

 


      到了90年代初,Martin發現,大多數程序員很難通過緊跟技術創新的腳步來享受軟件工程領域的新成果。

 

身為一個信息系統對象建模顧問, Martin從Smalltalk上學得的專業知識是遠遠超過這個職業所需要的,他覺得自己既然有了這些建模方面的理念,同時又對編程方面很感興趣,所以他不單在建模方面幫助別人,還在編程方面進行指導——借助外力的幫助,精確地運用UML。


從建模到編程語言,他把這些都看成一件完整的、而非毫無關聯的事。

 

這樣的工作持續了近十年,1999年,Martin迎來了他人生中意義重大的一年。

 

那時Martin造訪了客戶調研的開發項目時發現,該系統的核心繼承體系相當凌亂,為此,他建議負責該項目的經理將這些代碼進行整理,但是項目經理認為在項目面臨很大的進度壓力下,只要程序看上去還可以運行就算是完成。


這種情況下,《重構:改善既有代碼的設計》面世了,Martin在這本書中揭示了重構的過程,解釋了重構的原理和最佳實踐方式,并給出了何時以及何地應該開始挖掘代碼以求改善。

重構這個理念一經推出,受到了廣大程序員的喜愛,他們覺得在不改變代碼外在行為的前提下,對代碼做出修改,以改進程序的內部結構是一個非常妙的事。后來,這本風靡國際IT行業的《重構》被引入國內,在豆瓣評分以9.2的高分長期霸屏程序員必讀書單中。

2010年,第五屆敏捷軟件開發大會“敏捷中國2010”上,Martin的“敏捷宣言”又一次引領了整個IT行業對敏捷開發的認識,從此“敏捷”二字開始風行國內 IT 領域。對程序員們來說,他就是當之無愧的先行者。


就在去年,這位先行者又全面升級了《重構》,《重構:改善既有代碼的設計(第2版)》面世了,國內外掀起一陣搶購熱潮,豆瓣評分更是高達9.5分。


Martin定義的重構到底是什么?

說起重構,還要從1999年發生在Martin身上的一件事說起。面對凌亂的系統的核心繼承體系,他建議負責該項目的經理將這些代碼進行整理,但是被項目經理拒絕。

隨后,Martin把自己的想法第一時間告訴了在這個繼承體系上工作的程序員,程序員都很敏銳, 馬上就看出問題的嚴重性,特別是在這種需要借助外力才能發現問題。他們立刻用了兩天的時間整理好這個繼承體系,并刪掉了其中一半代碼,功能毫發無損,而且發現在繼承體系中加入新的類或使用系統中的其他類都更快、更容易了,他們十分感謝Martin。

但項目經理很不高興,他覺得這些程序員卻白白耗費了兩天時間,做的工作卻與未來幾個月要交付的大量功能毫不相干,明明原先的代碼運行起來還算正常,為什么要為了可能發生的問題去花費時間提前預防呢?

 

不過在6個月之后,這個項目還是宣告失敗了,原因是代碼太復雜,無法調試,也無法將性能調優到可接受的水平。再后來,這個項目重新啟動,唯一的解決辦法就是從頭開始編寫整個系統,Kent Beck 受邀做了顧問。他做了幾件迥異以往的事,其中最重要的一件就是聽從Martin的建議,堅持以持續不斷的重構行為來整理代碼。

那時,Martin第一次認識到重構的重要且不可替代性。

“重構”這個概念最開始來自于 Smalltalk圈子,由于重構是框架開發中不可缺少的一部分,所以當框架設計者討論自己的工作時,這個術語就誕生了。

當他們精煉自己的類繼承體系時,當他們叫喊自己可以拿掉多少多少行代碼時,重構的概念慢慢浮出水面,后來重構就進入了其他編程語言陣營之中。

說得直白一點,所謂重構(refactoring)就是這樣一個過程:在不改變代碼外在行為的前提下,對代碼做出修改,以改進程序的內部結構。

重構是一種經千錘百煉形成的有條不紊的程序整理方法,可以最大限度地減小整理過程中引入錯誤的概率。本質上說,重構就是在代碼寫好之后改進它的設計。

“在代碼寫好之后改進它的設計”這種說法有點兒奇怪。在軟件開發的大部分歷史時期,大部分人認為,應該先設計而后編碼:首先得有一個良好的設計,然后才能開始編碼。

但是,隨著時間流逝,人們不斷修改代碼,于是根據原先設計所得的系統,整體結構逐漸衰弱。代碼質量慢慢沉淪,編碼工作從嚴謹的工程墮落為胡砍亂劈的隨性行為。

“重構”正好與此相反。

哪怕手上有一個糟糕的設計,甚至是一堆混亂的代碼,我們也可以借由重構將它加工成設計良好的代碼。重構的每個步驟都很簡單,甚至顯得有些過于簡單:只需要把某個字段從一個類移到另一個類,把某些代碼從一個函數拉出來構成另一個函數,或是在繼承體系中把某些代碼推上推下就行了。

但是,聚沙成塔,這些小小的修改累積起來就可以根本改善設計質量。這和一般常見的“軟件會慢慢腐爛”的觀點恰恰相反。

有了重構以后,Martin發現工作的平衡點開始發生變化,例如,設計不是在一開始完成的,而是在整個開發過程中逐漸浮現出來。在系統構筑過程中,他學會了如何不斷改進設計。這個“構筑-設計”的反復互動,可以讓一個程序在開發過程中持續保有良好的設計。

Martin認為,重構這東西不可能一開始就完全正確,它將隨著設計者的經驗成長而進化,代碼被閱讀和被修改的次數遠遠多于它被編寫的次數。而保持代碼易讀、易修改的關鍵,就是重構。


作為一本為專業程序員編寫的重構指南——《重構》,Martin的目的是告訴所有程序員如何以一種可控且高效的方式進行重構,從而減少了開發過程中的風險。

書里提出的重構準則將幫助他們學習如何有條不紊地、一次一小步地修改代碼、改進程序結構,且不會引入錯誤的正確的重構方式,最終得到有效的、長期可運行的代碼程序,而不是去遵循那句古老的工程諺語:“如果它還可以運行,就不要動它。”

 

重構再度升級

《重構》自1999年面世以來,已經經過21年了。軟件行業里新的編程語言不斷涌現,老的編程語言也加快迭代,而函數式編程和面向對象一樣成了主流編程語言的標配。不僅軟件開發技術發生了很多重要的變化,各種軟件開發工具也日益現代化,對開發的更好支持也已成為主流編程語言新的核心競爭力。

 

而現在, “重構”這一理念已被讀者廣泛接納,作為一種經千錘百煉形成的有條不紊的程序整理方法,能夠最大限度地減小整理過程中引入錯誤的概率,成為編程的詞匯表中不可或缺的部分,《重構》一書至今依舊被無數程序員奉為軟件開發領域的經典之作。

但重構的扎實功夫要學起來、做起來,頗不是件輕松的事,且不說詳盡到近乎瑣碎的重構手法,光是單元測試一事,怕是已有九成程序員無法企及,漸漸地,“重構”成了一塊漂亮的招牌,大家都愿意掛上這個名號,可實際上干的卻多是“刀劈斧砍”的勾當。

就國內先如今的情況而論,“重構”概念的表里分離,大有愈演愈烈之勢。隨著當年的一線技術人員紛紛走上領導崗位,他們樂于將“重構”這塊漂亮招牌用在更寬泛的環境下,例如系統架構乃至組織結構,都可以“重構”一下。

然而基本功的欠缺,卻也一路如影隨形。當年在對象中的刀劈斧砍,如今被照搬到了架構、組織的調整。于是“重構”的痛苦回憶又一遍遍重演,甚而程度更深、影響更廣、危害更烈。

通過重構,現在的程序員普遍通過微增量來開發系統、編寫測試用例。但Martin認為這遠遠不夠,重構的影響其實應該更廣泛,20年前,他和其他先行者鼓勵大家都接受重構這一概念,但是,在整個行業普及重構仍需要相當長的時間。

對于IT領域來說,Martin不僅僅是一個先行者,他還是一個引路者。

Martin希望看到更多人使用他們大力推廣的測試法,使用持續集成和持續交付等方法。但涉及上述概念,Martin覺得自己只能盡量在書中,從主客觀上盡可能詳盡地解釋這些技術,并希望這會說服更多人進行嘗試,“當他們嘗到甜頭后就會在工作中真正用上這些方法“。

針對這一現象,Martin推出了《重構:改善既有代碼的設計(第2版)》,他在第1版的基礎上做了全面修訂,反映了編程領域業20年來發生的許多變化,但Martin傳遞的理念也始終如一:不改變外在行為,而提高代碼質量,但將基礎功夫做得更扎實。讓人不禁感嘆于他對“微末功夫”的執著!

很多人好奇Martin為什么決定將《重構》再版?Martin給出了3個原因:

1版里的代碼已經很陳舊了,書里面還有Java.util.Vector;

一些重構并非是與面向對象緊耦合在一起的;

Martin認為Java是一種非常嚴格的面向對象編程語言,而第1版中所有的重構都是基于面向對象的,他想通過再版來說明每個程序員都可以用任何(編程)語言、在任何環境中、遵循書中提到的范例進行重構,這也是他決定再版《重構》的源動力。

Martin認為重構的基本機制不會發生巨大轉變,即使使用面向對象語言工作也是如此。他覺得有一等函數很好,可以嘗試許多函數式的理念,例如,寫軟件時大部分函數都具備引用透明性,這在面向對象系統和在函數式系統中都是好事。

所以Martin不像許多人那樣在函數式編程和面向對象編程間畫出明確界限,他認為兩者有很多共同的地方,未必存在巨大差異。他鼓勵程序員不要有門戶之見,要用綜合理念來解決問題。

對于最新版《重構》,Martin認為有一個重構手法也許值得注意,拆分階段(split phase)。早在幾年前,當Martin和Ken Beck商談拆分階段的時候,Martin第一次意識到這也是重構手法。

通過這種重構手法,Martin將大量計算合理分為兩個階段,使用中間數據結構進行通信。其中一個例子是解析拆分階段可有效地將token從解析中抽離出來,這樣就得到了一個可可保存在存儲器種的token流,可處理相關字符串、文本字符串。

而說到重構工具,Martin和Kent做了很多年了,但他們從來沒有意識到工具的重要性;當他們意識到這一點之后,他們感覺重構工具已經無處不在,他們認為這個內容非常重要,然后Martin就真把這些新內容加到新版中了。

重構的關鍵是理念:通過進行最細微的改變,然后將這些變化串聯起來,這就是重構思維核心。將一個大變化拆分為許多小變化,又在盡可能多進行細微變化的同時,不改變系統的整體表現,然后隨時間推移,反復練習并思考如何進行拆分。Martin在《重構 2》一書中說過,他通過重構框架思考問題的體驗,嘗試各種高效的重構手法并做出決定,最重要的就是通過實踐進行重構。

他認為在嘗試了不同的重構手法后,找出能重構手法生成理想序列,繼而進行嘗試識別出這種重構手法,而同樣的邏輯也適用于更廣泛的層面。

因此,他采用了70多個種可行的重構,并且把每個重構都介紹了一種經過驗證的代碼變換手法的動機和技術。就像軟件開發的大多數工作一樣,重構除了動手做,別無他法,必須反復實踐,必須在項目中使用重構。

Martin始終希望,重構準則能幫助大家一步步修改自己的代碼,減少了開發過程中的風險。


重構=編碼

在日新月異的 IT 技術世界里,不變的東西其實還是有的——重構。

從《重構》的英文原版引進國內,到現在已經過去20年了。Martin  Fowler 這次對本書進行的重構,體現了近年來編程領域的一些思潮變化,既有設計,又永遠有改進空間。

盡管時間是最強大的重構工具,連書里的示例語言都從 Java 變成 JavaScript 了,但書中的理念和實踐的價值并沒有隨時間流逝。

重構早就成了軟件開發從業者本能的一部分,每個 IDE 都內置了重構功能,每個程序員都定期重構自己的代碼。

對于軟件工程師來說,重構,并不是額外的工作,它就是編碼本身。切實地讀懂了《重構》的軟件工程師,在能力上都會獲得一個數量級的提升。

 

  • 有玩快乐8的吗