二十年前(2006 年 9 月),我在部落格寫了一篇簡短的筆記 Josh Bloch on API Design,推薦了 Joshua Bloch 著名的演講與投影片《How to Design a Good API and Why it Matters》(亦可參考他在 Google 的 Tech Talk 演講影片)。當時我在文末寫下了這段心得:
「其實軟體開發者的大部分工作就是和一大堆的 API 打交道,我是最討厭使用那種設計不良的 API,因為往往要用更多的 client code 來完成功能或者避過設計的缺陷。怎麼去設計『良好的 API』正是所有軟體開發者要必備的技巧,Joshua 所提出的這些設計準則,都是相當值得參考學習的。」
一轉眼二十年過去了。最近在社群上看到一個很有深度的大哉問:時隔將近二十年,在 API 設計這個領域,到底有沒有任何資源真正超越了 Joshua Bloch 的這場經典演講?
這個提問促使我重新把那份經典的投影片翻出來重溫,也對照了過去二十年間整個軟體工程界在 API 設計上的演化。
簡潔的結論是:就基礎介面哲學而言,沒有任何單一資源能夠完全取代 Joshua Bloch;但現代軟體工程已經發展出更加全面且深入的資源,足以應對現代 API 在維運、分散式架構與網路環境中的現實挑戰。
歷久彌新的核心哲學:為什麼 Bloch 的原則依然適用?
為什麼二十年過去了,大家依然將 Joshua Bloch 的演講(以及他在《Effective Java》中的原則)奉為圭臬?
因為 Bloch 當年談論的重點,並非特定語言語法或特定框架的技術細節,而是觸及了認知心理學與軟體工程的本質矛盾——人類大腦的工作記憶(working memory)十分有限,而軟體系統的複雜度卻永遠在膨脹。
Bloch 提出的幾個核心信條,放到今天依然字字珠璣:
容易學習,難以誤用
好的 API 應該做到「Easy to learn」、「Easy to use, even without documentation」與「Hard to misuse」。它的行為要符合開發者的直覺(Principle of Least Astonishment),讓做對的事情變得很自然,讓犯錯在編譯期或呼叫當下就被阻擋。如果一個 API 需要呼叫者小心翼翼地遵循隱含的順序假設,那它就是一枚未爆彈。
儘早回報錯誤
Fail fast 原則指出,錯誤一旦發生,就應該立即在最靠近源頭的地方暴露出來,而不是吞下錯誤、回傳魔術數字,或是帶著損壞的狀態繼續執行,最終在數百行之外引發莫名其妙的崩潰。
最小化公開介面與資訊隱藏
When in doubt, leave it out.(猶豫不決時,就不要放進公開介面)。API 一旦公開,每一個方法、每一個欄位都是對外做出的長期承諾。增加功能永遠容易,移除或修改壞設計卻會破壞相容性。資訊隱藏不只是封裝實作細節,更是為未來的重構保留自由度。
命名即核心概念
名稱是建立心理模型(mental model)的基石。好的命名不需要翻閱文件就能心領神會;命名要前後一致、避免隱晦縮寫,並且能夠精準表達職責邊界。
文件也是 API 的一部分
任何必須透過閱讀底層實作程式碼才能搞懂如何使用的 API,都是不合格的設計。規格與文件的缺失,本質上就是 API 的缺陷。
這些原則之所以歷久彌新,是因為過去二十年來,硬體效能與架構工具大幅演進,但人類工程師的大腦結構與認知侷限並沒有改變。只要 API 的使用者還是人,Bloch 的哲學就永遠不會過時。
二十年間的典範轉移:API 的戰場如何擴大?
既然原則未變,那為什麼我們今天不能「只讀」Joshua Bloch?
原因在於:Bloch 的演講誕生於 2000 年代中期,主要圍繞在 Java 與 process 內部的類別庫介面(in-process class & library interfaces,最典型的代表就是他親手操刀的 Java Collections Framework)。
在那樣的語境下,呼叫發生在同一塊記憶體位址空間內、同步完成、沒有網路延遲,也不會有網路分割(network partition)。因此,Bloch 的內容自然缺乏了現代工程不可或缺的面向:網路邊界、雲端規模的向後相容、冪等性(idempotency)、分散式工作流以及跨平台 schema 規範。
在過去二十年間,軟體架構經歷了劇烈的典範轉移,API 的設計維度延伸到了以下面向:
從 in-process 到 out-of-process
當 API 跨出記憶體邊界,走入分散式系統與雲端網路時,原本單純的函式呼叫就必須面對分散式運算的殘酷現實:
- 非同步與長任務(long-running operations):當一個操作需要數十秒甚至數分鐘才能完成,API 往往不再適合同步阻塞連線,而更常採用非同步輪詢(polling)或事件通知模型。
- 分頁策略(pagination):海量資料無法一次載入記憶體,傳統以
offset為基礎的分頁容易遇到資料漂移與效能瓶頸,現代 API 越來越常採用cursor作為分頁策略。 - 網路不可靠性與冪等性(idempotency):在分散式系統中,超時不代表失敗。為了讓客戶端能安全重試,API 通常會透過冪等鍵(idempotency key)等機制,在伺服器正確實作時,避免或降低重複建立資源的風險。
契約優先與開發者體驗
二十年前的開發方式往往是寫好程式碼後,再藉由 Javadoc 產生說明。現代分散式與跨語言架構下,contract-first(契約優先)成為常見的架構選擇之一:先透過 OpenAPI 或 Protobuf 定義明確的 schema 契約,作為團隊跨語言通訊、mock 測試與自動化 SDK 產生(如 Fern)的核心契約(single source of truth),並追求更短的 time to first call。
AI agent 時代的 API 設計
在當前這個時代,API 的消費者已經不再侷限於人類工程師,越來越多是由大型語言模型驅動的 AI agent(自主代理人)。
當 API 成為 LLM 的 tool calling(函式呼叫)對象,或是透過 MCP(Model Context Protocol)接入代理人系統時,Bloch 的「難以誤用」原則被賦予了全新的意義:
- Schema 的精確與去歧義:人類工程師遇到含糊的參數說明可能還會去查原始碼或詢問同事,但 AI agent 更容易產生誤解或幻覺。
- 語意自明的工具描述:函式的描述(description)會直接成為模型可見上下文的一部分。工具的適用情境、先決條件與邊界約束都應盡可能清晰明確。
- 錯誤回傳的可操作性(actionable errors):當 agent 呼叫失敗時,回傳的錯誤訊息若只是模糊的「Bad Request」,模型難以自行修正;若能具體指出哪一個欄位格式不合、有效範圍為何,agent 就更有機會根據錯誤提示進行自我修復(self-correction)。
現代的延伸與超越:兩大分支與代表資源
如果你想要在 Bloch 的哲學基礎上建立更符合當代工程實踐的技能樹,現代的最佳資源取決於你的設計場景是網路服務(REST / gRPC)還是程式碼層級的程式庫(libraries / SDKs):
網路與伺服器端 API 設計
針對網路通訊、微服務與分散式架構,我會優先推薦以下三本書:
- JJ Geewax 的《API Design Patterns》(Manning 出版):這本書是 Bloch 的經典建議在 Web 與 RPC 時代極具啟發性的延伸閱讀。它提供了一套與特定協議無關的架構模式,專門解決 Bloch 當年從未涉足的現實挑戰:分頁機制、冪等性 token、背景長任務(long-running operations)、批次請求以及安全的局部更新(partial updates)。
- Arnaud Lauret 的《The Design of Web APIs, Second Edition》(Manning 出版):作者以「API Handyman」為名寫作。這本書專注於 HTTP/REST 與 web 服務的人體工學(ergonomics)與易用性,成功將 Bloch 風格的人本設計原則轉譯到 URI 層級結構、payload 契約、錯誤格式以及可探索性(discoverability)上。
- James Higginbotham 的《Principles of Web API Design: Delivering Value with APIs and Microservices》(Addison-Wesley 出版):這本書非常適合架構師研讀。它採用 job stories 與領域驅動設計(DDD)的方法,引導開發者以企業業務能力邊界來劃分 API,而不是單純將底層資料庫的 schema 直接暴露成介面。
程式庫與模組端 API 設計
如果你希望在程式碼與模組設計層面,將 Bloch 的哲學提升到更高的理論維度,這兩本書是極具代表性的參考:
- John Ousterhout 的《A Philosophy of Software Design》(2021 年第二版):如果說有哪本書能把 Bloch 的哲學推向更高的抽象層次,那就是這本當代經典。Ousterhout 提出了著名的 deep modules(深模組)概念——一個優秀的模組應該擁有極其簡單直覺的介面,背後卻隱藏了巨大的實作複雜度;相反地,那些只添加無謂樣板程式碼的 shallow modules(淺模組)則是他極力批判的反模式。這本書對「如何設計介面以隱藏複雜度」給出了無比嚴謹的論證。
- Jaroslav Tulach 的《Practical API Design: Confessions of a Java Framework Architect》:作者是 NetBeans 平台的創始人與架構師。這本書是一部詳盡深入的教科書,專門探討二進位層級的向後相容性(binary compatibility)、棄用生命週期(deprecation lifecycles),以及如何在跨越多年與多個大版本的演進中,盡可能不破壞呼叫端的既有程式碼。
業界指標規範
多家科技公司也將自身的 API 設計經驗整理為公開指南,成為 Bloch 核心哲學在真實生產環境中的延伸參考:
- Google Cloud API Design Guide:彙整了 Google 內部常用的設計慣例,針對資源導向架構(resource-oriented architecture)中的標準方法命名(
List、Get、Create、Update、Delete)、欄位行為與版本控制提供了詳細的實踐參考。 - Microsoft REST API Guidelines:在 GitHub 上歷經實戰檢驗的規範,詳細規定了錯誤結構、URL 模式、查詢字串、標頭設計以及冪等操作的最佳實踐。
- Zalando RESTful API Guidelines:深獲開源社群推崇的規範,特別聚焦於 JSON payload、OpenAPI / JSON Schema、超媒體(hypermedia)以及微服務間的通訊準則。
當程式碼全由 AI agent 撰寫,API 設計還重要嗎?
Joshua Bloch 當年的講題是《How to Design a Good API and Why it Matters》。但在軟體開發日益走向自主自動化的今天,一個不可迴避、也經常被工程師熱烈討論的問題浮現了:如果未來的程式碼絕大部分、甚至完全是由 AI agent 撰寫,人類不再逐行推敲語法,那麼「API 設計」到底還重不重要?
乍看之下,既然大型語言模型具備極強的程式碼理解能力,似乎再糟糕的介面它都能讀懂並產生相應的呼叫。但從實際的工程實踐來看,情況恰好相反:當程式碼主要由 AI agent 撰寫時,良好的 API 設計不僅依然重要,甚至比過去由人類手寫程式碼時更加關鍵。
這背後有三個深層原因:
上下文視窗的極限與深模組的必要性
雖然部分現代模型已支援數十萬甚至百萬 token 的上下文視窗(context window),但模型的注意力分配並非均勻且無限。
如果一個系統的 API 設計不良、職責邊界模糊,或是充滿了缺乏封裝的淺模組(shallow modules),AI agent 在處理任何單一任務時,就容易把寶貴的上下文容量耗費在周邊實作細節與樣板程式碼上。這不僅可能增加推論成本與延遲,也更容易稀釋模型對核心業務邏輯的專注度。
相反地,Bloch 所強調的「資訊隱藏」與 Ousterhout 倡導的「deep modules」——用極其精煉的介面遮蔽龐大的實作複雜度——恰好是降低 agent 認知負擔的利器。良好的 API 讓模型可以在極小的局部上下文中,進行高精確度的推理與程式碼產生。
「難以誤用」成為 AI agent 的安全護欄
人類工程師在遇到設計不良、充滿陷阱的 API 時,通常會感到困惑、皺起眉頭,然後停下來去查閱原始碼或與同事討論;但 AI agent 不一定會主動質疑介面設計,反而可能快速產生看似合理卻繞過缺陷的程式碼,甚至產生幻覺,將錯誤掩蓋在更深層的呼叫鏈中。
在自主迴圈(agentic loop)中,一個不直覺、容易被誤用的 API 會導致 agent 陷入反覆嘗試、修復失敗的死循環。Bloch 當年提倡的「Hard to misuse」與「Fail fast」,在人類時代是為了提升開發體驗與減少除錯時間;而在 AI 時代,它們實質上升級成了安全設計的重要一環,有助於防範自主代理人產生災難性錯誤。
實作可以隨時丟棄,但契約永遠長存
在 AI 輔助與自主編程的時代,撰寫「程式碼實作」的邊際成本正在急劇下降。一段不夠優雅的演算法、一個效能欠佳的函式,AI agent 可以在某些情境下快速重寫多個版本。
然而,API 契約(contract)卻無法隨意推倒重來。API 是跨模組、跨服務、甚至跨多個自主 agent 協同作業時關鍵的共識邊界之一。實作是消耗品,隨生隨滅;但介面是架構的骨架,一旦確立,就錨定了系統的溝通成本與演進彈性。
當人類開發者逐漸從「逐行撰寫程式碼的工人」轉變為「系統架構的設計者與審查者」,我們用來引導、約束並與 AI agent 溝通的最核心語言,正是 API。
總結:如何選擇適合你的現代指南?
回到最初的問題:時隔二十年,有比 Joshua Bloch 更好的 API 設計指南嗎?
答案很清晰:沒有任何單一資源能奪走 Joshua Bloch 作為入門哲學的桂冠;但現代工程師必須根據自己的工作場景,選讀相應的現代資源:
- 如果你專注於程式碼架構與模組設計:請研讀 John Ousterhout 的《A Philosophy of Software Design》,掌握 deep modules 的精髓。
- 如果你正在打造雲端、Web、微服務或 RPC 系統:請研讀 JJ Geewax 的《API Design Patterns》,並將 Google Cloud API Design Guide 作為日常開發的隨身參考標準。
二十年前,我們在單一程式記憶體裡追求「容易做對,難以做錯」;二十年後的今天,我們面對的是跨越網路、微服務與 AI agent 的全新的疆界。載體在變,但那個最根本的追求始終未變。