天天看點

Swagger - 前後端分離後的契約

按照現在的趨勢,前後端分離幾乎已經是業界對開發和部署方式所達成的一種共識。所謂的前後端分離,并不是傳統行業中的按部門劃分,一部分人隻做前端(html/css/javascript等等),另一部分人隻做後端(或者叫服務端),因為這種方式是不工作的:比如很多團隊采取了後端的模闆技術(jsp, freemarker, erb等等),前端的開發和調試需要一個背景web容器的支援,進而無法将前後端開發和部署做到真正的分離。

通常,前後端分别有着自己的開發流程,建構工具,測試等。做前端的誰也不會想要用maven或者gradle作為建構工具,同樣的道理,做後端的誰也不會想要用grunt或者gulp作為建構工具。前後端僅僅通過接口來協作,這個接口可能是json格式的restful的接口,也可能是xml的,重點是背景隻負責資料的提供和計算,而完全不處理展現。而前端則負責拿到資料,組織資料并展現的工作。這樣結構清晰,關注點分離,前後端會變得相對獨立并松耦合。但是這種想法依然還是很理想化,前後端內建往往還是一個很頭痛的問題。比如在最後需要內建的時候,我們才發現最開始商量好的資料結構發生了變化,而且這種變化往往是在所難免的,這樣就會增加大量的內建時間。

不過,僅僅靠紀律是不夠的,還需要通過工具的輔助來提高效率。下面,我們就來看一下,一個api設計工具——swagger,将如何幫助我們更好的實作“前後端分離”。

swagger包括庫、編輯器、代碼生成器等很多部分,這裡我們主要講一下swagger editor。這是一個完全開源的項目,并且它也是一個基于angular的成功案例,我們可以下載下傳源碼并自己部署它,也可以修改它或內建到我們自己的軟體中。

在swagger editor中,我們可以基于yaml文法定義我們的restful api,然後它會自動生成一篇排版優美的api文檔,并且提供實時預覽。相信大多數朋友都遇到過這樣一個場景:明明調用的是之前約定好的api,拿到的結果卻不是想要的。可能因為是有人修改了api的接口,卻忘了更新文檔;或者是文檔更新的不及時;又或者是文檔寫的有歧義,大家的了解各不相同。總之,讓api文檔總是與api定義同步更新,是一件非常有價值的事。下面我們通過一個例子來感受一下swagger給我們帶來的好處。

當我們修改了api的定義之後,在編輯器右側就可以看到相應的api文檔了,而且永遠是最新的。

Swagger - 前後端分離後的契約

不僅如此,它還能夠自動生成mock server所需要的代碼,這樣一來前端開發就再也不用等着後端api 的實作了。除此之外,它還有一個更強大的功能,甚至能夠幫助我們自動生成不同語言的用戶端的代碼。swagger是基于插件來實作各種不同的語言的,是以,如果已經提供的語言中沒有你正在用的,你也可以自己實作相應的插件,甚至是從源代碼級别進行定制化。

Swagger - 前後端分離後的契約

談到了前後端分離,那麼在所難免,會遇到一些內建的問題:一撥人在全心全意的進行前端開發,另一撥人在心無旁骛的做後端開發,那麼誰應該為內建買單呢?在現在這個持續內建、持續傳遞的年代裡,我們應該如何去保證雙方不會分道揚镳、越走越遠呢?

是以,在一開始就定一個契約就成了迫在眉睫的事情,雙方就api相關的内容,包括路徑、參數、類型等達成一緻,當然,這份契約并不是一旦建立就不能修改的,而且,如果一開始沒有設計好,很有可能會頻繁的修改。這個時候,要讓雙方都能夠實時的跟蹤最新的api就成了一個難題。還好,在總結了前人的經驗和教訓之後,我們早已有了應對之策,那就是<code>契約測試</code>。

首先,我們先假設我們已經有了一份契約,可能是基于json格式的,有可能是基于xml格式的,這都不重要。然後,前端會根據這份契約建立一個mock server,所有的測試都發往這個mock server。有兩方面的原因:一是這個時候可能背景的api還沒有開發完成;二是有可能因為網絡等其他方面的原因導緻直接調用真實的背景api會很不穩定或者很耗時。到這裡,可能有人就要說了,如果背景的api實作和之前約定的并不一樣,怎麼能保證到了內建的時候雙方還能很順利的內建呢?其實這個問題并不難,隻需要讓前端的測試定期連接配接真實的api執行一遍就能盡早的發現差異性。比方說,在我們平常的build pipeline上添加一個job,讓這些測試每天在午夜裡連着真實的api執行。如果,第二天發現這些測試有的失敗了,那麼就需要和開發背景api的人員進行一次溝通了,很有可能由于真實的業務邏輯發生了變化,api在實作的時候,已經和之前的契約不一緻了,如果是這樣,那麼相應的測試和契約定義就需要更新以滿足最新的業務需求。

總之,進行契約測試的目的就是盡早的發現差異性,并作出調整,将最後內建的風險降到最低。