網路上已經有許多重複程式碼的文章,因為這是非常基本的原則。
- 石一楹:重複的程式碼:用DavidHooker 提出的 7 個軟體開發原則說明為什麼不要複製貼上
- pajace2001:軟體路上不孤單Day09-物件導向原則介紹-DRY:介紹The Pragmatic Programmer一書中將DRY分成四大部分
- MSDN-利用程式碼複製品偵測尋找重複程式碼:介紹Visual Studio中尋找重複程式碼的工具。
書中有一段話我覺得很有意思:
關乎特定問題發掘通用解決方案,不是重利用既有的通用方法,就是設法讓既有的方法變得更通用。
如何遵守此指導方針
若要取代程式碼的複製貼上,最常見的方式就是之前提到的重構手法-Extract Method
。遇到相同甚至類似的邏輯,都可以試著建立一個通用method以重複使用。
這在一個class中可行,但如果兩個class都有相同的邏輯需要時做呢?通常我們會建立一個helper class以讓各自class進行叫用。但這個class很對就會變成一堆互不相關之方法的大雜燴,導致類別體積龐大且過度緊密耦合。這是一種程式碼「壞味道」。
這時候,有一個重構手法可能可以處理這個問題-Extract Superclass
。也就是利用繼承機制,將共用method放到父類別中。
當然,要使用這個手法,前提是這兩個class必須是相關且適合建立繼承關係的。
常見的反對意見
試著反向思考這個問題
應該允許從其他程式碼基礎複製程式碼
「從其他程式碼基礎複製及貼上程式碼不是問題,因為那樣並未在目前系統中產生重複程式碼」
技術上而言,這樣說並沒錯,它的確沒有在目前系統中產生重複的程式碼。不過,考慮到未來來源程式碼修改維護,甚至停用的情境。最好的方式還是用reference的方式,叫用所需的method。
細微的變異無可避免,因而導致程式碼重複
「在我們的情況中,重複程式碼無可避免,因為我們的通用功能性存在著細微的變異」
確實如此,不過作者建議還是要異中求同,找出這些程式碼當中相同的部分,然後將它們移到共用的父類別。
這段程式碼永遠不會改變
「這段程式碼永遠不會改變,所以重複也沒關係」
如果可以百分之百的確定程式碼永遠不會改變,重複程式碼確實就不是問題。不過,這幾乎是不可能的事。
單元測試會幫我發現問題
「單元測試會澄清重複程式碼是否出現問題」
作者建議不能只依賴單元測試發現問題,而不解決問題的根源。不應該假設所有問題,最後都會在後續的開發流程中獲得解決。
字串實字的重複是不可避免且無害的
「我需要冗長的字串實字,其中包含許多重複。這樣的重複無可避免,而且因為只是實字,所以不會有甚麼傷害」
作者認為,久了還是會累積出傷害。可以使用Extract Method
,搭配參數來處理當中的差異性。或是使用模板引擎。