📘 完整指南:開發各階段的類圖

📘 引言:從孤立元件到連結系統——類圖的演進

在軟體開發的世界中,類圖不僅僅是靜態的圖示——它們是隨著所代表系統一同演變的活躍藍圖。在開發的每個階段,從最初的規格需求到發布後的維護,類圖的細節層次、結構與設計意圖都會產生顯著變化。然而,一個常見的陷阱始終存在:孤立的元件.

考慮典型的付款處理器類——CreditCardProcessor, PayPalProcessor,以及StripeProcessor——通常在類圖中被建模為獨立且彼此脫節的實體。雖然這在早期設計階段可能足夠,但卻暴露出更根本的問題:整合與行為清晰度的缺乏。這些類別彼此孤立,缺乏明確的選擇、設定或執行時期彈性的機制。結果導致設計僵化、難以擴展且難以測試。

本文探討類圖應如何演進於開發各階段——從高階概念模型到詳細且可執行的設計——以及如何策略性連結元件之間的策略性連結,能將零散的系統轉化為整合且可擴展的架構。我們將聚焦於一個實際案例:付款處理子系統——並展示如何應用策略模式, 工廠模式,以及依賴注入,來彌補孤立類別與真正動態、可維護系統之間的差距。

透過PlantUML 圖表以及實用的設計洞見,你將學會如何:

  • 超越靜態類別關係。
  • 模擬現實世界的行為與執行時期動態。
  • 設計靈活、可擴展且易於演進的系統。

到最後,你會發現一個連接良好的類圖不僅僅是文檔工具——它是一種你的軟體應如何運作的視野.

類圖是用於建模物件導向系統的最強大 UML 工具之一。它們的細節層級會根據開發階段而有顯著差異。本指南將帶你走過四個關鍵階段的軟體開發過程,並展示類圖如何相應地演進。


🧩 1. 階段 1:需求與概念設計(早期階段)

🎯 目的:

  • 捕捉高階領域概念。
  • 識別關鍵實體及其關係。
  • 促進利益相關者與開發人員之間的溝通。

🔍 特徵:

  • 著重於領域實體關係.
  • 無方法或屬性(或極少)。
  • 使用泛化關聯聚合,以及 組成.
  • 避免實現細節(例如存取修飾符、資料類型)。

📌 範例:電子商務系統(概念層級)

@startuml
' 概念類別圖 - 第一階段:需求

class 客戶 {
  +姓名:字串
  +電子郵件:字串
}

class 產品 {
  +名稱:字串
  +價格:十進位
}

class 訂單 {
  +訂購日期:日期
  +狀態:字串
}

客戶 "1" -- "0..*" 訂單 : 下單
訂單 "1" -- "1..*" 產品 : 包含
產品 "1" -- "0..*" 訂單 : 售出於

note right of 客戶
  代表購買產品的使用者
end note

note right of 產品
  可實體或數位的銷售項目
end note

note right of 訂單
  交易紀錄
end note

@enduml

✅ 使用案例:向利害關係人展示,優化領域模型,並與業務分析師驗證。


🧱 2. 第二階段:分析與高階設計(中期)

🎯 目的:

  • 將領域模型進一步細化為更結構化的設計。
  • 引入 屬性基本操作,以及 關聯.
  • 開始識別 介面抽象類別,以及 設計模式.

🔍 特徵:

  • 新增 屬性 和 操作 (使用最少的類型)。
  • 使用 抽象類別 和 介面.
  • 引入 多重性 和 可導航性.
  • 開始思考 責任 和 內聚性.

📌 範例:電子商務系統(分析層級)

@startuml
' 高階類別圖 - 第二階段:分析

@startuml
' 高階類別圖 - 第二階段:分析

抽象類別 Order {
  - orderID: 字串
  - orderDate: 日期
  - status: 字串
  +calculateTotal(): 十進位
  +validate(): 布林
  +save(): 無回傳值
}

class Customer {
  - customerID: 字串
  - name: 字串
  - email: 字串
  +addOrder(order: Order): 無回傳值
  +getOrders(): List<Order>
}

class Product {
  - productID: 字串
  - name: 字串
  - price: 十進位
  - stockQuantity: 整數
  +isInStock(): 布林
  +updateStock(amount: 整數): 無回傳值
}

class OrderItem {
  - quantity: 整數
  - unitPrice: 十進位
  +getSubtotal(): 十進位
}

Customer "1" -- "0..*" Order : 下單
Order "1" -- "1..*" OrderItem : 包含
OrderItem "1" -- "1" Product : 參考
Product "1" -- "0..*" OrderItem : 出現在

