1. 何謂”模組” (Module)
一種抽象的概念
其實C#沒有Module概念
以C#舉例
- 可能是一個「類別」(class)
- 可能是一個「方法」(method)
- 可能是一個「組件」(assembly)
2. 內聚力 Cohesion
- 在一個”模組” 內完成 “一件工作” 的度量指標
- 內聚一次只專注做一件事
2.1. 高內聚力
- 在一個”模組”內只完成一件工作
- 內聚力高,意味著該模組可以獨立運作,也意味著更容易重複利用
- 範例:一個class只負責一件事情(例如寄送郵件)
2.2. 低內聚力
- 在一個”模組”內完成多份工作
- 內聚力低,意味著這個棤組會造成難以維護/測試/重用/理解
- 範例:所有功能寫在一個class裡面或一個method有5000行程式碼
2.3. 最佳實務
- 在設計模組的時候,要盡量設計出
高內聚力
的程式碼。
- 若要在一個模組內完成多項工作,建議拆成多個不同的類別
- 實現
SRP
就是實現「提高內聚力
」的一種表現
3. 耦合力 Coupling
- 模組與模組之間的關聯強度
- 模組之間相互依賴的程度
- 衡量兩個模組的緊密連接程度
- 範例:在ClassB裡面,直接”建立”了ClassA的物件實體,就會建立ClassA與ClassB之間的”耦合關係”。
3.1. 高耦合力
- 意著當改了A模組時,相關的B模組就會容易被影響(改A壞B)
3.2. 低耦合力
- 當在修改模組的時候,有越少的模組被影響,就意味著耦合力較低。
3.3. 最佳實務
- 在設計不同模組的時候,要盡量設計出
低耦合力
的程式碼。
- 實現
DIP
就是實現「降低耦合力」的一個原則。
3.4. 隨堂測驗
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class InvitationService public
public void SendInvite (string elail, string firstName, string lastName) {
if (String.IsNullOrWhiteSpace(firstName) || String.IsNullOrWhiteSpace(lastName)){ throw new Exception("Name is not valid!"); }
if (!email.Contains("@") || !email.Contains(".")){ throw new Exception("Email is not valid!!"); }
SmtpClient client = new SmtpClient();
client.Send(new MailMessage("mysite@nowhere.com", email) { Subject "Please join me at my party!" });
}
}
|
這段代碼中的 InvitationService
類與以下幾個類發生了耦合關係:
String
類 - 用於驗證 firstName
和 lastName
是否為空或空白字串。
方法:String.IsNullOrWhiteSpace
Exception
類 - 用於在驗證失敗時拋出異常。
1 2
| throw new Exception("Name is not valid!"); throw new Exception("Email is not valid!");
|
SmtpClient
類 - 用於發送電子郵件。
創建了 SmtpClient
實例 client
。
MailMessage
類 - 用於構造電子郵件訊息。
創建了 MailMessage
物件,設置發件人和收件人資訊以及郵件主題。
3.5. 隨堂測驗
耦合是不可避免的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class Order { private ShoppingCartContents cart; private float salestax; public Order(ShoppingCartContents cart, float salesTax) { this.cart = cart; this.salesTax = salesTax; } public class ShoppingCart { public float Price; public int Quantity; } public float OrderTotal() { float cartTotal = 0; for (int i = 0; i < cart.items.length; i++) { cartTotal += cart.items[i].Price * cart.items[i].Quantity; } cartTotal += cartTotal * salestax; return cartTotal; } }
public class ShoppingCartContents { public ShoppingCart[] items; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @startuml class Order { - ShoppingCartContents cart - float salestax + Order(ShoppingCartContents, float) + OrderTotal(): float } class ShoppingCartContents { - ShoppingCart[] items } class ShoppingCart { + float Price + int Quantity } Order --> ShoppingCartContents ShoppingCartContents --> ShoppingCart @enduml
|