iT邦幫忙

2026 iThome 鐵人賽

DAY 14
0
Software Development

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

Day 14:分層架構(Layered Architecture)——分離表現層(View)、邏輯層(Logic)與資料存取層(Data Access)

  • 分享至 

  • xImage
  •  

昨天我們看到高耦合怎麼把程式碼纏成一團麻——商品抓取、訂單計算、通知、資料庫連線全擠在同一個函式裡,改一處就牽動全部。今天要談的分層架構,就是預防這件事發生的具體做法:把不同職責放進不同的層,讓耦合沒有機會在同一個地方發生。

分層架構是軟體設計中最常見的架構模式之一。它將應用程式組織成不同的邏輯層,每個層級負責特定的任務,並僅與相鄰的層級進行互動。透過落實「關注點分離」(Separation of Concerns)原則,此模式確保了軟體中不同面向(如使用者互動、商業規則與資料儲存)保持獨立,進而提升系統的可理解性、可維護性與可擴展性。

一、三個主要層級

表現層 / 介面層(Presentation Layer)

  • 角色:使用者直接互動的最上層。
  • 職責:負責處理使用者輸入並顯示輸出結果。例如網頁、行動應用程式或桌面介面。

邏輯層 / 服務層(Business Logic Layer)

  • 角色:應用程式的核心「大腦」。
  • 職責:包含應用程式的商業邏輯,並協調表現層與資料層之間的資料流動。例如處理「計算折扣」或「驗證使用者輸入」等規則。

資料存取層 / 永續層(Data Access Layer)

  • 角色:負責管理資料的儲存與檢索。
  • 職責:與資料庫或其他儲存系統互動,處理如 SQL 查詢、儲存庫(Repositories)或 ORM 框架(如 Prisma)等操作。

二、代購 App 案例

把訂單建立這件事,拆進三層看:

// controllers/orderController.js —— 表現層:只負責收請求、回結果
app.post('/orders', async (req, res) => {
  const order = await OrderService.createOrder(req.body);
  res.json(order);
});

// services/orderService.js —— 邏輯層:商業規則都在這裡
async function createOrder(input) {
  if (input.quantity <= 0) throw new Error('數量不合法'); // 驗證
  const total = input.price * input.quantity + input.shippingFee; // 計算
  return OrderRepository.save({ ...input, total });
}

// repositories/orderRepository.js —— 資料存取層:只跟資料庫講話
async function save(order) {
  return db.query('INSERT INTO orders (buyer_id, total) VALUES (?, ?)', [order.buyerId, order.total]);
}

表現層:供海外代購業者與買家使用的手機 App 或網頁介面。當買家在介面上提交新的代購商品需求時,此層負責收集輸入資料並發送請求至邏輯層——它不知道、也不需要知道總金額是怎麼算出來的。

邏輯層:負責處理代購業務流程。收到訂單請求時,驗證訂單資料、計算商品總金額(含國際運費與代購服務費),並處理匯率換算——它不直接碰資料庫,也不管畫面長什麼樣。

資料存取層:透過 ORM 與資料庫進行互動的儲存庫元件。接收來自邏輯層的指令後,安全地執行資料庫查詢,將新訂單寫入資料庫並更新庫存記錄,不直接暴露 SQL 查詢給前端。

哪天要把「運費計算規則」改掉,只需要動 orderService.js 這一個檔案——跟昨天那個一改運費就意外弄壞 Line 通知的義大利麵範例相比,這裡的三個檔案彼此不知道對方內部長什麼樣,改一層不會波及另外兩層。

三、結論

分層架構透過嚴格分離表現層、邏輯層與資料存取層,為軟體開發提供了一個清晰且具組織性的藍圖。這種設計不僅防止了元件間的緊密耦合,還能讓開發團隊在不影響整個系統的情況下,輕鬆進行特定層級的擴展、維護或技術遷移。拿昨天那個義大利麵範例重新看一次,才發現分層架構要解決的其實不是「程式碼要不要拆檔案」,而是「改一個地方會不會波及另一個地方」——三個檔案分開放,跟三個檔案彼此不知道對方內部長什麼樣,是兩件不同層次的事,後者才是分層真正要保護的東西。


上一篇
Day 13:什麼是壞味道(Code Smell)?——高耦合與義大利麵程式碼的形成原因
下一篇
Day 15:SOLID 原則入門(一)——單一職責原則(SRP)在函式與模組拆分上的實踐
系列文
文科生的軟體工程啟蒙:用一個代購 App,看懂 30 個系統設計觀念 共 18 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言