用產品思維設計API(二)——數據解耦,才是前後分離的本質
前言
最近公司內部在重構項目代碼,包括API方向的重構,期間遇到了很多的問題,不由得讓我重新思考了下。
- 一個優雅的API該如何設計? - 前後端分離之後,API真的解耦分離了嗎? - 不斷的版本迭代,API的兼容性該如何做?ps.這裡所說的API僅為Web API,提供APPWEB開發使用。
年前,我司內部的介面已經進入了一個完全的重構階段,參考了市面上各大平台的API和文檔,自己也總結出了很多的心得。這裡向大家分享一下,接下來一個月,我們向從下面幾個方面向大家介紹一個優雅的API(至少我認為挺優雅)該如何設計。
- RESTful就是個騙局 (用產品思維設計API(一)--RESTful就是個騙局 - 北漂周的專欄(微信:stchou_zst) - 博客頻道 - CSDN.NET)
- 數據解耦,才是前後分離的本質(用產品思維設計API(二)--數據解耦,才是前後分離的本質 - 北漂周的專欄(微信:stchou_zst) - 博客頻道 - CSDN.NET)
- 版本控制,沒有你想的這麼簡單
- 隨意定義錯誤碼,你還在這樣干?
- 安全,就只能用HTTPS?
ps. 打一個廣告,公司內部現在在招聘各種技術崗位,Java、Android、前端等,待遇保證能讓你漲30%,有興趣的朋友可以加韜哥的微信(微信號:stchou_zst),二維碼在文章最後。
明確需求就開始研發,哪裡錯了?
一個移動應用的從無到有,必須經過需求討論、交互/UI設計、資料庫設計、API設計、APP開發、聯調、測試等階段。而在整個研發的流程中API的設計有起到了承上啟下的作用。
我們這裡從新回顧一個APP迭代的開發流程:
需求 —— 採用用例圖描述需求
分析 —— 明確解決問題的細節
設計 —— 給出交互、設計解決方案
開發 —— 將類用某面向對象語言實現
測試 —— 單元測試等
通常,我們都會在需求理清楚之後,產品給出交互圖就開始了整個資料庫設計、UML、API開發等等。
等等,貌似有哪裡不對。設計出來之後,對接的人往往是前端客戶端研發同事,後台同事只管需要下發哪些數據,真的不需要理解前端的交互嗎?
數據展示型API——面向用戶設計
作為後端研發人員,你的用戶是誰?——毫無以為,肯定是調用API的其他段的開發同事。那麼API的開發就得對用戶負責(負責,並不僅是寫一個方便閱讀的文檔而已)。
- Android、iOS、H5三端的同事如何調用的你的API?
- 他們在調用你的API繪製界面上使用是否費勁?
- 後期迭代中API能否兼容?
- 客戶端是否要發版?強制更新?
- ……
都是你需要考慮的。
這裡我們也不賣關子,直接說出鄙人得出的結論:
需要參與計算的值統一按照存儲類型下發,僅作為顯示的值統一按字元串下發。
後台研發:前端展示關我屁事!
我們的結論說起來很簡單,但是在實際的工作中我們能夠看到,許多的同事並沒有一個全局的可發展的思維,我能做出來就行了,需要的數據都有,你們怎麼展示,怎麼交互我不管了。
ps.越是在大型企業之中,牛人越多,牛人越多的地方自以為是的人就越多。別問我怎麼知道的,鬼知道我經歷了什麼。
多說無益,馬上來個Demo,如下所示,我們要做一個產品的詳情頁:
這個頁面看起來功能並沒有多少,簡單分析一下:
- 4個跳轉按鈕
- 一個展示內容的Tab
- 一個頭部特殊展示信息。
大概估算一下客戶端研發時間,3天左右,夠了。
Ok,當你你屁顛屁顛的向上級彙報你的工作量完了之後,1天後API開發好了,簡單的調了一下API你瞬間就石化了。API返回結果如下:
JSON
{ "totalCount": 99, "data": [ { "id": 8055,"sTitle": "浙金信託-匯城47號",
"productTypeId": 1, "zdPrice2": 0.93, "nianHuaShouYiStart": 6.7, "nianHuaShouYiEnd": "7.0", "jdt": 0, "touZiLingYu": "基礎設施類", "level": 99, "saleStatus": 20, "category": 30,"jdTime": "2017-01-04 09:33:27",
"raiseProgress": "【2017年1月4日9時更新】本期第一期,本期規模不限,開放打款中,封賬時間根據進款情況安排,有下一期。(三大一小配比,需要錄音錄像)", "touZiMenkan": 100, "collectCount": 4, "hasCollect": false, "redPack": "", "fundType": null, "visitCount": 47315, "docPreviewCount": 4, "producttagids_intarray": " 13 4 71","productTags": "4,基礎設施類;13,固定收益類;71,三年期;",
"title": "浙金信託-匯城47號(第1期)", "bid": 1, "statusId": 40, "qiXian": 36, "peibi": "三大一小配比", "pmName": "王月", "pmUserName": "王月", "daXiao": "嚴格配比", "lingYu": "基礎設施類","shouYiType": "固定收益類",
"payStatus": "半年付息", "downLoad": "Upload/ProductPDF/20161223/浙金-匯城47號_521.zip", "groupName": null, "zdPrice": 0.5, "addr": null, "companyId": 23, "adminId": 521, "groupMaxPrice": 0, "nianHuaShouYiExt": "","companyName": "恆天",
"fxList": [ { "title": "100萬≤X<300萬", "price": "0.93%", "isFloat": false, "earningRate": "6.7%", "packingRate": 6.7 }, {"title": "300萬≤X",
"price": "0.5%", "isFloat": false, "earningRate": "7%", "packingRate": 7 } ], "sourceRepayment": "1.安順市西秀區財政收入2.融資人西秀城投的經營收入
3.擔保人西秀工投的經營收入", "fundInvest": "用於受讓西秀城投持有的對西秀區政府的標的債權", "windControl": "1.安順市西秀區工業投資(集團)有限公司提供連帶責任保證擔保
2.受讓西秀城投對西秀區政府已納入國務院地方債務系統的8.05億應收賬款", "highlights": "市場稀缺中央《預案》承認地方政府存量債務政信、發債融資主體16年11月已發行15億7年期債券完全覆蓋本次融資本息及期限!", "productOrganizationId": 307, "productOrganizationPic": "Upload/ProductOrganization/20160118/2016011818020432129312.jpg", "bqqsr": "2017-01-03 00:00:00", "province": 520000, "proviceName": "貴州省", "cityName": "安順市", "dyl": -1, "addrId": null, "updateTime": "2017-01-04 17:58:13", "listingTime": "2016-12-23 16:29:35", "parentId": 8055, "phase": 1, "issuerCompanyId": 0, "issuerCompanyName": "", "issuerId": 2492, "issuerPhone": "13552818811", "issuerName": "陳敏 ", "project": 3, "attr": 3, "jianBan": "", "appointmentCount": 5, "downloadCount": 716, "sendEmailCount": 21, "cashback": "", "tagsArray": [ { "id": "13", "name": "固定收益類" }, { "id": "4", "name": "基礎設施類" }, { "id": "71", "name": "三年期" } ], "bestEarningRate": "7%", "bestEarningRate_fore": 7, "bestEarningRate_back": "0", "bestPrice": "0.93%", "bestPrice_fore": 0, "bestPrice_back": "93", "bestGroupPrice": "待定", "bestGroupPrice_fore": "待定", "bestGroupPrice_back": 0, "bestEmployeePrice": "待定", "bestEmployeePrice_fore": "待定", "bestEmployeePrice_back": 0, "saleStatusName": "在售", "isNew": false, "isHot": false, "isHotSale": true, "isRecommend": false, "packingRate": 0, "returnCash": 0 } ], "isSuccess": true, "code": 0, "runSpanTime": 41 }
不就是展示頁面嗎?也沒啥交互啊!也沒有什麼邏輯處理啊!為什麼這麼難?
看完之後,我相信估計沒有一個人是在不看文檔的情況下能理解每一個欄位是什麼信息的。一系列的問題隨之出現。
- 「產品名字」是哪個欄位?該在哪裡展示?
- 「大小配比」是哪個欄位?該在哪裡展示?
- 「發行機構」是哪個欄位?該在哪裡展示?
- 「產品期限」是哪個欄位?該在哪裡展示?
- ………
- 是不是要建立一個大的Bean來存儲這個對象?
- 是不是要緩存裡面信息?本地緩存資料庫怎麼建立?
- 同級別的產品類型還有13個,是不是每一個類別我都得看一次文檔,重複一下這個噁心的事。
- ………
當然,我們不能這麼做,這個API讓調用它的研發者感到噁心,就是沒有服務好用戶。
API從數據上必須解耦,不能將整個資料庫的理解扔給前端。
重新設計!!!!按照解耦法則分析一下這個頁面:
首先,將需求中的展示類型,進行劃分
- 左右型
- 上下型
demo:
認購金額(萬元) 預期收益 返佣比例300-9906.8% 登錄可見1000+7% 登錄可見ok,加入顏色控制,我們得出了結論,重構了一下介面如下:
雖然,層級比較多,但是我們已經定義了展示類型,前端只需要做循環,就能夠將整個頁面展示出來,完全不需要了解每個欄位什麼意思。我們這裡稱之為:API設計之——鍵值對大法。
列表顯示,統一格式返回
鍵值對大法雖然好,但是並不是適合於很多複雜顯示的交互之中,特別是針對移動APP的研發,我們的頁面KV展示的結構也比較少。那麼,在移動開發之中我們最常見的交互是什麼呢?
毫無疑問——列表頁
分析了一下現在項目之中的列表頁
- ProductListActivity (產品列表)
- BookMarkListActivity (收藏列表)
- RelativeListActivity (推薦列表)
- OrderListActivity (訂單列表)
- ……………
那麼,常見的列表頁交互我們分析一下有:
- 下拉刷新
- 上拉載入更多
- 不同項Item點擊跳轉,操作
除去 每一個ListItem 的操作不一樣 ,我們發現,其實每一個列表頁都差不多。那麼,這個地方我們是不是也可以抽象? 抽象到直存在一個頁面,裡面展示的內容項都是後端下發的?
答案是肯定的,首先我們與後端約定一個item項的type,如:
ListType 說明1 產品列表項
2 收藏列表項
3 推薦列表項
4 訂單列表項
然後,我們可以把通用的交互抽象出來,把整個數據適配器(Adapter)根據規則進行Mapping,指向到每一個單獨的ListItem之中。如下:
發現了什麼?
- 以後再來一個列表形式的需求,只需要添加Mapping和新的ListItem操作即可,如果出Bug也只是這個ListItem的Bug不會產生連帶影響。(降低Bug出現的影響面)
- 其次,一個列表中不定ListType的顯示也變成了後端配置,每個列表頁面都可以隨時更換已知顯示樣式。(後端可控,不用重複發版)
如今日頭條之中,N多tab,N多不同的ListItem(股票、新聞、圖文、視頻、頭條號等)類型,也就是這麼設計出來的。我們這裡稱之為:API設計之——Type大法。
「大法好,退出客戶端思維才能保平安!」。其實,還有很多API設計方向的小技巧,但是上面韜哥覺得是做得較好的地方,先只向大家分享這兩個。有興趣的加個微信一起交流交流。
寫在後面,最近快過年了,公司業務繁忙,重構任務重大,更新博客也慢了。希望大家多多包涵。
@author zhoushengtao(周聖韜)
@since 2017年1月7日 23:06 @weixin stchou_zst @blog 北漂周的專欄(微信:stchou_zst) - 博客頻道 - CSDN.NEThttp://weixin.qq.com/r/wUkhOTzEMWFOrXha9xzT (二維碼自動識別)
推薦閱讀:
※如何看待「機器學習不需要數學,很多演算法封裝好了,調個包就行」這種說法?
※知乎將如何做開放?
※開源介面管理平台 yapi 發布 v1.2.8版本
※了解Revit API
※基於阿里雲打造時序資料庫硬體API