iT邦幫忙

2025 iThome 鐵人賽

DAY 10
0
Software Development

消除你程式碼的臭味系列 第 10

Day 10- 介面最小化:只暴露必要的東西

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20250903/20124462P1N8QjGguI.png

消除你程式碼的臭味 Day 10- 介面最小化:只暴露必要的東西

介面越小,被誤用的空間越小,維護成本越低。
公開的每個函式,都是欠下的一筆債

介面是你經過深思熟慮後,願意用未來十年的維護成本來做擔保的一個最小化承諾。

每一次輕率地公開一個內部實作,就在為未來埋下一顆地雷。
總有一天,當要重構時,會發現自己動彈不得,因為有十個地方依賴了那個當初根本不該公開的地方。

什麼是介面 Interface?

介面是你唯一的承諾

  • 對外能被呼叫、依賴、或需要遵守的入口與契約。
  • 包含匯出函式、公開類別、HTTP 路由、CLI 參數、事件名稱、資料庫表結構與欄位、檔案格式。
  • 你一旦公開,外部使用者就會用;你一改,別人的程式就可能壞。

目標很單純

  • 對外只保留「完成任務必需」的最小集合。
  • 內部實作細節不要讓外部看見,也不要讓外部可以依賴。
    https://ithelp.ithome.com.tw/upload/images/20250912/201244621Icxw5FBnl.png

經典案例:把內部細節都丟給外面

// 🔴 臭味道:把所有東西都 export
export function toDto(post) { return { id: post.id, title: post.title }; }
export function logDebug(msg) { console.log('[debug]', msg); }
export function fetchPosts(db) { return db.posts.all(); }

呼叫端可以動到不該碰的東西,耦合度過高。
https://ithelp.ithome.com.tw/upload/images/20250912/20124462sKXyD37UtO.png

  • 喪失了自由: 有人開始直接使用 toDto。現在,你想在 DTO 裡加一個 author 欄位。恭喜,所有直接呼叫 toDto 的地方都可能出錯。被自己的實作細節給綁架了。

  • 提供了錯誤的工具: 使用者根本不該關心 toDtologDebug。他們只想「取得文章列表」。他們可能用這些零件組裝出奇怪的東西。

  • 契約過於龐大: 你現在必須為這 3 個函式的穩定性負責,而不是 1 個。你的維護成本無緣無故增加了 3 倍。

把內部細節封起來

好的模組就像一個黑盒子。
外界不需要、也不應該知道裡面發生了什麼。
你只需要提供一個定義良好、功能單一的入口。
https://ithelp.ithome.com.tw/upload/images/20250912/20124462zI135yVM6B.png

// 🟢 好品味:這才叫 API。一個入口,一個承諾。

// 這些都是內部實作細節,外界一個字都不該看到。
// 可以把它們全部改名、合併、刪除,而不需要通知任何人。
function toDto(post) { return { id: post.id, title: post.title }; }
function logDebug(_msg) { /* ... */ }
function fetchPostsFromDb(db) { return db.posts.all(); }

// 這是我唯一對外的承諾。
export function listPublishedPostTitles(db) {
  logDebug('Fetching posts...');
  const posts = fetchPostsFromDb(db);
  return posts.map(toDto);
}
  • 自由: 現在擁有 100% 的內部重構自由。
    只要 listPublishedPostTitles 的輸入和輸出不變,可以把 toDtologDebugfetchPostsFromDb 重寫一百遍。

  • 意圖清晰: API 的名字 listPublishedPostTitles 直接說明了它的業務目的。使用者一看就知道這是做什麼的。而 fetchPoststoDto 只是實作細節,不是業務目的。

  • 最小化攻擊面: 更少的公開介面意味著更少的 bug 來源,更少的誤用可能,以及更簡單的測試。

介面最小化的判斷

先問自己這幾個問題:

  1. 預設就是 private 每個函式、每個變數,預設都是模組內部的。必須給出一個極其強大的理由,才能將其公開。理由不是「可能有用」,而是「絕對必要」。

  2. 公開意味著永恆: 一旦公開,就幾乎永遠無法在不破壞別人程式碼的情況下修改或刪除它。有打算對這個函式簽名負責到專案終結嗎?

  3. 提供解決方案,而非工具箱: 不要給使用者一堆樂高積木(工具函式),然後讓他們自己去拼。直接給他們一輛組好的法拉利(解決特定問題的高階函式)。

https://ithelp.ithome.com.tw/upload/images/20250912/20124462381aGHG3Qq.png

今日重點

  • 對外暴露最小集合,其他關起來。
  • 內部細節不給外界依賴,重構才安全。
  • 讓 API 命名貼近問題本身。
  • 你公開的每一個函式,都是在消耗你未來的自由。

把介面縮到最小,減少誤用與耦合,停止把內部亂七八糟的實作細節當成 API 到處亂丟。

設計一個乾淨、最小化、且有意義的介面,這就是好程式碼的差別。


上一篇
Day 9- 迴圈最佳化:把邊界判斷和特殊處理移到外面
下一篇
Day 11- 函式的副作用:把計算與 I/O 分離
系列文
消除你程式碼的臭味12
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言