怎么對經理說?
技術復審是減少錯誤,提高開發速度的一條重要途徑,隨便找一些關于復審、審查或軟件的開發程序的書看看,從中找些最新引證,應該可以讓大多數經理認識復審的價值。然后你就可以把重構當作“將復審意見引入代碼內”的方法來使用。
間接層的價值
允許邏輯共享。比如說一個子函數在兩個不同的地點被調用,或superclass中的某個函數被所有subclasses共享。
分開解釋"意圖"和"實現"。你可以選擇每個class和函數的名字,這給了你一個解釋自己意圖的機會。class或函數內部則解釋實現這個意圖的做法。如果class和內部函數又以“更小單元的意圖”來編寫,你所寫的代碼就可以“與其結構中的大部分重要信息溝通”。
將變化加以隔離。很可能我在兩個不同地點使用同一對象,其中一個地點我想改變對象行為,但如果修改了它,我就要冒“同時影響兩處”的風險。為此我做出一個subclass,并在需要修改處引用這個subclass。這樣我就可以修改這個subclass而不必承擔“無意中影響另一處”的風險。
將條件邏輯加以編碼。對象有一種匪夷所思的機制:多態消息,可以靈活而清晰的表達條件邏輯。只要顯式條件邏輯被轉化為消息形式,往往便能夠降低代碼的重復,增加清晰度并提高彈性。
推測性設計總是試圖在任何一行代碼誕生之前就先讓系統擁有所有優秀質量,然后程序員將代碼塞進這個強健的骨架就行了。這個過程的問題在于:太容易猜錯。如果運用重構,你就永遠不會面臨全盤錯誤的危險。
還有一種比較少見的重構游戲:找出不值得的間接層,并將它拿掉。這種間接層常以中介函數的形式出現,也許曾有有過貢獻,但芳華已逝。它也可能是個組件,你本來期望在不同地點共享它,或讓他表現出多態性,最終卻只在一處使用之。如果你找到這種“寄生式間接層”,請把它扔掉。如此一來你會獲得一個更有價值的程序,不是因為它取得了更多的四種優秀質量,而是因為它以更少的間接層獲得一樣多的優秀質量。
數據庫
就算你非常小心的將系統分層,將database schema和對象模型間的依賴降至最低,但database schema的改變還是讓你不得不遷移所有數據,這可能是件漫長而繁瑣的工作。
修改接口
只有當需要修改的接口被那些找不到,即使找到也不能修改的代碼使用時,接口的修改才會成為問題。這種接口被稱之為“已發布接口”。比公開接口更進一步。接口一旦發布,你就再也無法僅僅修改調用者而能夠安全的修改接口了。
如果重構手法改變了已發布接口,你必須同時維護新舊兩個接口,直到你的所有用戶都有時間對這個變化做出反應。幸運的是這不太困難。你通常都有辦法把事情組織好,讓舊接口繼續工作。請盡量這么做:讓舊接口調用新接口。當你需要修改某個函數名稱時,請留下舊函數,讓它調用新函數。千萬不要拷貝函數實現碼,那會讓你陷入“重復代碼”的泥淖中難以自拔。你還應該使用java提供的deprecated(反對)關鍵字,標記舊接口。這么一來你的調用者就會注意它了。
過渡強調代碼擁有權的團隊常常會犯過量發布接口的錯誤。除非真有必要,別發布接口。讓每個人都可以修改別人的代碼,以運應接口的改動。Pair Programming通常是個好主意。
對于會出現不可控異常的情況,通常可以在包中創建一個超類異常,然后讓所有的public函數只在自己的throws 子句中聲明這個異常。這樣就可以隨心所欲的定義子類異常,不會影響調用者。因為調用者永遠只知道subperclass異常。
這里可以 寫一個例子:
開始的時候,我的電腦只有鍵盤這種輸入工具,所以我可以這樣定義我的“電腦”類:
public interface Computer {
void input() throws KeyBoardException;
}
它會拋出鍵盤異常。后來,我的電腦又有了鼠標這種設備,所以要想保證鼠標的使用過程中所產生的錯誤是可控的,只能這樣修改接口:
public interface Computer {
void input() throws KeyBoardException,MouseException;
}
這樣就導致了接口被修改,涉及這個接口的實現者需要作出修改,否則不能編譯通過;但是不這樣做的話,鼠標輸入的異常就會變為不可控異常。所以書中提倡這樣做:
public interface Computer {
void input() throws InputDeviceException;
}
其中InputDeviceException是所有輸入設備異常的超類,這樣既不用修改實現者的代碼,也保證了這些異常是可控的。
posted on 2007-06-22 22:59
littlegai 閱讀(174)
評論(0) 編輯 收藏 引用