簡單設計

XP(極限編程)裏除了大名鼎鼎的TDD,重構等最佳實踐外還有一些不怎麼被人注意的實踐,比如本文想談的簡單設計(Simple Design)。

我們常常說設計要簡單,簡單即美。甚至敏捷軟件開發的四個要素(溝通、反饋、簡單、勇氣)簡單也位於其中。那到底什麼是XP開發者眼中所認爲的簡單呢?

在Kent Beck所著的《解析極限編程》裏對簡單設計有四條“簡單”的描述,通常也被大家稱爲簡單設計四原則:

通過所有測試

體現所有意圖

消除重複

類和方法儘量短小

可能和原文有所出入,順序也不同(注:我這裏列出的順序不代表它的優先級),但要表達的意思是這樣的。

通過所有測試

對於通過所有測試這一條,它是與XP的另外一個實踐TDD相輔相成的。通過所有測試不僅僅表明程序運行“正確(正確是相對的)”。更重要的是一種設計態度。

要通過測試就得能寫測試,要爲程序編寫測試並不是一件容易的事情,“複雜”或“混亂”的程序是很難測試的。可測試性本來就是設計質量的一項考量標準。鐵板一塊的程序無法很容易解耦,要對其進行測試只有在鐵板的外圍進行測試,測試的粒度如此之大,先不說是否好構建測試,即使測試構建好了,如果測試失敗了也很難發現問題之所在。

所以光滿足可測試性這一條就要死傷很多腦細胞。你得讓該模塊所依賴的東西能輕鬆的“注入”進去,這樣就能解耦,這樣就能單獨對這個模塊進行測試,這樣就能在更小的粒度上進行測試。

比如很簡單的一個實例,我們做一個計算稅率的程序,假設稅率的獲取依靠第三方系統提供,那我們在開發之前可以將其劃分爲幾個任務:

  1. 輸入金額
  2. 計算(從第三方獲取稅率)
  3. 輸出結果

很好,我們可以這樣“即興設計”出一個方法:

從終端讀入金額,然後實例化一個第三方的“本地代理對象”,調用其接口獲取稅率,然後計算,得到結果後輸出到終端。

很簡單是不,但是這個方法如何測試呢?你也許可以說:我們可以重定向終端到文件,這樣就可以提供測試數據並得到輸出,那麼第三方系統呢?

我們想想,對於這個小程序,我們最關心的是計算邏輯是否正確,對於從終端讀入、從第三方獲取稅率以及輸出到終端都是較難測試的,我們必須把這個依賴解耦,然後就可以對計算邏輯測試了。

解開依賴實際上還不能完全滿足可測試性的要求,要這個測試容易構建還得看看你到底有多少依賴。我們常常將一個測試分爲三段式:

Given

這裏用來構建依賴,以及輸入對象

When

這裏調用被測試元素

Then

這裏用來測試結果

常常有這樣的測試,它的Given段非常長,而When和Then非常短小。這就是一種信號:這個玩意兒依賴的東西太多了,需要很多代碼來構建依賴,如果有那麼兩個依賴很難構建那又更困難了。所以說解開依賴還不夠,還得要容易構建依賴。實際上依賴太多常常說明一件事情:你的類或方法職責不單一,做的事情太多。這裏的類有兩個意思:

  1. 要麼是你的被測試類的職責不單一,乾的事情太多,需要從許多地方獲取所需的功能,這樣如果有一個依賴改變了,那麼你這個類就得變,如果有兩個依賴變了,而且變化的方法還不是統一的,那麼你這個類就被扯的四分五裂。
  2. 要麼是被測試類所依賴的類不單一,本來從一個地方獲取功能就可以了,現在要從好幾個地方獲取。

好了,關於通過所有測試這一條就談這麼多吧,這塊的內容要談可以有很多。

體現所有意圖

不管是高德納所說的文學編程,還是領域驅動開發裏面都有體現意圖這層意思。體現意圖不僅要體現作者(也就是作爲開發者的呢)的意圖,你當時是怎麼想的,還要體現當前業務的意圖。我們要將業務需求通過代碼來表達出來。其實表達這些意圖的方式很簡單:起名字。

好的類名,好的方法名,好的變量名

在這些名字上多斟酌一點時間,回報是巨大的。代碼閱讀的次數會比編寫的次數多,所以如果你想節約點閱讀的時間,讓你的代碼生命力更長久點,那麼就在這上面多花點時間吧。

消除重複

其實在大部分時候,消除重複往往是我們重構的第一步,也是重構的契機。消除重複往往能誕生出更好的設計結果。因爲重複消除了,你總是要使用一些抽象的手段將這些原來使用重複代碼,而現在被刪除了的地方連接起來。你總有可能提取新的基類或接口。消除重複不僅能降低bug(如果修改了一處重複的代碼,你得修改多出,修改的越多就越容易出錯),更重要的是能降低複雜性。關於消除重複《Refactor》這本書裏講了很多手段,這裏就不囉嗦了。

類和方法儘量短

這裏有兩個問題:爲什麼要短?到底要多短?

我總覺得我的腦子太笨,一下子讓我理解很多的內容我大腦會混亂。我喜歡的短的類和方法,這樣我在同一時刻就可以理解少一點東西。但是也有人說每個類或方法短就會產生很多類和方法。從某種程度上是正確的,但也不對。我們不僅要強調短,我們還得強調集中(或單一職責)。我們不是爲了追求短而短,不是說爲了短,我把所有的類都拆成兩個。短需要短的理由,如果這個方法有500行,但是它的內聚性非常好,乾的事兒單一,把它任何一個方法拆出去都顯得不完整,那麼我覺得沒有理由要讓它變短。

短的方法和類不僅容易理解,還容易測試,因爲短的方法和類“往往”更趨向於職責單一(當然也有例外)。而且短的類和方法又更容易用名字來說明意圖了,因爲乾的事兒少嘛。

那麼我到底該多短呢?這個太有爭議了。有人說一屏幕能顯示就可以了。問爲什麼一屏顯示就可以了啊?答:這樣就不用拖動滾動條了。如果你是這個回答我就不認同了。我們要短的類和方法並不是爲了不拖動滾動條,如果真的實現了這個目標那也是個副產品。如果你們團隊用的是一樣的屏幕,你們可以建立一個Guideline說一個類一屏。但理由絕對不是不拖動滾動條。而且注意的是這是一個Guideline,不是死規定。也就是說如果別人有充足的理由,是可以打破這個Guideline的。

PS:我們團隊的Guideline是每個方法15行(這只是我們的Guideline,但是我們竭力去維護它)。

我想,如果我們在編寫代碼是不是那麼的隨興發揮,我們字字句句的斟酌一番記住上面簡單設計的四個原則,我想離Simple Design不會太遠。


轉自:http://www.cnblogs.com/yuyijq/archive/2011/08/31/2160252.html

發佈了77 篇原創文章 · 獲贊 9 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章