介面 PaymentProcessor {
  +processPayment(amount: 十進位): 布林
}

Order "1" -- "1" PaymentProcessor : 使用

@enduml

✅ 使用案例:設計審查、團隊協調、初步架構決策。


🔧 3. 第三階段:詳細設計與實現(後期階段)

🎯 目的:

  • 為編碼做準備。
  • 定義 精確的屬性方法資料類型存取修飾詞.
  • 包含 約束相依性關聯,以及 組合.
  • 使用 設計模式 (例如:工廠模式、策略模式、單例模式)。

🔍 特徵:

  • 完整的方法簽章與傳回類型。
  • 使用 存取修飾詞 (+-#).
  • 依賴關係繼承介面均已被完整定義。
  • 可能包含約束條件(例如,<<約束條件>>).

📌 範例:電子商務系統(詳細設計)

@startuml
' 詳細類圖 - 第三階段:實作

@startuml
' 詳細類圖 - 第三階段:實作

class Customer {
  - customerID: 字串
  - name: 字串
  - email: 字串
  - address: 字串
  +addOrder(order: Order): 無
  +getOrders(): List<Order>
  +validateEmail(): 布林
}

class Order {
  - orderID: 字串
  - orderDate: 日期
  - status: OrderStatus
  - total: 十進位
  +calculateTotal(): 十進位
  +validate(): 布林
  +save(): 無
  +cancel(): 無
}

class OrderItem {
  - quantity: 整數
  - unitPrice: 十進位
  +getSubtotal(): 十進位
}

class Product {
  - productID: 字串
  - name: 字串
  - price: 十進位
  - stockQuantity: 整數
  +isInStock(): 布林
  +updateStock(amount: 整數): 無
  +getPrice(): 十進位
}

class PaymentProcessor {
  +processPayment(amount: 十進位): 布林
}

class CreditCardProcessor {
  +processPayment(amount: 十進位): 布林
}

class Payment {
  - paymentID: 字串
  - amount: 十進位
  - method: 字串
  - timestamp: 日期
  +confirm(): 布林
}

' 繼承
Customer <|-- PremiumCustomer

' 介面
PaymentProcessor <|-- CreditCardProcessor
PaymentProcessor <|-- PayPalProcessor

' 關聯
Customer "1" -- "0..*" Order : 下單
Order "1" -- "1..*" OrderItem : 包含
OrderItem "1" -- "1" Product : 參考
Order "1" -- "1" Payment : 擁有
PaymentProcessor "1" -- "1" Payment : 處理

' 約束條件
note right of Order
  狀態:[待處理, 已確認, 已出貨, 已取消]
end note

note right of Product
  庫存必須大於 0 才能銷售
end note

@enduml

✅ 使用案例:開發者交接、程式碼產生、設計文件記錄。


🛠️ 4. 第四階段:維護與演進(發行後)

🎯 目的:

  • 反映現實世界的變更系統中的變更。
  • 文件重構已棄用新功能.
  • 支援技術負債追蹤系統理解.

🔍 特性:

  • 可能包含已棄用類別/方法。
  • 顯示新類別重新命名的元件已移除的元件.
  • 使用範疇 (<<已棄用>><<單例>><<工廠>>).
  • 通常 簡化 以提高可讀性。

📌 範例:電子商務系統(維護階段)

@startuml

' 重新設計的支付系統:策略 + 工廠模式
' 介面
class PaymentProcessor {
+processPayment(amount: Decimal): Boolean
}

' 具體策略
class CreditCardProcessor {
+processPayment(amount: Decimal): Boolean
}

class PayPalProcessor {
+processPayment(amount: Decimal): Boolean
}

class StripeProcessor {
+processPayment(amount: Decimal): Boolean
}

' 工廠模式
class PaymentProcessorFactory {
+createProcessor(type: String): PaymentProcessor
+getAvailableTypes(): List<String>
}

' 使用策略的服務
class OrderService {
- processor: PaymentProcessor
+createOrder(customer: Customer, items: List<OrderItem>): Order
+setPaymentProcessor(processor: PaymentProcessor): void
}

' 支付實體
class Payment {
- paymentID: String
- amount: Decimal
- method: String
- timestamp: Date
+confirm(): Boolean
}

' 客戶與訂單(簡化)
class Customer {
- customerID: String
- name: String
- email: String
+addOrder(order: Order): void
+getOrders(): List<Order>
}

class Order {
- orderID: String
- orderDate: Date
- status: OrderStatus
- total: Decimal
+calculateTotal(): Decimal
+validate(): Boolean
+save(): void
+cancel(): void
}

' 標籤以增加清晰度
PaymentProcessor <<interface>>
CreditCardProcessor <<strategy>>
PayPalProcessor <<strategy>>
StripeProcessor <<strategy>>
PaymentProcessorFactory <<factory>>
OrderService <<service>>

' 繼承:策略模式
CreditCardProcessor <|-- PaymentProcessor
PayPalProcessor <|-- PaymentProcessor
StripeProcessor <|-- PaymentProcessor

' 工廠建立處理器
PaymentProcessorFactory "1" -- "1" PaymentProcessor : 建立

' OrderService 使用處理器(依賴注入)
OrderService "1" -- "1" PaymentProcessor : 使用

' OrderService 使用工廠來設定處理器
OrderService "1" -- "1" PaymentProcessorFactory : 透過配置

' 支付依賴處理器
Payment "1" -- "1" PaymentProcessor : 使用

' 關聯關係
Customer "1" -- "0..*" Order : 下單
Order "1" -- "1..*" OrderItem : 包含
OrderItem "1" -- "1" Product : 參考
Order "1" -- "1" Payment : 擁有

' 約束
note right of Order
狀態:[待處理, 已確認, 已出貨, 已取消]
end note

note right of Payment
方式:"CreditCard", "PayPal", "Stripe"
end note

note right of PaymentProcessorFactory
支援的類型:"CreditCard", "PayPal", "Stripe"
可擴展而不需修改 OrderService
end note

@enduml

✅ 使用案例:新開發人員入職、系統重構、審計追蹤。


🔄 總結:類圖的演進

階段 重點 細節層級 關鍵元素
1. 需求 領域概念 高階 實體、關聯
2. 分析 系統結構 中等 屬性、操作、介面
3. 實作 程式碼就緒 類型、存取修飾符、設計模式
4. 維護 系統演進 適應性 範疇、棄用、簡化

🛠️ 使用 PlantUML 的提示

  • 使用 @startuml 和 @enduml 來包裝圖表。
  • 使用 <<範疇>> 用於設計模式或元數據。
  • 使用 note right of 用於文件記錄。
  • 使用 +-# 用於可見性(公開私有保護).
  • 使用 <<介面>><<抽象>><<單例>> 為清晰起見。
  • 透過 PlantUML Online 或 IDE 插件(VS Code、IntelliJ)。

📚 最後想法

類圖是 非靜態 — 它們 隨著專案演進。務必策略性地使用它們:

  • 早期:與非技術利益相關者溝通。
  • 中期:讓開發人員在架構上達成共識。
  • 晚期:引導實作與程式碼品質。
  • 發行後:維持系統知識。

✅ 專業提示:將你的 PlantUML 檔案與程式碼一同進行版本控制——它們是活文件!


✅ 結論:設計的不只是類別,更是系統

類圖不只是圖表——它們是意圖的地圖, 合作的藍圖,以及建築演進的活體紀錄。正如我們所見,它們的價值不在於最初的形態,而在於它們如何適應在開發生命週期中不斷演變——從需求的高階抽象,到後期設計中精確且可執行的模型。

從孤立的處理器類別到一個相互連結、以策略為導向的系統的演進,揭示了一個根本的事實:優秀的設計不僅在於定義組件——更在於定義它們如何協同運作。當CreditCardProcessor, PayPalProcessor,以及StripeProcessor被視為可互換的策略——由工廠協調並注入服務中——圖表便不再只是靜態的快照。它變成了一個彈性動態模型、可擴展性與可維護性。

透過使用如策略, 工廠,以及依賴注入,我們將孤立的類轉化為一個整合且可擴展的生態系統。這不僅僅是為了更好的圖表——更是為了打造更好的軟體。它讓團隊能夠:

  • 在不觸碰現有程式碼的情況下新增付款方式。
  • 獨立測試行為。
  • 即使在發佈多年後,也能有信心地演進系統。

最終,最具威力的類別圖並非那些詳細展示每個欄位與方法的圖——而是那些講述一個故事:一個關於合作、適應力與前瞻設計的故事。

當你繪製下一個類別圖時,請問問自己:

我的類別只是被定義了嗎——還是它們彼此相連?
它們是孤立的嗎——還是屬於一個能夠成長的系統的一部分?

因為最終,最好的類別圖不僅僅描述系統是什麼——它們激發系統應該如何發展.