iT邦幫忙

2026 iThome 鐵人賽

DAY 15
0
Software Development

文科生的軟體工程啟蒙:用一個代購 App,看懂 30 個系統設計觀念系列 第 15 篇

Day 15:SOLID 原則入門(一)——單一職責原則(SRP)在函式與模組拆分上的實踐

  • 分享至 

  • xImage
  •  

昨天我們用分層架構把系統切成表現層、邏輯層、資料層三塊。但「層」本身還是可能很肥大——邏輯層裡如果塞了十件不相干的事,一樣會變回 Day 13 講的高耦合,只是搬到了同一層裡發生而已。從今天開始,我們要進入 SOLID 五大原則,把「職責要單一」這件事講得更精確、更有系統。

在軟體開發的過程中,我們常常會遇到程式碼隨著需求增加而變得臃腫、難以維護的情況。SOLID 原則是物件導向設計的五大核心準則,旨在幫助開發者打造低耦合、高內聚且易於擴充的架構。這篇要深入探討其中的第一項原則——單一職責原則(Single Responsibility Principle, SRP)。

一、單一職責原則

單一職責原則的核心概念是:「一個類別或模組應該只有一個修改的原因」。換句話說,每個函式、類別或模組都應該只負責一項特定的任務或功能。當一個模組承載了過多不相干的責任時(例如同時處理商業邏輯、資料庫存取與通知發送),只要其中一項需求變更,就容易牽一髮而動全身,增加產生臭蟲的風險。透過將複雜的功能拆分為獨立的小型模組,我們能大幅提升程式碼的可讀性、可測試性與可維護性。

二、代購 App 案例

在初期開發時,可能會把所有功能寫在同一個 OrderManager 類別中,同時處理訂單建立、匯率換算、海外物流追蹤,以及發送 LINE 買家通知:

// 違反 SRP:一個類別做三件不相干的事
class OrderManager {
  createOrder(order) {
    const rate = this.getExchangeRate(order.currency); // 匯率換算
    const total = order.price * rate + order.shippingFee;
    db.save(order); // 資料庫存取
    this.notifyBuyer(order.buyerId, total); // 通知
  }
  getExchangeRate(currency) { /* 匯率邏輯 */ }
  notifyBuyer(buyerId, total) { /* 呼叫 LINE API */ }
}

違反 SRP 的設計:OrderManager 需負責計算匯率、寫入資料庫及呼叫通訊 API。當 LINE 通知格式改變、或匯率計算公式調整時,都必須修改同一個檔案,導致這個類別因為多種不同原因而需要被修改。

遵循 SRP 的重構方式:把職責拆分成各自獨立的模組:

// 遵循 SRP:拆成各司其職的模組
class ExchangeRateCalculator {
  getRate(currency) { /* 匯率邏輯 */ }
}
class OrderRepository {
  save(order) { /* 資料庫存取 */ }
}
class LineNotificationService {
  notify(buyerId, message) { /* 呼叫 LINE API */ }
}

function createOrder(order) {
  const rate = exchangeRateCalculator.getRate(order.currency);
  const total = order.price * rate + order.shippingFee;
  orderRepository.save({ ...order, total });
  lineNotificationService.notify(order.buyerId, `訂單總額 ${total} 元`);
}
  • OrderRepository:專門負責訂單資料的儲存與讀取。
  • ExchangeRateCalculator:專門負責處理外幣匯率換算邏輯。
  • LineNotificationService:專門負責發送買家狀態通知。

透過這樣的拆分,每個模組各司其職,未來若要新增其他通知管道(如 Email),只需調整 LineNotificationService,完全不會影響核心的訂單處理邏輯。

三、結論

單一職責原則是打造穩固軟體架構的基石。透過確保每個函式和模組只做一件事並做好,我們能有效降低元件間的耦合度,讓程式碼在面臨需求變更時展現更高的彈性與延展性——這也是這五天以來,從壞味道、分層架構到 SRP,一直在重複強調的同一件事:把不相干的職責分開,系統才不會牽一髮動全身。把 Day 13 到 Day 15 這三天串起來看,反而覺得是一條很順的路——先看到義大利麵程式碼有多難改,再看到分層架構怎麼把職責攤開,最後才懂 SRP 講的「一個類別只能有一個改變的理由」,其實就是分層原則往下再收斂一層的具體規則。


上一篇
Day 14:分層架構(Layered Architecture)——分離表現層(View)、邏輯層(Logic)與資料存取層(Data Access)
下一篇
Day 16:SOLID 原則入門(二)——開放封閉原則(OCP)與依賴反轉原則(DIP)的抽象思維
系列文
文科生的軟體工程啟蒙:用一個代購 App,看懂 30 個系統設計觀念 共 18 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言