前面我們用了那么多示例討論了代碼復用。毫無疑問,幾乎所有人都明白代碼復用的重要意義,知道要寫好代碼必須要合理地復用代碼。然而,曾經有一份真摯的感情放在你面前你卻沒有珍惜,那就是你應該復用代碼了。等你失去的時候我才后悔莫及,有木有?為什么每當我們應當復用代碼的關鍵時刻,我們卻往往選擇復制粘貼呢?因為道理非常清楚但實際操作起來卻困難重重,因為要實現復用必須要調整原有程序。要調整原有程序,這就不好玩了,我們就不知道該怎樣應對了,還是復制粘貼來得簡單快捷。
有一次,我參與了一個財務系統的研發。我在開發一個功能的時候,發現有個數值型參數,有時候在前端傳過來的時候數據位數或精度會非常大,造成轉型成Number類型的時候會出錯,必須轉型成BigDecimal。同時,前端傳送過來的數據有可能是String類型,也可能是char[]類型。為此我進行了如下的修改:
1 …… 2 Number amount 3 Object value = req.getParameter(“amount”); 4 try{ 5 if (value ==null){ 6 amount = null; 7 } else if (value instanceof Number){ 8 amount = (Number)value; 9 } else if (value instanceof String){ 10 amount = new BigDecimal((String)value).setScale(9, RoundingMode.HALF_UP); 11 } else if (value instanceof char[]){ 12 amount = new BigDecimal((char[])value).setScale(9, RoundingMode.HALF_UP); 13 } else { 14 throw new MsgException("數據不是數字!”);
15 } 16 }catch(NumberFormatException nfe){ 17 throw new MsgException("數據不是數字格式!”); 18 } 19 ……
經過測試,該問題得到了修復。但在隨后的開發中,我發現系統中許許多多從前端獲取數字的程序都需要這段程序。如果當我們每次需要這個功能時都將這段代碼拷貝過去,實現現有的功能當然沒有問題,但卻會為日后的維護埋下隱患。假如有一天這段程序需要調整,難道我們要到整個系統的數百份拷貝中去修改嗎?道理大家都明白,關鍵是這樣的問題卻在無數軟件系統中反復出現。
在這里問題的關鍵在於,要讓這段程序為其它的程序所復用,不修改它自身是根本沒有辦法做到的。我們必須從現有程序中將這段程序提取出來形成一個公用函數,為其它程序所復用,然后將該程序修改成對這個公用程序的引用才行。為此我做出了如下修改:
首先運用“抽取方法”,將這段代碼從其它程序中提取出來,放到工具類中形成一個靜態調用函數:
1 /** 2 * @param value 3 * @return 根據不同的數據格式返回數字類型的數據 4 */ 5 public static Number getNumber(Object value){ 6 if(value==null){return null;} 7 if(value instanceof Number){ 8 return (Number)value; 9 } 10 try{ 11 if(value instanceof String){ 12 return new BigDecimal((String)value).setScale(PRECISION,ROUNDMODE); 13 } 14 if(value instanceof char[]){ 15 return new BigDecimal((char[])value).setScale(PRECISION,ROUNDMODE); 16 } 17 }catch(NumberFormatException nfe){ 18 throw new MsgException("數據不是數字格式!”); 19 } 20 throw new MsgException("數據不是數字!”);
21 }
然后將原程序改為:
1 …… 2 Number amount = XxxUtil.getNumber(req.getParameter(“amount”)); 3 ……
這里,我們運用了重構中“兩頂帽子”的設計方式,先在不增加新功能的情況下,調整原程序內部結構,即抽取出工具類,以此來適應新功能的需要。經過這樣的調整,在實現新功能時就可以大膽復用原有代碼了,復用變得不再那么困難。
然而,我們說,做好代碼復用簡約而不簡單,它考驗的是IT攻城獅的設計水平與開發能力。怎么說呢?有時候我們意識到應該復用了,但真正要寫好復用真的需要下很多功夫。而每一個復用都是一個分析、設計、重構的過程。
沒有經過重構的、原生態的代碼是沒有辦法復用的,但當我們發現代碼需要復用時,切忌不要使用過去那種簡單粗暴的復制粘貼。合理運用重構方法,加之以仔細、認真、及時的測試,可以保證既有代碼的正確,而使整個系統合理地復用起來,以提高系統的可維護性,關鍵是你有沒有這樣的意識。所以,重構是一種習慣。
然而,復用不是銀彈,它不能搞定一切問題。被復用以后,如果公用的代碼出現變更,甚至出現一部分客戶使用舊程序,一部分客戶使用新程序,應當怎么辦呢?呵呵,這下好,老革命遇到了新問題。這常常讓人十分頭疼,而要解決這個問題,我們就進入了一個新的話題,老程序的功能擴展……(續)
相關文檔:
遺留系統:IT攻城獅永遠的痛
需求變更是罪惡之源嗎?
系統重構是個什么玩意兒
我們應當改變我們的設計習慣
小步快跑是這樣玩的(上)
小步快跑是這樣玩的(下)
代碼復用應該這樣做(1)
代碼復用應該這樣做(2)
代碼復用應該這樣做(3)
做好代碼復用不簡單
特別說明:希望網友們在轉載本文時,應當注明作者或出處,以示對作者的尊重,謝謝!