最近使用 Backbone.js 開發(fā)客戶端時發(fā)現(xiàn)了一個看似很小挣棕,實則非常麻煩的問題:
如何與非 CRUD 式的 RESTFul API 交互宁玫。
舉個例子贷盲,有一個活動 activity
模型淘这,它可以被開啟或者停止剥扣,有兩種解決方案:
- 使用 put 或者 patch巩剖,比如
/service/activities/:id
并傳遞參數(shù){status: :active}
- 使用額外的 endpoint, 比如
/service/activities/:id/active
如果使用第一種方式铝穷,那么就是標(biāo)準(zhǔn)的 CRUD 式的 API,Backbone.js
默認(rèn)就支持佳魔。
但是實際上開啟一個活動是一個比較大的動作曙聂,可能需要調(diào)用其他模塊的功能,不是簡單的改一個字段鞠鲜。
因此從 api 設(shè)計的角度我是傾向于使用第二種方式的宁脊。可是奇怪的是關(guān)于 Backbone.js 調(diào)用 CRUD 以外 的 API 的文章非常少贤姆,我翻遍 google 就勉強找到了這篇榆苞。通過臨時改變 model 的 url 屬性來實現(xiàn)的。 并沒有太讓我滿意霞捡。
正好晚上向 vincent 請教了一下這個問題坐漏,因為討論的重點是 api 設(shè)計而不是 backbone 的具體實現(xiàn), 反而開闊了我的思路碧信。
重新復(fù)習(xí)了一下 RESTful 的相關(guān)知識赊琳,發(fā)現(xiàn)了一個常見誤區(qū):
最常見的一種設(shè)計錯誤,就是URI包含動詞砰碴。因為"資源"表示一種實體躏筏,所以應(yīng)該是名詞,URI不應(yīng)該有動詞呈枉,動詞應(yīng)該放在HTTP協(xié)議中趁尼。
對于這個觀點爭論不少,畢竟類似于 /service/activities/:id/active
這樣的設(shè)計還是很常見的猖辫。 這個 AOE 范圍有點大酥泞。。住册。stackoverflow上有個討論可以參考婶博。其中我比較贊同的一點是:
In general, when you think you need more verbs, it may actually mean
that your resources need to be re-identified.
這里 提出的三種解決方案也可以參考。
舉個例子:
你是想打印一本書荧飞,還是發(fā)起一個打印的訂單請求凡人?
一樣的道理,我是要激活一個活動叹阔,還是發(fā)起一個激活活動的請求挠轴?
這個例子中,使用了名詞代替動詞耳幢。一旦變成了名詞岸晦,我立馬想到可以新建一個 model欧啤。
這下,只要創(chuàng)建一個 Backbone.js 的模型 startActivity
, 把它的 url 指向
/service/activities/:id/active
启上。
當(dāng)發(fā)起請求后(激活由于業(yè)務(wù)邏輯的限制邢隧,未必就會成功),后續(xù)的邏輯就可以都放在這個 startActivity
對象中冈在。
如果激活失敗就顯示錯誤信息倒慧,成功則通知 activity
模型重新渲染自己的視圖。
這樣結(jié)構(gòu)更加清晰包券。這未必是最好的解決方案纫谅,但是不失為一種不錯的思路。
這次我犯的錯誤是溅固,一開始總是從 Backbone.js 的方面找問題付秕。想要把 Backbone.js 變成 一把錘子來解決這個釘子。二是對 RESTful 這樣比較基礎(chǔ)的知識的理解還是不夠侍郭,否則思路也不會這么局限询吴。