2016年5月4日 星期三

Implementation Patterns - Kent Beck (Chapter 6 State (狀態))


根據書上的建議,狀態的管理應該:
  1. 把相似的狀態放一起
  2. 把不同的狀態分離
要判斷兩個狀態(或是變數)的相似性,可以用下列方式:
  1. 他們在同一個 method 被用到
  2. 他們出現和消滅的時間相同
就以 MaterdiskAutoTool 的設計來當作例子看看設計...

[Case 1]:
MasterdiskAutoTool 會讀取 CM_Options.xml,來作為建立 Steps 的判斷。設計如下:


可以發現,Form 直接讀取 CM_Options.xml,然後再把 CM_Options.xml 的內容用參數的方式傳遞給其他的class (紅色框框的地方, 以及每個 Step)。
這種設計有下列缺點:
1.) 參數的傳遞路徑太長了,參數也太多了
2.) 這些參數透過Step的constructor傳進去變成step的全域變數,然後被Step裡面的 method 所使用,造成 method 裡面會有'全域變數'與'區域變數'交雜的情況,不容易閱讀
3.) 本質來說,Step 物件本身並不需要擁有這些參數,只有 Step 的 method 需要這些參數。'全域變數'與'區域變數'在此 method 的生命週期不一樣 (違反狀態管理原則)
4.) 因為Step 擁有CM_Options.xml的參數,當Step要增減這些參數時,必須修改很多地方  (:ex: constructor, 全域變數...)
5.) 不容易寫unit test (因為要準備太多參數當作input)

[Case 2]:
比較好的做法,是把讀取CM_Options.xml 的內容交給某個CMOptions class 處理 (橘色框框),然後物件向CMOptions class 要內容。
也就是說,CMOptions class只會出現在Step裡面的 method,Step 不會有CM_Options.xml 的內容變成全域變數 (生命週期一樣)。

修改後的設計如下:


這種設計可以避免上列的缺點,而且還有下列優點:
1.) CMOptions class只只需要出現在Step裡面的 method,Step不會有CM_Options.xml 的內容是全域變數 (因此 method 內的變數生命週期一樣)
2.) 一旦 CM_Options.xml 有變化,則不需要改變 MasterdiskAutoTool 的架構

[Case 3]:
由上面Case 2可以發現,幾乎所有Steps都必須使用 CMOptions class,造成關係太複雜。
可以再進一步改善一下: 讓 BaseStep 使用 CMOptions class,這樣每個Steps 就可以擁有 CMOptions class,免除每個Step自己使用CMOptions class。






沒有留言:

張貼留言