设计优秀API的五大规则
人們在如何設計一款優秀的API上有著很強烈的意識。在互聯網上有關API方面的網頁和書籍有很多很多。本文我們將重點關注設計優秀API的規則。
規則就是當發生任何變化時,應當遵循“最小驚奇原則”。無論你想嘗試什么樣的個人風格或者品味,你都可以添加到API中,因此,這是優秀的API理應具備的特性之一。
設計“正規”API理應注意的幾件事情:
規則1:建立強有力的條款
隨著API的不斷增長,這些條款會被重復使用。例如,這些行為會導致各種類/類型/方法(classes/types/methods)產生不同微妙的行為。
事實上,他們看起來很相似,需要通過命名來區分。以JDBC為例,無論你執行哪條語句,你都需要使用它們來執行。比如,你可以調用這些方法:
- execute(String)
- executeBatch()
- executeQuery(String)
- executeUpdate(String)
與之類似,無論你發布哪些資源,你都經常使用條款,比如,你會調用:
- Connection.close()
- Statement.close()
- ResultSet.close()
事實上,close在JDK中是一款強大的且已被確立的條款,這就導致java.io.Closeable (since Java 1.5)與java.lang.AutoCloseable (since Java 1.7)接口建立了釋放資源約定。
違反例子1:Observable
這條規則違反了JDK中的一組條款,比如java.util.Observable類。當其他“Collection-like”類型成立條款時:
- size()
- remove()
- removeAll()
該類聲明
- countObservers()
- deleteObserver(Observer)
- deleteObservers()
同樣適用于Observer.update(),實則應稱為notify(),JDK API里的另一個術語。
違反例子2:Spring.?
目前,Spring已得到了普及,很多Java項目都使用Spring框架,那么Spring又是如何違反這條規則的呢?
- AbstractBeanFactoryBasedTargetSourceCreator
- AbstractInterceptorDrivenBeanDefinitionDecorator
- AbstractRefreshablePortletApplicationContext
- AspectJAdviceParameterNameDiscoverer
- BeanFactoryTransactionAttributeSourceAdvisor
- ClassPathScanningCandidateComponentProvider
- J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource.
下面進行客觀點的分析:
- Creator和Factory之間有何區別?
- Source和Provider之間又有何區別?
- Source和Provider非微妙的差異是什么?
- Discoverer和Provider非微妙的差異是什么?
- ?Advisor和AspectJAdvice有關聯嗎?
- ScanningCandidate還是CandidateComponent?
- TargetSource是什么?它與SourceSource區別是什么?SourceSourceTargetProviderSource與SourceTarget之間有何差別?
規則2:在組合上運用對稱
一旦你創建強有力的條款,你會開始將他們結合起來。當你看到JDK收集APIS,你會注意到它們以對稱的方式創建條款add()、remove()、contains()等等,在將其結合之前:
- add(E)
- addAll(Collection<? extends E>)
- remove(Object)
- removeAll(Collection<?>)
- contains(Object)
- containsAll(Collection<?>)
現在,Collection類型就是個很好的例子,當規則發生異常時,這個方法便不適用了。這可能是因為在retainAll(Collection<?>)情況下,不使用equivalent retain(E) 方法。
規則3:使用重載
人們之所以使用方法重載,主要是因為它給程序帶來了許多方便。你經常希望在不同的地方做相同的事情,但每次去構造方法又很繁瑣,那怎么辦?你只需為API用戶在相同的方法里提供額外的變量,并且把參數類型設置成友好型(friend)。下面以Collection為例:
- toArray()
- toArray(T[])
另外一個是Arrays utility類:
- copyOf(T[], int)
- copyOf(boolean[], int)
- copyOf(int[], int)
使用重載的兩大原因:
1.?提供“default”參數行為,正如Collection.toArray()
2.?支持一些不兼容的“相似”參數設置,如 Arrays.copyOf()
違反例子1:TreeSet
在JDK中很難找到一個例子,是與本規則相違背的,但也有另外,就是TreeSet和TreeMap。他們的構造函數可以被多次重載,下面讓我們來看下這些構造函數:
- ? TreeSet(Collection)
- ? TreeSet(SortedSet )
這兩個構造函數在不同的操作行為下,返回的值也是不一樣的:
| 1 2 3 4 5 6 7 | SortedSet<Object> original =// [...] ?? // Preserves ordering: new TreeSet<Object>(original); ?? // Resets ordering: new TreeSet<Object>((Collection<Object>) original); |
規則4:參數順序一致
為了確保參數順序的一致性,把數組類型放在第一位會給你帶來很多好處:
- copyOf(T[], int)
- copyOf(boolean[], int)
- copyOf(int[], int)
你會注意到,在上面那個類中,把所有數組操作都放在第一位,一些其他例子:
- binarySearch(Object[], Object)
- copyOfRange(T[], int, int)
- fill(Object[], Object)
- sort(T[], Comparator<? super T>)
違反例子1:Arrays
Array是如何違反這條規則的,它在兩個參數之間添加了一些可選參數,如:
- fill(Object[], Object)
- fill(Object[], int, int, Object)
依照這種方式,copyOfRange()也和fill()一樣,遵循了相同的參數順序:
- fill(Object[], int, int, Object)
- copyOfRange(T[], int, int)
- copyOfRange(T[], int, int, Class)
如果你的API存在過分重載現象,那么你將不得不面對這些問題。
違反例子2:String
另一個例子是String類:
- regionMatches(int, String, int, int)
- regionMatches(boolean, int, String, int, int)
問題所在:
規則5:建立返回值類型
當涉及到返回值類型時,你應該創建一致的、正規的API,下面提供一套設置規則(你可能會對下面的規則存在異議):
對于上面的1、2條,最好的實踐應該是:
違反例子1:File
File是JDK中的一個類,它違反了許多規則,其中一條就是關于返回值類型。
正確遍歷文件名稱(如果你做的是防御性編程):
?
| 1 2 3 4 5 6 7 8 | String[] files = file.list(); ?? // You should never forget this null check! if (files != null) { ????for(String file : files) { ????????// Do things with your file ????} } |
值得注意的是,文件必須存在根目錄下( File.isDirectory()),而如果程序出錯,則應該拋出IOException異常,而不是返回null。
當返回類型為數組或集合時,千萬不要返回null。
違反例子2:JPA
JPA違反這個規則的方式就是實體如何從EntityManager中取回或者從查詢中獲得的:
- EntityManager.find():如果沒有發現實體,就返回null。
- Query.getSingleResult():如果沒有發現實體,會拋出一個NoResultException異常。
需要注意的是,NoResultException異常為運行時異常,如果你堅持拋出該異常,請確保客戶端代碼必須檢查和處理。
?
轉載于:https://www.cnblogs.com/wala-wo/archive/2013/04/11/5119367.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的设计优秀API的五大规则的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [转]iOS5 ARC学习笔记:stro
- 下一篇: Linux命令操作,文件复制,删除修改等