大話重構連載1:遺留系統——軟件工業時代的痛


我常常感到幸運,我們現在所處的是一個令人振奮的時代,我們進入了軟件工業時代。在這個時代里,我們進行軟件開發已經不再是一個一個的小作坊,我們在進行着集團化的大規模開發。我們開發的軟件不再是為某個車間、某個工序設計的輔助工具,它從某個單位走向整個集團,走向整個行業,甚至整個社會,發揮着越來越重要的作用。一套軟件所起到的作用與影響有多大,已經遠遠超越了所有人的想象,成為一個地區、一個社會,乃至整個國家不可或缺的組成部分。慢慢地,人們已經難以想象沒有某某軟件或系統的生活和工作會是怎樣的。這就是軟件工業時代的重要時代特征。

然而,在這個令人振奮的軟件工業時代,處於時代中心的各大軟件企業卻令人沮喪。軟件規模越來越龐大,軟件結構越來越復雜的同時,卻是軟件質量越來越低下,軟件維護變得越來越困難,以至於每個小小的變更都變得需要傷筋動骨。研發人員為此舉足無措,測試人員成為唯一的救星,每個小小的變更都需要付出巨大代價進行測試。軟件企業在這樣一種惡性循環中苦苦支撐。毫無疑問,這也成為這個令人振奮的時代的另一個特征。

是的,面對軟件工業時代我們並沒有做好准備。過去,一套軟件的生命周期不過2~3年時間,隨着軟件需求的變化,我們總是選擇將軟件推倒了重新開發,但是現在這樣的情況在發生着改變。隨着軟件規模的擴大,軟件數據的積累,軟件影響力的提升,我們,以及我們的客戶,都真切地感受到,要推倒一套軟件重新開發,將變得越來越困難而不切實際。這樣的結果就是,我們的軟件將不停地修改、維護、再修改、再維護……直到永遠。這是一件多么痛苦的事情啊!

一套軟件,當它第一次被開發出來的時候,一切都十分清晰:清晰的業務需求、清晰的設計思路、清晰的程序代碼。但經歷了幾次需求變更與維護以后,一切就變得不那么清晰了。業務需求文檔變得模糊不清,設計思路已經跟不上變更的腳步,程序代碼則隨着業務邏輯的復雜而臃腫不堪。程序員開始讀不懂代碼,軟件開發工作變得不再是一種樂趣。

隨着時間的推移,軟件經過數年、數十次的變更與維護,情況變得越來越糟。最初的程序員已經不願再看到自己的代碼而選擇離去。他的繼任者們變得更無所是從,由於看不懂程序,代碼的每一次修改如同在走鋼絲。測試人員變成了唯一的希望,開發人員的每一次修改都意味着測試人員需要把所有程序測試一遍。繼任者們開始質問最初的設計者們,程序是怎么設計的。如果此時恰巧又有什么新技術出現,就會更顯得原有系統的破舊與不堪。

相信這就是軟件工業時代的所有企業都不得不面對的尷尬境地。難倒真的是我們最初的設計錯了嗎?是的,我們都這樣質問過我們自己,因此我們開始嘗試在軟件設計之初投入更多的精力。我們開始投入更多的時間作需求調研,考慮更多可能的需求變化,做更多的接口,實現更加靈活但復雜的設計。然后呢,我們解決了我們的問題了嗎?顯然是沒有。需求並沒有像我們想象的那樣發生變更:我們之前認為可能發生的變更並沒有發生,使我們為之做出的設計變成了擺設;我們之前沒有考慮到的變更發生了,讓我們猝不及防,軟件質量開始下降,我們被打回了原形。難倒真的是無葯可解了嗎?在我看來,如果我們沒有看明白軟件開發的規律與特點,那么我們永遠找不到那份向往已久的解葯。現在,讓我們真正靜下心來分析分析軟件開發的規律與特點吧。

