本書運用大量源於實踐的示例,從編碼、設計、組織、架構、測試、評估、應對需求變更等方面,深入而多角度地講述了我們應該如何重構,建設性地提出了高效可行的重構七步。讀完本書,實踐重構不再卡殼,需求變更不再糾結。全面領悟重構之美,遺留系統不再是夢魘,自動化測試原來可以這樣做。本書幫助程式設計師告別劣質代碼步入精妙設計,讓遺留系統的維護者逐步改善原有設計,指導重構實踐者走出困惑步步堅定。同時,也為管理者加強軟體質量的管理與監督,提供了好的方法與思路。
基本介紹
- 書名:大話重構
- 出版社:人民郵電出版社
- 頁數:256頁
- 開本:16
- 品牌:人民郵電出版社
- 作者:范鋼
- 出版日期:2014年5月1日
- 語種:簡體中文
- ISBN:9787115348852
基本介紹,內容簡介,作者簡介,圖書目錄,序言,
基本介紹
內容簡介
本書的最大價值在於兩點:
一,讓讀者明白真正的專業級軟體開發是如何進行的;
二,讓讀者明白真正的重構具體是一步步怎么做的。
作者將繁複冗長模糊不清的軟體重構過程劃分成明確而清晰的七個步驟。使初學者在面對實際中的軟體重構時,不會卡殼。
本書所講解的重構遠遠超越了代碼級,充分滲透到軟體系統與設計的各個層面,涵蓋從代碼、函式、類與對象,直至設計模式、分層架構、領域模型、軟體測試的整個過程。
你聽過或沒聽過的那些術語和概念,多少明白或完全不明白的技術和方法,知道卻沒用過或完全不知道的工具和軟體,這些之前各玩各的的獨立散碎,在這本書中被榫卯成一個強韌的整體。你會明了它們中每一個的作用,應被安插到的位置,並見識它們各就各位時所發揮出的能量。頭腦從未有過的清醒,你理解了以前所不理解的。
一,讓讀者明白真正的專業級軟體開發是如何進行的;
二,讓讀者明白真正的重構具體是一步步怎么做的。
作者將繁複冗長模糊不清的軟體重構過程劃分成明確而清晰的七個步驟。使初學者在面對實際中的軟體重構時,不會卡殼。
本書所講解的重構遠遠超越了代碼級,充分滲透到軟體系統與設計的各個層面,涵蓋從代碼、函式、類與對象,直至設計模式、分層架構、領域模型、軟體測試的整個過程。
你聽過或沒聽過的那些術語和概念,多少明白或完全不明白的技術和方法,知道卻沒用過或完全不知道的工具和軟體,這些之前各玩各的的獨立散碎,在這本書中被榫卯成一個強韌的整體。你會明了它們中每一個的作用,應被安插到的位置,並見識它們各就各位時所發揮出的能量。頭腦從未有過的清醒,你理解了以前所不理解的。
作者簡介
范鋼
1999年畢業於重慶大學,後攻讀哈爾濱工業大學軟體工程碩士。參與過國內數十個大型軟體研發項目,現任航天信息股份有限公司系統架構師,先後擔任過軟體工程師、需求分析員、主管設計師、項目經理、系統架構師等各項職務。長期關注軟體設計與質量的基礎理論研究。
2007年開始寫作,先後發表了《一個優秀軟體開發人員的必修課》、《談談軟體開發那些事兒》、《一堂如何提高代碼質量的培訓課》、《一次疊代式開發的研究》等系列文章。
《大話重構》是我的第一部著作。
部落格:fangang.iteye.com
信箱:[email protected]
1999年畢業於重慶大學,後攻讀哈爾濱工業大學軟體工程碩士。參與過國內數十個大型軟體研發項目,現任航天信息股份有限公司系統架構師,先後擔任過軟體工程師、需求分析員、主管設計師、項目經理、系統架構師等各項職務。長期關注軟體設計與質量的基礎理論研究。
2007年開始寫作,先後發表了《一個優秀軟體開發人員的必修課》、《談談軟體開發那些事兒》、《一堂如何提高代碼質量的培訓課》、《一次疊代式開發的研究》等系列文章。
《大話重構》是我的第一部著作。
部落格:fangang.iteye.com
信箱:[email protected]
圖書目錄
第一部分 基礎篇
第1章 重構:改變既有代碼的一劑良藥
1.1 什麼是系統重構
1.2 在保險索上走鋼絲
1.3 大布局與小步快跑
1.4 軟體修改的四種動機
1.5 一個真實的謊言
第2章 重構方法工具箱
2.1 重構是一系列的等量變換——第一次HelloWorld重構
2.2 盤點我們的重構工具箱——對HelloWorld抽取類和接口
第3章 小步快跑的開發模式
3.1 大布局你傷不起
3.2 小設計而不是大布局
3.3 小步快跑是這樣玩的——HelloWorld重構完成
第4章 保險索下的系統重構
4.1 你不能沒有保險索
4.2 自動化測試——想說愛你不容易
4.3 我們是這樣自動化測試的——JUnit下的HelloWorldTest
4.4 採用Mock技術完成測試
第二部分 實踐篇
第5章 第一步:從分解大函式開始
5.1 超級大函式——軟體退化的重災區
5.2 抽取方法的實踐
5.3 最常見的問題 5
第6章 第二步:拆分大對象
6.1 大對象的演化過程
6.2 大對象的拆分過程——抽取類與職責驅動設計
6.3 單一職責原則(SRP)與對象拆分
6.4 合久必分,分久必合——類的歸併
第7章 第三步:提高代碼復用率
7.1 順序編程的煩惱
7.2 代碼重複與DRY原則
7.3 提高代碼復用的方法
7.3.1 當重複代碼存在於同一對象中時——抽取方法
7.3.2 當重複代碼存在於不同對象中時——抽取類
7.3.3 不同對象中復用代碼的另一種方法——封裝成實體類
7.3.4 當代碼所在類具有某種並列關係時——抽取父類
7.3.5 當出現繼承泛濫時——將繼承轉換為組合
7.3.6 當重複代碼被割裂成碎片時——繼承結合模板模式
7.4 代碼重複的檢查工具
第8章 第四步:發現程式可擴展點
8.1 開放?封閉原則與可擴展點設計
8.2 過程的擴展與放置鉤子——運用模板模式增加可擴展點
8.3 面向切面的可擴展設計
8.4 其他可擴展設計
第9章 第五步:降低程式依賴度
9.1 接口、實現與工廠模式
9.1.1 徹底理解工廠模式和依賴反轉原則
9.1.2 工廠模式在重構中的實際運用
9.2 外部接口與適配器模式——與外部系統解耦
9.3 繼承的泛濫與橋接模式
9.4 方法的解耦與策略模式
9.5 過程的解耦與命令模式
9.6 透明的功能擴展與設計——組合模式與裝飾者模式
第10章 第六步:我們開始分層了
10.1 什麼才是我們需要的分層
10.2 怎樣才能擁抱需求的變化
10.3 貧血模型與充血模型
10.4 我們怎樣面對技術的變革
第11章 一次完整的重構過程
11.1 第一步:分解大函式
11.2 第二步:拆分大對象
11.3 第三步:提高復用率
11.4 第四步:發現擴展點
11.5 第五步:降低依賴度
11.6 第六步:分層
11.7 第七步:領域驅動設計
第三部分 進階篇
第12章 什麼時候重構
12.1 重構是一種習慣
12.2 重構讓程式可讀
12.3 重構,才好復用
12.4 先重構,再擴展
12.5 變更任務緊急時,又該如何重構
第13章 測試驅動開發
13.1 測試驅動開發(TDD)vs.後測試開發(TAD)
13.2 測試驅動開發與重構
13.3 遺留系統怎樣開展TDD
第14章 全面的升級任務
14.1 計畫式設計vs.演進式設計
14.2 風險驅動設計
14.3 制定系統重構計畫
第15章 我們怎樣擁抱變化
15.1 領域才是軟體系統的“心”——工資軟體的三次設計演變
15.2 領域模型分析方法
15.3 原文分析法
15.4 領域驅動設計——使用領域模型與客戶一起設計
15.5 在遺留系統中的套用
第16章 測試的困境
16.1 重構初期的困局
16.2 解耦與自動化測試
16.3 開發人員,還是測試人員
16.4 建立自動化測試體系
第17章 系統重構的評價
17.1 評價軟體質量的指標
17.2 怎樣評價軟體質量呢
結束語:重構改變了世界
附錄
第1章 重構:改變既有代碼的一劑良藥
1.1 什麼是系統重構
1.2 在保險索上走鋼絲
1.3 大布局與小步快跑
1.4 軟體修改的四種動機
1.5 一個真實的謊言
第2章 重構方法工具箱
2.1 重構是一系列的等量變換——第一次HelloWorld重構
2.2 盤點我們的重構工具箱——對HelloWorld抽取類和接口
第3章 小步快跑的開發模式
3.1 大布局你傷不起
3.2 小設計而不是大布局
3.3 小步快跑是這樣玩的——HelloWorld重構完成
第4章 保險索下的系統重構
4.1 你不能沒有保險索
4.2 自動化測試——想說愛你不容易
4.3 我們是這樣自動化測試的——JUnit下的HelloWorldTest
4.4 採用Mock技術完成測試
第二部分 實踐篇
第5章 第一步:從分解大函式開始
5.1 超級大函式——軟體退化的重災區
5.2 抽取方法的實踐
5.3 最常見的問題 5
第6章 第二步:拆分大對象
6.1 大對象的演化過程
6.2 大對象的拆分過程——抽取類與職責驅動設計
6.3 單一職責原則(SRP)與對象拆分
6.4 合久必分,分久必合——類的歸併
第7章 第三步:提高代碼復用率
7.1 順序編程的煩惱
7.2 代碼重複與DRY原則
7.3 提高代碼復用的方法
7.3.1 當重複代碼存在於同一對象中時——抽取方法
7.3.2 當重複代碼存在於不同對象中時——抽取類
7.3.3 不同對象中復用代碼的另一種方法——封裝成實體類
7.3.4 當代碼所在類具有某種並列關係時——抽取父類
7.3.5 當出現繼承泛濫時——將繼承轉換為組合
7.3.6 當重複代碼被割裂成碎片時——繼承結合模板模式
7.4 代碼重複的檢查工具
第8章 第四步:發現程式可擴展點
8.1 開放?封閉原則與可擴展點設計
8.2 過程的擴展與放置鉤子——運用模板模式增加可擴展點
8.3 面向切面的可擴展設計
8.4 其他可擴展設計
第9章 第五步:降低程式依賴度
9.1 接口、實現與工廠模式
9.1.1 徹底理解工廠模式和依賴反轉原則
9.1.2 工廠模式在重構中的實際運用
9.2 外部接口與適配器模式——與外部系統解耦
9.3 繼承的泛濫與橋接模式
9.4 方法的解耦與策略模式
9.5 過程的解耦與命令模式
9.6 透明的功能擴展與設計——組合模式與裝飾者模式
第10章 第六步:我們開始分層了
10.1 什麼才是我們需要的分層
10.2 怎樣才能擁抱需求的變化
10.3 貧血模型與充血模型
10.4 我們怎樣面對技術的變革
第11章 一次完整的重構過程
11.1 第一步:分解大函式
11.2 第二步:拆分大對象
11.3 第三步:提高復用率
11.4 第四步:發現擴展點
11.5 第五步:降低依賴度
11.6 第六步:分層
11.7 第七步:領域驅動設計
第三部分 進階篇
第12章 什麼時候重構
12.1 重構是一種習慣
12.2 重構讓程式可讀
12.3 重構,才好復用
12.4 先重構,再擴展
12.5 變更任務緊急時,又該如何重構
第13章 測試驅動開發
13.1 測試驅動開發(TDD)vs.後測試開發(TAD)
13.2 測試驅動開發與重構
13.3 遺留系統怎樣開展TDD
第14章 全面的升級任務
14.1 計畫式設計vs.演進式設計
14.2 風險驅動設計
14.3 制定系統重構計畫
第15章 我們怎樣擁抱變化
15.1 領域才是軟體系統的“心”——工資軟體的三次設計演變
15.2 領域模型分析方法
15.3 原文分析法
15.4 領域驅動設計——使用領域模型與客戶一起設計
15.5 在遺留系統中的套用
第16章 測試的困境
16.1 重構初期的困局
16.2 解耦與自動化測試
16.3 開發人員,還是測試人員
16.4 建立自動化測試體系
第17章 系統重構的評價
17.1 評價軟體質量的指標
17.2 怎樣評價軟體質量呢
結束語:重構改變了世界
附錄
序言
【前言】
我常常感到幸運,我們現在所處的是一個令人振奮的時代,我們進入了軟體工業時代。在這個時代里,我們進行軟體開發已經不再是一個一個的小作坊,我們在進行著集團化的大規模開發。我們開發的軟體不再是為某個車間、某個工序設計的輔助工具,它從某個單位走向整個集團,走向整個行業,甚至整個社會,發揮著越來越重要的作用。一套軟體所起到的作用與影響有多大,已經遠遠超越了所有人的想像,成為一個地區、一個社會,乃至整個國家不可或缺的組成部分。慢慢地,人們已經難以想像沒有某某軟體或系統的生活和工作會是怎樣的。這就是軟體工業時代的重要特徵。
然而,在這個令人振奮的軟體工業時代,處於時代中心的各大軟體企業卻令人沮喪。在軟體規模越來越龐大,軟體結構越來越複雜的同時,卻是軟體質量越來越低下,軟體維護變得越來越困難,以至於每個小小的變更都變得需要傷筋動骨。研發人員為此手足無措,測試人員成為唯一的救星,每個小小的變更都需要付出巨大代價進行測試。軟體企業在這樣一種惡性循環中苦苦支撐。毫無疑問,這也成為這個令人振奮的時代的另一個特徵。
是的,面對軟體工業時代我們並沒有做好準備。過去,一套軟體的生命周期不過2~3年時間,隨著軟體需求的變化,我們總是選擇將軟體推倒了重新開發,但是現在這樣的情況在發生著改變。隨著軟體規模的擴大,軟體數據的積累,軟體影響力的提升,我們,以及我們的客戶,都真切地感受到,要推倒一套軟體重新開發,將變得越來越困難且不切實際。這樣的結果就是,我們的軟體將不停地修改、維護、再修改、再維護……直到永遠。這是一件多么痛苦的事情!
一套軟體,當它第一次被開發出來的時候,一切都十分清晰:清晰的業務需求、清晰的設計思路、清晰的程式代碼。但經歷了幾次需求變更與維護以後,一切就變得不那么清晰了。業務需求文檔變得模糊不清,設計思路已經跟不上變更的腳步,程式代碼則隨著業務邏輯的複雜而臃腫不堪。程式設計師開始讀不懂代碼,軟體開發工作變得不再是一種樂趣。
隨著時間的推移,軟體經過數年、數十次的變更與維護,情況變得越來越糟。最初的程式設計師已經不願再看到自己的代碼而選擇離去。他的繼任者們變得更加無所適從,由於看不懂程式,代碼的每一次修改如同在走鋼絲。測試人員變成了唯一的希望,開發人員的每一次修改都意味著測試人員需要把所有程式測試一遍。繼任者們開始質問最初的設計者們,程式是怎么設計的。如果此時恰巧又有什麼新技術出現,就會更顯得原有系統的破舊與不堪。
相信這就是軟體工業時代的所有企業都不得不面對的尷尬境地。難道真的是我們最初的設計錯了嗎?是的,我們都這樣質問過我們自己,因此我們開始嘗試在軟體設計之初投入更多的精力。我們開始投入更多的時間作需求調研,考慮更多可能的需求變化,做更多的接口,實現更加靈活但複雜的設計。然後呢,解決了我們的問題了嗎?顯然是沒有。需求並沒有像我們想像的那樣發生變更:我們之前認為可能發生的變更並沒有發生,使我們為之做出的設計變成了擺設;我們之前沒有考慮到的變更卻發生了,讓我們猝不及防,軟體質量開始下降,我們被打回了原形。難道真的是無藥可解了嗎?在我看來,如果我們沒有看明白軟體開發的規律與特點,那么我們永遠找不到那味嚮往已久的解藥。現在,讓我們真正靜下心來分析分析軟體開發的規律與特點。
軟體,特別是管理軟體,其實質是對真實世界的模擬。我們通過對真實世界的模擬,實現計算機的信息化管理,來提高我們的生產效率。然而,真實的世界複雜而多變的,我們認識世界卻是一個由簡單到複雜循序漸進的過程,這是一個我們無法改變的客觀規律。因此,毫無疑問,遵循著這樣一個客觀規律,我們的軟體開發過程必然也是一個由簡單到複雜循序漸進的過程。
最初,我們開發的是一個對真實世界最簡單、最主要、最核心部分的模擬。因為簡單,我們的思路變得清晰而明了。但是,我們的軟體不能永遠只是模擬那些最簡單、最主要、最核心的部分。我們的客戶在使用軟體的過程中,如果遇到那些不那么簡單、不那么主要、不那么核心的情況時,我們的軟體就無法處理了,這是客戶所不能接受的。因此,當軟體的第一個版本交付客戶以後,客戶的需求就開始變更。
客戶的需求永遠不會脫離真實世界,也就是說,真實世界不存在的事物、現象、關係永遠都不可能出現在軟體需求中。但是,真實世界的事物、規則與聯繫並不是那么地簡單與清晰的。隨著我們的軟體對它模擬得越來越細緻,程式的業務邏輯開始變得不再清晰而易於理解,這就是軟體質量下降最關鍵的內因。
任何一個軟體的設計,總是與軟體的複雜度有密切的關係。舉例來說吧,客戶資料是許多系統都必須要記錄的重要信息。起初,我們程式簡單,客戶資料只記錄了一些簡單的信息,如客戶名稱、地址、電話等等,但隨著程式複雜度的增加,客戶資料開始變得複雜。比如,起初“地址”欄位就僅僅需要一個字元串就可以了,但隨著需求的變更,它開始有了省份、城市、地區、街道等信息。隨後還會有郵政編碼、所屬社區、派出所等信息。起初增加一個兩個欄位時我們還可以在“客戶信息表”里湊合一下,但後來我們必須要及時調整我們的設計,將地址提取出來單獨形成一個“地址信息表”。如果不及時予以調整,“客戶信息表”將越來越臃腫,由10來個欄位,變成50個、80個、上100個……
信息表尚且如此,業務操作更是如此。起初的業務操作是如此地簡單而明了,以至於我們不需要花費太多的類就可以將它們描述清楚。比如開票操作,最初的需求就是將已開具的票據信息讀取出來,保存,並統計出本月開票量及金額。這樣一個簡單操作,設計成一個簡單的“開票業務類”合情合理。但隨後的業務邏輯變得越來越複雜,我們要檢查客戶是否存在、開票人是否有許可權、票據是否還有庫存,等等。起初的開票方式只有一種,但隨著非正常開票的加入,開票方式不再單一,而統計方式也隨之變化……隨著業務的不斷增加,軟體代碼的規模也在發生著質的變化。如果這時我們不及時調整我們的設計,而是將所有的程式都硬塞進“開票業務類”,那么程式質量必然會退化。“開票業務類”由原有的數十行,激增到數百行,甚至上千行。這時的代碼將難於閱讀,維護它將變成一種痛苦,毫無樂趣可言。
面對這樣的狀況,我們應當怎樣走出困境呢?毫無疑問,就是重構。開票前的校驗真的屬於“開票業務類”嗎?它們是否應當被提取出來,解耦成一個一個的校驗類。正常開票與非正常開票真的應該寫在一起嗎?是否我們應當把“開票業務類”抽象成接口,以及正常開票與非正常開票的實現類。這就是我給大家的良方:當軟體因為需求變更而開始漸漸退化時,運用軟體重構改善我們的結構,使之重新適應軟體需求的變化。
范鋼
2014年元旦
我常常感到幸運,我們現在所處的是一個令人振奮的時代,我們進入了軟體工業時代。在這個時代里,我們進行軟體開發已經不再是一個一個的小作坊,我們在進行著集團化的大規模開發。我們開發的軟體不再是為某個車間、某個工序設計的輔助工具,它從某個單位走向整個集團,走向整個行業,甚至整個社會,發揮著越來越重要的作用。一套軟體所起到的作用與影響有多大,已經遠遠超越了所有人的想像,成為一個地區、一個社會,乃至整個國家不可或缺的組成部分。慢慢地,人們已經難以想像沒有某某軟體或系統的生活和工作會是怎樣的。這就是軟體工業時代的重要特徵。
然而,在這個令人振奮的軟體工業時代,處於時代中心的各大軟體企業卻令人沮喪。在軟體規模越來越龐大,軟體結構越來越複雜的同時,卻是軟體質量越來越低下,軟體維護變得越來越困難,以至於每個小小的變更都變得需要傷筋動骨。研發人員為此手足無措,測試人員成為唯一的救星,每個小小的變更都需要付出巨大代價進行測試。軟體企業在這樣一種惡性循環中苦苦支撐。毫無疑問,這也成為這個令人振奮的時代的另一個特徵。
是的,面對軟體工業時代我們並沒有做好準備。過去,一套軟體的生命周期不過2~3年時間,隨著軟體需求的變化,我們總是選擇將軟體推倒了重新開發,但是現在這樣的情況在發生著改變。隨著軟體規模的擴大,軟體數據的積累,軟體影響力的提升,我們,以及我們的客戶,都真切地感受到,要推倒一套軟體重新開發,將變得越來越困難且不切實際。這樣的結果就是,我們的軟體將不停地修改、維護、再修改、再維護……直到永遠。這是一件多么痛苦的事情!
一套軟體,當它第一次被開發出來的時候,一切都十分清晰:清晰的業務需求、清晰的設計思路、清晰的程式代碼。但經歷了幾次需求變更與維護以後,一切就變得不那么清晰了。業務需求文檔變得模糊不清,設計思路已經跟不上變更的腳步,程式代碼則隨著業務邏輯的複雜而臃腫不堪。程式設計師開始讀不懂代碼,軟體開發工作變得不再是一種樂趣。
隨著時間的推移,軟體經過數年、數十次的變更與維護,情況變得越來越糟。最初的程式設計師已經不願再看到自己的代碼而選擇離去。他的繼任者們變得更加無所適從,由於看不懂程式,代碼的每一次修改如同在走鋼絲。測試人員變成了唯一的希望,開發人員的每一次修改都意味著測試人員需要把所有程式測試一遍。繼任者們開始質問最初的設計者們,程式是怎么設計的。如果此時恰巧又有什麼新技術出現,就會更顯得原有系統的破舊與不堪。
相信這就是軟體工業時代的所有企業都不得不面對的尷尬境地。難道真的是我們最初的設計錯了嗎?是的,我們都這樣質問過我們自己,因此我們開始嘗試在軟體設計之初投入更多的精力。我們開始投入更多的時間作需求調研,考慮更多可能的需求變化,做更多的接口,實現更加靈活但複雜的設計。然後呢,解決了我們的問題了嗎?顯然是沒有。需求並沒有像我們想像的那樣發生變更:我們之前認為可能發生的變更並沒有發生,使我們為之做出的設計變成了擺設;我們之前沒有考慮到的變更卻發生了,讓我們猝不及防,軟體質量開始下降,我們被打回了原形。難道真的是無藥可解了嗎?在我看來,如果我們沒有看明白軟體開發的規律與特點,那么我們永遠找不到那味嚮往已久的解藥。現在,讓我們真正靜下心來分析分析軟體開發的規律與特點。
軟體,特別是管理軟體,其實質是對真實世界的模擬。我們通過對真實世界的模擬,實現計算機的信息化管理,來提高我們的生產效率。然而,真實的世界複雜而多變的,我們認識世界卻是一個由簡單到複雜循序漸進的過程,這是一個我們無法改變的客觀規律。因此,毫無疑問,遵循著這樣一個客觀規律,我們的軟體開發過程必然也是一個由簡單到複雜循序漸進的過程。
最初,我們開發的是一個對真實世界最簡單、最主要、最核心部分的模擬。因為簡單,我們的思路變得清晰而明了。但是,我們的軟體不能永遠只是模擬那些最簡單、最主要、最核心的部分。我們的客戶在使用軟體的過程中,如果遇到那些不那么簡單、不那么主要、不那么核心的情況時,我們的軟體就無法處理了,這是客戶所不能接受的。因此,當軟體的第一個版本交付客戶以後,客戶的需求就開始變更。
客戶的需求永遠不會脫離真實世界,也就是說,真實世界不存在的事物、現象、關係永遠都不可能出現在軟體需求中。但是,真實世界的事物、規則與聯繫並不是那么地簡單與清晰的。隨著我們的軟體對它模擬得越來越細緻,程式的業務邏輯開始變得不再清晰而易於理解,這就是軟體質量下降最關鍵的內因。
任何一個軟體的設計,總是與軟體的複雜度有密切的關係。舉例來說吧,客戶資料是許多系統都必須要記錄的重要信息。起初,我們程式簡單,客戶資料只記錄了一些簡單的信息,如客戶名稱、地址、電話等等,但隨著程式複雜度的增加,客戶資料開始變得複雜。比如,起初“地址”欄位就僅僅需要一個字元串就可以了,但隨著需求的變更,它開始有了省份、城市、地區、街道等信息。隨後還會有郵政編碼、所屬社區、派出所等信息。起初增加一個兩個欄位時我們還可以在“客戶信息表”里湊合一下,但後來我們必須要及時調整我們的設計,將地址提取出來單獨形成一個“地址信息表”。如果不及時予以調整,“客戶信息表”將越來越臃腫,由10來個欄位,變成50個、80個、上100個……
信息表尚且如此,業務操作更是如此。起初的業務操作是如此地簡單而明了,以至於我們不需要花費太多的類就可以將它們描述清楚。比如開票操作,最初的需求就是將已開具的票據信息讀取出來,保存,並統計出本月開票量及金額。這樣一個簡單操作,設計成一個簡單的“開票業務類”合情合理。但隨後的業務邏輯變得越來越複雜,我們要檢查客戶是否存在、開票人是否有許可權、票據是否還有庫存,等等。起初的開票方式只有一種,但隨著非正常開票的加入,開票方式不再單一,而統計方式也隨之變化……隨著業務的不斷增加,軟體代碼的規模也在發生著質的變化。如果這時我們不及時調整我們的設計,而是將所有的程式都硬塞進“開票業務類”,那么程式質量必然會退化。“開票業務類”由原有的數十行,激增到數百行,甚至上千行。這時的代碼將難於閱讀,維護它將變成一種痛苦,毫無樂趣可言。
面對這樣的狀況,我們應當怎樣走出困境呢?毫無疑問,就是重構。開票前的校驗真的屬於“開票業務類”嗎?它們是否應當被提取出來,解耦成一個一個的校驗類。正常開票與非正常開票真的應該寫在一起嗎?是否我們應當把“開票業務類”抽象成接口,以及正常開票與非正常開票的實現類。這就是我給大家的良方:當軟體因為需求變更而開始漸漸退化時,運用軟體重構改善我們的結構,使之重新適應軟體需求的變化。
范鋼
2014年元旦