為什麼要重構 從Martin Fowler所著的《重構
改善既有代碼的設計》一書連續兩年成為最暢銷的計算機圖書之一
就可以知道重構給程序員所帶來的欣喜程度了
那麼什麼是重構呢?重構就是在不改變軟件現有功能的基礎上
通過調整程序代碼改善軟件的質量
性能
使其程序的設計模式和架構更趨合理
提高軟件的擴展性和維護性
也許有人會問
為什麼不在項目開始時多花些時間把設計做好
而要以後花時間來重構呢?要知道一個完美得可以預見未來任何變化的設計
或一個靈活得可以容納任何擴展的設計是不存在的
系統設計人員對即將著手的項目往往只能從大方向予以把控
而無法知道每個細枝末節
其次永遠不變的就是變化
提出需求的用戶往往要在軟件成型後
始才開始
品頭論足
系統設計人員畢竟不是先知先覺的神仙
功能的變化導致設計的調整再所難免
所以
測試為先
持續重構
作為良好開發習慣被越來越多的人所采納
測試和重構像黃河的護堤
成為保證軟件質量的法寶
通過重構可以達到以下的目標
持續偏糾和改進軟件設計 重構和設計是相輔相成的
它和設計彼此互補
有了重構
你仍然必須做預先的設計
但是不必是最優的設計
只需要一個合理的解決方案就夠了
如果沒有重構
程序設計會逐漸腐敗變質
愈來愈像斷線的風筝
脫缰的野馬無法控制
重構其實就是整理代碼
讓所有帶著發散傾向的代碼回歸本位
使代碼更易為人所理解 Martin Flower在《重構》中有一句經典的話
任何一個傻瓜都能寫出計算機可以理解的程序
只有寫出人類容易理解的程序才是優秀的程序員
對此
筆者感觸很深
有些程序員總是能夠快速編寫出可運行的代碼
但代碼中晦澀的命名使人暈眩得需要緊握坐椅扶手
試想一個新兵到來接手這樣的代碼他會不會想當逃兵呢?
軟件的生命周期往往需要多批程序員來維護
我們往往忽略了這些後來人
為了使代碼容易被他人理解
需要在實現軟件功能時做許多額外的事件
如清晰的排版布局
簡明扼要的注釋
其中命名也是一個重要的方面
一個很好的辦法就是采用暗喻命名
即以對象實現的功能的依據
用形象化或擬人化的手法進行命名
一個很好的態度就是將每個代碼元素像新生兒一樣命名
也許筆者有點命名偏執狂的傾向
如能榮此雅號
將深以此為幸
對於那些讓人充滿迷茫感甚至誤導性的命名
需要果決地
大刀闊斧地整容
永遠不要手下留情!
幫助發現隱藏的代碼缺陷 孔子說過
溫故而知新
重構代碼時逼迫你加深理解原先所寫的代碼
筆者常有寫下程序後
卻發生對自己的程序邏輯不甚理解的情景
曾為此驚悚過
後來發現這種症狀居然是許多程序員常患的
感冒
當你也發生這樣的情形時
通過重構代碼可以加深對原設計的理解
發現其中的問題和隱患
構建出更好的代碼
從長遠來看有助於提高編程效率 當你發現解決一個問題變得異常復雜時
往往不是問題本身造成的
而是你用錯了方法
拙劣的設計往往導致臃腫的編碼
改善設計
提高可讀性
減少缺陷都是為了穩住陣腳
良好的設計是成功的一半
停下來通過重構改進設計
或許會在當前減緩速度
但它帶來的後發優勢卻是不可低估的
何時著手重構 新官上任三把火
開始一個全新的項目時
程序員往往也會燃起三把火
緊鑼密鼓
腳不停蹄
加班加點
一支聲勢浩大的千軍萬
碼
夾裹著程序員激情和扣擊鍵盤的鳴金奮力前行
勢如破竹
攻城掠地
直指
黃龍府
開發經理是這支浩浩湯湯代碼隊伍的統帥
他負責這支隊伍的命運
當齊恆公站在山頂上看到管仲訓練的隊伍整齊劃一地前進時
他感歎說
我有這樣一支軍隊哪裡還怕沒有勝利呢?
但很遺憾
你手中的這支隊伍原本只是散兵游勇
在前進中招兵買馬
不斷壯大
所以隊伍變形在所難免
當開發經理發覺隊伍變形時
也許就是克制住攻克前方山頭的誘惑
停下腳步整頓隊伍的時候了
Kent Beck提出了
代碼壞味道
的說法
和我們所提出的
隊伍變形
是同樣的意思
隊伍變形的信號是什麼呢?以下列述的代碼症狀就是
隊伍變形
的強烈信號
代碼中存在重復的代碼 中國有
家整車生產企業
數量幾乎等於美
日
歐所有汽車廠家數之和
但是全國的年產量卻不及一個外國大汽車公司的產量
重復建設只會導致效率的低效和資源的浪費
程序代碼更是不能搞重復建設
如果同一個類中有相同的代碼塊
請把它提煉成類的一個獨立方法
如果不同類中具有相同的代碼
請把它提煉成一個新類
永遠不要重復代碼
過大的類和過長的方法 過大的類往往是類抽象不合理的結果
類抽象不合理將降低了代碼的復用率
方法是類王國中的諸侯國
諸侯國太大勢必動搖中央集權
過長的方法由於包含的邏輯過於復雜
錯誤機率將直線上升
而可讀性則直線下降
類的健壯性很容易被打破
當看到一個過長的方法時
需要想辦法將其劃分為多個小方法
以便於分而治之
牽一毛而需要動全身的修改 當你發現修改一個小功能
或增加一個小功能時
就引發一次代碼地震
也許是你的設計抽象度不夠理想
功能代碼太過分散所引起的
類之間需要過多的通訊 A類需要調用B類的過多方法訪問B的內部數據
在關系上這兩個類顯得有點狎昵
可能這兩個類本應該在一起
而不應該分家
過度耦合的信息鏈 計算機是這樣一門科學
它相信可以通過添加一個中間層解決任何問題
所以往往中間層會被過多地追加到程序中
如果你在代碼中看到需要獲取一個信息
需要一個類的方法調用另一個類的方法
層層掛接
就象輸油管一樣節節相連
這往往是因為銜接層太多造成的
需要查看就否有可移除的中間層
或是否可以提供更直接的調用方法
各立山頭干革命 如果你發現有兩個類或兩個方法雖然命名不同但卻擁有相似或相同的功能
你會發現往往是因為開發團隊成員協調不夠造成的
筆者曾經寫了一個頗好用的字符串處理類
但因為沒有及時通告團隊其他人員
後來發現項目中居然有三個字符串處理類
革命資源是珍貴的
我們不應各立山頭干革命
不完美的設計 在筆者剛完成的一個比對報警項目中
曾安排阿朱開發報警模塊
即通過Socket向指定的短信平台
語音平台及客戶端報警器插件發送報警報文信息
阿朱出色地完成了這項任務
後來用戶又提出了實時比對的需求
即要求第三方系統以報文形式向比對報警系統發送請求
比對報警系統接收並響應這個請求
這又需要用到Socket報文通訊
由於原來的設計沒有將報文通訊模塊獨立出來
所以無法復用阿朱開發的代碼
後來我及時調整了這個設計
新增了一個報文收發模塊
使系統所有的對外通訊都復用這個模塊
系統的整體設計也顯得更加合理
每個系統都或多或少存在不完美的設計
剛開始可能注意不到
到後來才會慢慢凸顯出來
此時唯有勇於更改才是最好的出路
缺少必要的注釋 雖然許多軟件工程的書籍常提醒程序員需要防止過多注釋
但這個擔心好象並沒有什麼必要
往往程序員更感興趣的是功能實現而非代碼注釋
因為前者更能帶來成就感
所以代碼注釋往往不是過多而是過少
過於簡單
人的記憶曲線下降的坡度是陡得嚇人的
當過了一段時間後再回頭補注釋時
很容易發生
提筆忘字
愈言且止
的情形
曾在網上看到過微軟的代碼注釋
其詳盡程度讓人歎為觀止
也從中體悟到了微軟成功的一個經驗
From:http://tw.wingwit.com/Article/program/Java/hx/201311/25897.html