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