顯示具有 Design Pattern 標籤的文章。 顯示所有文章
顯示具有 Design Pattern 標籤的文章。 顯示所有文章

2017年7月3日 星期一

OOD 原則 - SOLID

OOD 原則 - SOLID

物件導向設計 5 大原則:
1. (SRP) 單一職責:
    一個類別只負責一件事情

2. (OCP) 開放/封閉原則:
    開放擴充, 關閉修改

3. (LSP) Liskov替換:
    子類別應該可以替換掉父類別而不會影響程式架構
    子類別可以擴充父類別的功能, 但不能改變父類別原有的功能。子類別不要覆蓋父類別的方法!
    -->設計上應該少用繼承, 多用composite/aggregation 達到re-use目的 (i.e., 做一個wrapper 包住 base class)
    --> CARD - 先思考 Composition/Aggregation 的 Reuse ,真的沒辦法才思考 Derivation

4. (ISP) 介面隔離:
     使用多個專門介面, 比使用單一總介面要好! 把不同的函數從介面中分離出來
    --> 不同的函數應該屬於不同的介面

5. (DIP) 依賴反轉
    高階模組不應依賴低階模組,兩個都應該依賴在抽象概念上
    抽象不應該依賴於細節, 細節應該依賴於抽象!
    --> 針對介面寫程式
    --> Dependency Injection 是實作 DIP 的手法 (例如: 通過Constructor注入依賴)
    --> 若一個Constructor注入太多的依賴,則此Class 可能違反了SRP

SRP 與 OCP 都只是一個方向, 不是教義! 寫程式要專注一個主要的核心任務, class要盡可能簡單, 但是不是教義!

2017年1月3日 星期二

MVC 架構 - 以 Hyena 為例

MVC 架構以 M 最為重要! 說明如下:
  • Model: 存放資料,當資料改變時,透過 C 來更新V
  • View: 只是視覺化Model
  • Controller: 當 M 改變時,用來更新V
為了達到 "當 M 改變,透過 C 來更新V" 的目的,Controller 要能夠看得到Model 與View:


其中,Controller 的 RegisterView() 如下:

如此便可以把 M 的改變 呈現在 V  上面。

MVC的優缺點如下:
** 優點:
  • 可以用不同的View 呈現相同的Model
  • 容易對 Controller 進行測試 (Testability => mockup Model for testing),適合TDD

**缺點:
  • 採用Event-driven,是一種複雜的UI design pattern
  • 需要透過Controller 來更新View,很耗資源 



另外,請參考Hyena的Class diagram,Model 也用來執行真正的Business:


MVC 不是一種技術, 而是一種設計理念!

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。






2016年3月27日 星期日

Implementation Patterns - Kent Beck (Chapter 3 價值觀,原則, 模式)

第 3 章 - 程式設計理論

價值觀,原則,模式 這三種元素組成了一種穩定的開發方式:
  • 價值觀 - 提供了動機 (why)
  • 原則 - 實際行動 (what)
  • 模式 - 如何做 (how)


價值觀:
  1. 溝通 - 把程式寫成一個故事,讀起來像一本書一樣。
  2. 簡單 - 去掉多餘的複雜性,讓讀者看得懂。
  3. 靈活 - 只有真正發生變化的時候才需要靈活性 (不用想像明天或許會用得上的靈活)。

      重要性為 溝通>簡單>靈活

原則:
  1. 確保局部化影響 - 把組織程式碼的影響範圍縮到最小,程式碼就會有極佳的溝通效果。
  2. 消除重複 - 把程式拆成許多更小的部分:小方法, 小物件, 小 package 有助於發現並消除重複。
  3. 綑綁邏輯與資料 - 把邏輯和資料放在同一個方法,同一個物件,同一個 package,讓影響發生在局部。
  4. 建立對稱性 - 邏輯概念上的對稱。例如: Add () 與 Delete ()放在同一個物件。
  5. 使用宣告式表達 - 使用 Annotation (或者 attribute) 表達程式意圖。
  6. 確保相同變化率 - 物件中所有property 的 life time 應該一樣。較短 life time 的變數應該屬於某個方法。

模式:
  •       請參閱接下來的章節...