軟件,特別是管理軟件,其實質是對真實世界的模擬。我們通過對真實世界的模擬,實現計算機的信息化管理,來提高我們的生產效率。然而,真實的世界復雜而多變的,我們認識世界卻是一個由簡單到復雜循序漸進的過程,這是一個我們無法改變的客觀規律。因此,毫無疑問,遵循着這樣一個客觀規律,我們的軟件開發過程必然也是一個由簡單到復雜循序漸進的過程。

最初,我們開發的是一個對真實世界最簡單、最主要、最核心部分的模擬。因為簡單,我們的思路變得清晰而明了。但是,我們的軟件不能永遠只是模擬那些最簡單、最主要、最核心的部分。我們的客戶在使用軟件的過程中,如果遇到那些不那么簡單、不那么主要、不那么核心的情況時,我們的軟件就無法處理了,這是客戶無論如何不能接受的。因此,但軟件的第一個版本交付客戶以后,客戶的需求就開始變更。

客戶的需求永遠不會脫離真實世界,也就是說,真實世界不存在的事物、現象、關系永遠都不可能出現在軟件需求中。但是,真實世界的事物、規則與聯系並不是那么的簡單與清晰的。隨着我們的軟件對它模擬得越來越細致,程序的業務邏輯開始變得不再那么清晰而易於理解,這就是軟件質量下降最關鍵的內因。

任何一個軟件的設計,總是與軟件的復雜度有密切的關系。舉例來說吧,客戶資料是許多系統都必須要記錄的重要信息。起初,我們程序簡單,客戶資料只記錄了一些簡單的信息,如客戶名稱、地址、電話等等,但隨着程序復雜度的增加,客戶資料開始變得復雜。比如,起初“地址”字段就僅僅需要一個字符串就可以了,但隨着需求的變更,它開始有了省份、城市、地區、街道等信息。隨后還會有郵政編碼、所屬社區、派出所等信息。起初增加一個兩個字段時我們還可以在“客戶信息表”里湊合一下,但后來我們必須要及時調整我們的設計,將地址提取出來單獨形成一個“地址信息表”。如果不及時予以調整,“客戶信息表”將越來越臃腫,由10來個字段,變成50個、80個、上100個……

信息表尚且如此,業務操作更是如此。起初的業務操作是如此的簡單而明了,以至於我們不需要花費太多的類就可以將它們描述清楚。比如開票操作,最初的需求就是將已開具的票據信息讀取出來,保存,並統計出本月開票量及金額。這樣一個簡單操作,設計成一個簡單的“開票業務類”合情合理。但隨后的業務邏輯變得越來越復雜,我們要檢查客戶是否存在、開票人是否有權限、票據是否還有庫存,等等。起初的開票方式只有一種,但隨着非正常開票的加入,開票方式不再單一,而統計方式也隨之變化……隨着業務的不斷增加,軟件代碼的規模也在發生着質的變化。如果這時我們不及時調整我們的設計,而是將所有的程序都硬塞進“開票業務類”,那么程序質量必然會退化。“開票業務類”由原有的數十行,激增到數百行,甚至上千行。這時的代碼將難於閱讀,維護它將變成一種痛苦,毫無樂趣可言。

面對這樣的狀況,我們應當怎樣走出困境呢?毫無疑問,就是重構,軟件的重構。開票前的校驗真的屬於“開票業務類”嗎?它們是否應當被提取出來,解耦成一個一個的校驗類。正常開票與非正常開票真的應該寫在一起嗎?是否我們應當把“開票業務類”抽象成接口,以及正常開票與非正常開票的實現類。這就是我給大家的良方:當軟件因為需求變更而開始漸漸退化時,運用軟件重構改善我們的結構,使之重新適應軟件需求的變化。

 

大話重構連載首頁:http://www.cnblogs.com/mooodo/p/talkAboutRefactoringHome.html

特別說明:希望網友們在轉載本文時,應當注明作者或出處,以示對作者的尊重,謝謝!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM