如何設(shè)計(jì)一個(gè)優(yōu)秀的API
到目前為止,已經(jīng)負(fù)責(zé)API接近兩年了,這兩年中發(fā)現(xiàn)現(xiàn)有的API存在的問題越來越多,但很多API一旦發(fā)布后就不再能修改了,即時(shí)升級(jí)和維護(hù)是必須的。一旦API發(fā)生變化,就可能對(duì)相關(guān)的調(diào)用者帶來巨大的代價(jià),用戶需要排查所有調(diào)用的代碼,需要調(diào)整所有與之相關(guān)的部分,這些工作對(duì)他們來說都是額外的。如果辛辛苦苦完成這些以后,還發(fā)現(xiàn)了相關(guān)的bug,那對(duì)用戶的打擊就更大。如果API經(jīng)常發(fā)生變化,用戶就會(huì)失去對(duì)提供方失去信心,從而也會(huì)影響目前的業(yè)務(wù)。
但是我們?yōu)槭裁催€要修改API呢?為了API看起來更加漂亮?為了提供更多功能?為了提供更好的性能?還是僅僅覺得到了改變了時(shí)候了?對(duì)于用戶來說,他們更愿意使用一個(gè)穩(wěn)定但是看起來不那么時(shí)髦的API,這并不意味著我們不再改進(jìn)API了。當(dāng)糟糕的API帶來的維護(hù)成本越來越大時(shí),我想就是我們?nèi)ブ貥?gòu)它的時(shí)候。
如果可以回頭重新再做一遍,那么我心目中的優(yōu)秀的API應(yīng)該是怎么樣的?
判斷一個(gè)API是否優(yōu)秀,并不是簡單地根據(jù)***個(gè)版本給出判斷的,而是要看隨著時(shí)間的推移,該API是否還能存在,是否仍舊保持得不錯(cuò)。槽糕的API接口各種各樣,但是好的API接口對(duì)于用戶來說必須滿足以下幾個(gè)點(diǎn):
- 易學(xué)習(xí):有完善的文檔及提供盡可能多的示例和可copy-paste的代碼,像其他設(shè)計(jì)工作一樣,你應(yīng)該應(yīng)用最小驚訝原則。
- 易使用:沒有復(fù)雜的程序、復(fù)雜的細(xì)節(jié),易于學(xué)習(xí);靈活的API允許按字段排序、可自定義分頁、 排序和篩選等。一個(gè)完整的API意味著被期望的功能都包含在內(nèi)。
- 難誤用:對(duì)詳細(xì)的錯(cuò)誤提示,有些經(jīng)驗(yàn)的用戶可以直接使用API而不需要閱讀文檔。
而對(duì)于開發(fā)人員來說,要求又是不一樣的:
- 易閱讀:代碼的編寫只需要一次一次,但是當(dāng)調(diào)試或者修改的時(shí)候都需要對(duì)代碼進(jìn)行閱讀。
- 易開發(fā):個(gè)最小化的接口是使用盡可能少的類以及盡可能少的類成員。這樣使得理解、記憶、調(diào)試以及改變API更容易。
如何做到以上幾點(diǎn),以下是一些總結(jié):
1、 面向用例設(shè)計(jì)
如果一個(gè)API被廣泛使用了,那么就不可能了解所有使用該API的用戶。如果設(shè)計(jì)者希望能夠設(shè)計(jì)出被廣泛使用的API,那么必須站在用戶的角度來理解如何設(shè)計(jì)API庫,以及如何才能設(shè)計(jì)出這樣的API庫。
2、 采用良好的設(shè)計(jì)思路
在設(shè)計(jì)過程中,如果能按照下面的方式來進(jìn)行設(shè)計(jì),會(huì)讓這個(gè)API生命更長久
- 面向用例的設(shè)計(jì),收集用戶建議,把自己模擬成用戶,保證API設(shè)計(jì)的易用和合理
- 保證后續(xù)的需求可以通過擴(kuò)展的形式完成
- ***版做盡量少的內(nèi)容,由于新需求可以通過擴(kuò)展的形式完成,因此盡量少做事情是抑制API設(shè)計(jì)錯(cuò)誤的一個(gè)有效方案
- 對(duì)外提供清晰的API和文檔規(guī)范,避免用戶錯(cuò)誤的使用API,尤其是避免API(見***節(jié))靠后級(jí)別的API被用戶知曉與誤用
除此之外,下面還列出了一些具體的設(shè)計(jì)方法:
- 方法優(yōu)于屬性
- 工廠方法優(yōu)于構(gòu)造函數(shù)
- 避免過多繼承
- 避免由于優(yōu)化或者復(fù)用代碼影響API
- 面向接口編程
- 擴(kuò)展參數(shù)應(yīng)當(dāng)是便利的
- 對(duì)組件進(jìn)行合理定位,確定暴露多少接口
- 提供擴(kuò)展點(diǎn)
3、 避免極端的意見
在設(shè)計(jì)API的時(shí)候,一定要避免任何極端的意見,尤其是以下幾點(diǎn):
- 必須漂亮(API不一定需要漂亮)
- API必須被正確地使用(用戶很難理解如何正確的使用API,API的設(shè)計(jì)者要充分考慮API被誤用的情況:如果一個(gè)API可能會(huì)被誤用,那么它一定會(huì)被誤用)
- 必須簡單(我們總會(huì)面臨復(fù)雜的需求,能兩者兼顧的API是更好的API)
- 必須高性能(性能可以通過其他手段優(yōu)化,不應(yīng)該影響API的設(shè)計(jì))
- 必須絕對(duì)兼容(盡管本文一直提到如何保證兼容,但是我們?nèi)匀灰庾R(shí)到,一些極少情況下會(huì)遇到的不兼容是可以容忍的)
4、 有效的API評(píng)審
API設(shè)計(jì)完成以后,需要經(jīng)過周密的設(shè)計(jì)評(píng)審,評(píng)審的重點(diǎn)如下:
- 用例驅(qū)動(dòng),評(píng)審前必須提供完善的使用用例,確保用例的合理性和完備性。
- 一致性,是否與系統(tǒng)中其他模塊的接口風(fēng)格一致,是否與對(duì)稱接口的設(shè)計(jì)一致。
- 簡單明了,API應(yīng)該簡單好理解,容易學(xué)習(xí)和使用的API才不容易被誤用,給我們帶來更多的麻煩。
- API盡可能少,如果一個(gè)API可以暴露也可以不暴露,那么就不要暴露他,等到用戶真正有需求的時(shí)候再將它成為一個(gè)公開接口也不遲。
- 支持持續(xù)改進(jìn),API是否能夠方便地通過擴(kuò)展的方式增加功能和優(yōu)化。
5、 提高API的可測(cè)試性
API需要是可測(cè)試的,測(cè)試不應(yīng)依賴實(shí)現(xiàn),測(cè)試充分的API,尤其是經(jīng)過了嚴(yán)格的“兼容性整合測(cè)試”的API,更能保證在升級(jí)的過程中不出現(xiàn)兼容性問題。兼容性整合測(cè)試,是指一組測(cè)試用例集合,這組測(cè)試用例會(huì)站在使用者的立場(chǎng)上使用API。在API升級(jí)以后,再檢測(cè)這組測(cè)試用例是否能完全符合預(yù)期的通過測(cè)試,盡可能的發(fā)現(xiàn)兼容性問題。
6、 保證API的向后兼容
對(duì)于每一個(gè)API的設(shè)計(jì)者來說,都渴望做到“向后兼容”,因?yàn)椴还苁乾F(xiàn)在的API用戶,還是潛在的API用戶,都只信任那些可兼容的API。但向后兼容有多個(gè)層次上的意義,而且不同層次的向后兼容,也意味著不同的重要性和復(fù)雜度。
7、 保持逐步改善
過去我們總希望能將現(xiàn)有的“不合理”的設(shè)計(jì)完全推翻,然后按照現(xiàn)在“美好”的思路,重新設(shè)計(jì)這個(gè)API,但是在一段時(shí)間以后,又會(huì)碰到一樣的狀況,需要再推翻一次。 如果我們沒有有效的逐步改善的辦法,依靠推翻現(xiàn)有設(shè)計(jì),重新設(shè)計(jì)API只能讓我們回到起點(diǎn),然后重現(xiàn)之前的過程。 要有一套行之有效的持續(xù)改善的辦法來在API兼容的同時(shí),改善API使之更好。
8、 把握API的生命周期
每一個(gè)API都是有生命周期的,我們需要讓API的生命周期更長,并且在API的生命周期結(jié)束時(shí)能讓其平滑的消亡。
- 告訴用戶我們是如何設(shè)計(jì)的,避免誤用,提供指導(dǎo),錯(cuò)誤的使用往往是縮短API壽命的一大殺手
- 提供試用期,API不可能一開始就是穩(wěn)定,經(jīng)過試用的API才能有更強(qiáng)的生命力
- 為API分級(jí):內(nèi)部使用;二次開發(fā)使用;開發(fā)或試用中;穩(wěn)定;棄用API。避免API被濫用的同時(shí),我們可以通過調(diào)整API的級(jí)別,來擴(kuò)大其影響力,也能更優(yōu)雅的結(jié)束一個(gè)API的生命周期。
開發(fā)API的過程其實(shí)就是一個(gè)溝通交流的過程。溝通的雙方就是API用戶和API設(shè)計(jì)者。
9、 一些具體的實(shí)施方案
在一個(gè)API不可避免要消亡或者改變的時(shí)候,我們應(yīng)該接受并且面對(duì)這個(gè)事實(shí),下面列舉了幾種保證兼容性的前提下,對(duì)API進(jìn)行調(diào)整的辦法:
- 將API標(biāo)記為棄用,重新建立一個(gè)新的API。如果一個(gè)API不可避免要被消亡,這是唯一的辦法。
- 為其添加額外的參數(shù)或者參數(shù)選項(xiàng)來實(shí)現(xiàn)功能添加
- 將現(xiàn)有API拆成兩部分,提供一個(gè)精簡的核心API,過去的API通過封裝核心API上實(shí)現(xiàn)。這通常用于解決用戶需要一個(gè)代碼精簡的版本時(shí)。
- 在現(xiàn)有的API基礎(chǔ)上進(jìn)行封裝,提供一個(gè)功能更豐富的包或者類
一些好的API示例:
- Flickr API,這里是文檔的示例,同時(shí)提供了一個(gè)非常方便的API測(cè)試工具。
- Mediawiki API
- Ebay API,這里有一個(gè)非常詳盡的文檔示例。
原文鏈接:http://www.biaodianfu.com/how-to-design-a-good-api.html