驱动api_消费者驱动契约已死?
吐槽文一篇。
契約的一些問題
在實踐前后端分離的這些年來,已經誕生了一些技術與工具讓前后端進行溝通:
- 契約的 Mock 服務(Mock Server)。用于模擬一個服務器,為特定的接口返回特定的值。
- 契約測試。對前后端協定的 API 進行測試。
- 前后端膠水層。如 BFF (Backends for Frontends),根據客戶端的需要對 API 進行聚合、適配、裁剪等。
而使用這些工具的時候,往往容易出現一些問題。
消費者無法驅動的契約
消費者驅動,顧名思義就是在我們協定契約的時候,按消費者的業務實現角度,與生產者一起協定契約。在實踐上,往往由于后端在項目中的主導地位導致:協商的結果不會按消費者需要,而是按生者需要來生成契約。造成這種結果的因素有很多:
我的意思并不是說,按生產者來主導有什么問題,而是配不上『消費者驅動』這五個字。諸如于我們獲取某個 API 的時候,前端所需要的是相關的信息,而不是對應的實體 ID。而后,再由前端去獲取對應實體的信息。從邏輯上來說,由前端獲取或者后端獲取,從技術上來說,并沒有多大的問題。但是從用戶體驗上來說,并沒有那么友好。后端間的 API 調用,可以是幾十 ms 級別的;而前端多調用一個后端 API,在網絡上的傳輸時間,往往都是幾百 ms,乃至幾秒。
生產者的契約測試
所以,讓我們再看看各個團隊所宣稱的消費者驅動的契約測試。
消費者驅動的契約測試(Consumer-Driven Contracts,簡稱CDC),是指從消費者業務實現的角度出發,驅動出契約,再基于契約,對提供者驗證的一種測試方式。如果你不是消費者驅動的契約,而是后端一口氣定出來的接口,你怎么能叫『消費者驅動的契約測試』????按這樣的做法,它只能叫生產者的契約測試。
既然是生產者的契約測試,那么它就無法保證說:API 修改不影響消費者使用——因為消費者壓根就沒有參與到契約的制定,生產者可以按照自己的需要來修改契約。
所以,生產者到底是在給誰測試?又是在測試什么東西?
契約測試的契約作為 Mock Server——不行
在大部分的項目中,對于契約的使用存在問題,即模式錯了。契約測試需要圍繞業務流程施展,而不應該相互隔離。如果契約的用例不豐富,便無法串起整個系統的流程。而作為 API 的提供方,應該保證業務邏輯是可以串聯起來的。從用戶的登錄開始,到用戶獲取數據,展示列表頁,能進入詳情頁等等。
我們做契約測試的目標是,讓代碼修改不影響 API 輸出。后端需求一改,契約測試會掛,后端知道出現問題,會進行修復。如果前端用的是契約測試的契約提供的 Mock Server,前端的測試也會掛,這樣問題就不會往后流。
所以,契約不應當給前端做本地開發和測試 。
沒有契約的 Mock Server——不行
對于小團隊來說,去采用原始的 API 方式反而更加有效率;對于大團隊來說,這樣的方式并不可行。
既然,溝通那么麻煩,那么我們就分開吧。如果契約和 Mock Server 是分開的,那么維護前端 Mock Server 的人很很難識別到修改。相關的問題,在測試不及時的情況下,有可能在上線后才發現。
也因此,從理想情況來說,這個 Mock Server 是契約動態生成的,并能根據后端現有最新的契約更新。或者,后端在實現契約測試時,要做的是只測試部分數據,而不是為了測試而測試。
只有 DDD 的微服務——不行
盡管 DDD 模型不一定非要與 API 綁定,但是由于種種原因,真正在實踐的時候,就不是這么一回事。我們可以看到在很多的項目里,DDD 返回的實體資源,最后可能與 API 的字段一致的。但是它并非是業務上想要返回的邏輯,各個客戶端(PC Web、小程序、Android 端、iOS 端等)還都需要進行二次的處理。
這就是為什么,DDD + 微服務,一定要配合一下 BFF 的原因。
缺少前端、后端的 BFF——不行
實施 BFF,大家并沒有啥問題。可一誰來維護這一層膠水層的時候,大家都問題都來了——前后端都不愿意維護這個 BFF。對于前端來說,開發者只是 API 的消費者,突然間又變身成為生產者;對于后端來說,開發者原本不需要了解顯示邏輯,現在也要涉及到這部分的內容。
不過呢,我們可以保持一致的是:后端是 API 的生產者。而如果生產者沒有參與到 BFF 的開發,那么就會引發另外一個問題,API 發生變更的時候,可能沒有同步到 BFF——盡管每個項目都有自己的規范,但是只要是由人來執行的,都可能會出現問題。
那么,我們就需要一個 BFF 的契約測試,那在第一時間知道 API 的變化。雖然感覺怪怪的,但是我們還是將客戶端的契約測試,前移至了 BFF 層。
所以,消費者驅動的契約在哪里呢?
解決方案
BFF
大家都懂了。
前端為主寫 BFF
前端寫 BFF 并不是一件容易的事。你要懂微前端,要懂主流的微服務框架,如 Spring Cloud,要懂 Java。與此同時,還需要了解各個 API 的變化 情況。對于前后端分離團隊而言,要做樣的工作太難了。
而盡管你可以采用 Node.js + TypeScript,但是它也意味著你要成為一個 Node.js 專家。如果讓我用 Node.js 寫 BFF,那我還是寧愿和以前的項目一樣,寫 Scala 來作為 BFF。
所以,我并不推薦使用 Node.js 作為 BFF。一來,沒有阿里巴巴強大的 Node.js 專家群;二來,我對于成為 Node.js 沒有興趣。用擅長于某一領域的語言去做某一領域的事,而非用擅長的語言去做每一領域的事——興趣和愛好除外。
GraphQL as BFF
大家都懂了。
前端防腐層
參考《整潔前端架構》。
消費者的契約測試
我們在諸多項目實現了:針對于生產者的契約測試。其中也包含了之前我寫的 mest 框架,它是通過結合 TypeScript 的 Interface 來驗證后端接口是否一致。
當你沒有辦法的時候,這也是一個不那么差的做法。換個問題來思考的話,就是以生產者來解決這些問題。
直接轉換模型為 Java Class 和 TypeScript 是一種更簡單的做法。
結論
沒有銀彈。
總結
以上是生活随笔為你收集整理的驱动api_消费者驱动契约已死?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 操作系统之(一篇文章让你简单搞定:什么是
- 下一篇: 现代操作系统初理解