發散式修改與散彈式修改 (Divergent Change & Shotgun Surgery)

★★★★Draft

FromRefactoring

📚 From the Books

發散式修改與散彈式修改 (Divergent Change & Shotgun Surgery)Code Smells

兩個互為鏡像的變更味道。發散式修改:一個類別因不同原因、被不同方式反覆修改。散彈式修改:一個變更卻要同時改動好幾個類別。好的設計讓「一種變化」對上「一個模組」。

🧠 Why It's a Problem

NOTE

  • 發散式修改是「一個類別受多種變化影響」(一對多)。
  • 散彈式修改是「一種變化影響多個類別」(多對一)。

兩者是同一枚硬幣的兩面:都在破壞「一種變化 ↔ 一個模組」的對應關係。

⚖️ Refactoring

發散式 — 一個類別,三種變化都打在它身上
// 前:顯示、儲存、版稅三種不相干的變化,全落在同一個類別
class Article {
  formatForWeb() {
    /* 顯示規則變 → 改這 */
  }
  saveToDatabase() {
    /* 儲存方式變 → 改這 */
  }
  calcRoyalty() {
    /* 版稅規則變 → 改這 */
  }
}

// 後:依變化原因拆成三個類別,各自只因一種原因而變
class ArticleRenderer {
  formatForWeb(article) {}
}
class ArticleRepository {
  save(article) {}
}
class RoyaltyCalculator {
  calc(article) {}
}
散彈式 — 一種變化,散落在多個類別
// 前:「新增一種支付幣別」這一種變化,得同時改好幾個類別
class OrderView {
  formatPrice(o) {
    /* 幣別符號 */
  }
}
class Invoice {
  totalLine(o) {
    /* 幣別換算 */
  }
}
class Receipt {
  footer(o) {
    /* 幣別四捨五入 */
  }
}

// 後:把散落的幣別邏輯集中到一個模組,之後改幣別只動這裡
class Money {
  symbol() {}
  convert() {}
  round() {}
}

🔑 Takeaways

✍️ My Notes

No notes yet — jot your takeaways or Q&A here.

📖 Further Reading

🔗 Dive Deeper