本章將 Chapter 28 所學的元件設計原則實際應用於薪資系統,逐步分析並重組元件結構,最終得出一個符合 ADP、SDP、SAP 等原則的元件配置。

元件結構與內聚性分析#

Figure 30.1: Possible payroll component diagram

  • 第一步是根據 CCP(共同封閉原則)將類別分組:因相同原因而變化的類別放在同一個元件中
  • 初步的分組方式是根據功能領域:
    • PayrollDomain:核心領域物件(Employee、PaymentClassification 等)
    • PayrollDatabase:資料庫存取
    • TransactionImplementation:交易實作
    • TransactionApplication:應用程式入口
    • TextParser:文字指令解析器

套用耦合性原則#

Figure 30.3: Updated payroll component diagram

  • 檢查 ADP(無環依賴原則):確認依賴圖中不存在循環
  • 發現 TransactionImplementationPayrollDomain 之間可能存在問題——Transaction 類別直接存取了 TimeCard 等領域物件的建構子

Figure 30.4: Revision to TimeCardTransaction to protect TimeCard privacy

  • 為了保護 TimeCard 的封裝性,修改 TimeCardTransaction 使其透過 HourlyClassification 的方法來新增時間卡,而非直接操作 TimeCard 物件
  • 這遵循了 REP(再利用/發布等價原則):讓 PayrollDomain 可以獨立於 Transaction 實作被重用

指標計算與分析#

Figure 30.6: Component diagram with metrics

  • 針對每個元件計算 CaCeIAD’ 指標
  • 分析結果:
    • PayrollDomain:高穩定性(低 I),高抽象度(高 A)——位於主序列附近,是理想的核心元件
    • TransactionApplication:穩定但具體——需要增加抽象度,或重新評估其依賴關係
    • TextParser:高不穩定度(高 I),低抽象度(低 A)——也位於主序列附近,適合作為外層元件

補充: 指標是輔助工具而非目標。作者強調不應為了讓數字好看而做不必要的重構,而是在發現異常指標時深入調查是否存在真正的設計問題。

使用 Factory 模式解耦#

Figure 30.8: Static structure of main program and object factories

Figure 30.9: Dynamic structure of main program and object factories

  • 為了讓 TransactionImplementation 不直接依賴 PayrollDatabase 的具體實作,引入 PayrollDatabaseFactory 介面
  • main 程式負責建立所有 Factory 的具體實作,並注入到系統中
  • 這確保了依賴方向始終朝向穩定與抽象

最終元件結構#

Figure 30.10: Final payroll component structure

  • 最終的元件配置滿足了所有六大原則:
    • ADP:無循環依賴
    • SDP:依賴方向朝向穩定
    • SAP:穩定的元件是抽象的
    • CCP:因相同原因變化的類別在同一元件中
    • CRP:不一起使用的類別不在同一元件中
    • REP:每個元件可獨立發布與重用

重點: 元件結構不是一次設計好的。它隨著系統的演化而改變——在開發早期,你可能只有一兩個元件;隨著類別增加、依賴變複雜,才逐步分割與重組。元件設計原則提供的是持續檢視與改進的框架。

本章小結#

本章展示了如何將抽象的設計原則轉化為具體的架構決策。透過指標計算,我們可以量化地評估設計品質;透過 Factory 模式,我們可以打破不必要的依賴;透過反覆迭代,我們可以漸進地改善元件結構。