设计优秀API的五大规则
2013-05-31 13:05
316 查看
设计优秀API的五大规则
摘要:如何设计一款优秀的API已成为许多程序员的奋斗目标,而本文着重介绍了如何设计优秀的Java 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 )
这两个构造函数在不同的操作行为下,返回的值也是不一样的:
为了确保参数顺序的一致性,把数组类型放在第一位会给你带来很多好处:
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)
问题所在:
很难理解明白这两个方法之间的差异,而且可选的布尔参数排在参数列表的最前面。
很难理解每个int参数的作用,在一个方法里有过多参数。
规则5:建立返回值类型
当涉及到返回值类型时,你应该创建一致的、正规的API,下面提供一套设置规则(你可能会对下面的规则存在异议):
当方法返回一个单独的对象,但并没有对象被发现时,应该返回null。
当方法返回多个对象,但并没有对象被发现时,应该返回空List、Set、Map、array等,而不是null。
方法应该抛异常以防万一
对于上面的1、2条,最好的实践应该是:
抛出ObjectNotFoundExceptions当没有对象被发现时
返回null代替empty Lists
违反例子1:File
File是JDK中的一个类,它违反了许多规则,其中一条就是关于返回值类型。
正确遍历文件名称(如果你做的是防御性编程):
当返回类型为数组或集合时,千万不要返回null。
违反例子2:JPA
JPA违反这个规则的方式就是实体如何从EntityManager中取回或者从查询中获得的:
EntityManager.find():如果没有发现实体,就返回null。
Query.getSingleResult():如果没有发现实体,会抛出一个NoResultException异常。
需要注意的是,NoResultException异常为运行时异常,如果你坚持抛出该异常,请确保客户端代码必须检查和处理。
转自:http://www.csdn.net/article/2013-04-10/2814835-how-design-good-regular-api
相关文章推荐
- 设计优秀API的五大规则
- 设计优秀API的五大规则
- 设计优秀API的五大规则
- 设计优秀API的五大规则
- 设计优秀API的五大规则
- 设计API的五大规则
- 如何设计一款优秀的API
- 如何设计一个优秀的API
- REST API的认证机制的设计规则
- 如何设计出优秀的Restful API?
- 逐步改善,设计优秀API
- 优秀REST风格 API的设计原则
- Google首席软件工程师Joshua Bloch谈如何设计一款优秀的API【附PPT】
- 设计出优秀有吸引力API的七大要诀
- 如何设计优秀的API(1)
- 优秀logo设计的42个规则
- Google首席软件工程师Joshua Bloch谈如何设计一款优秀的API
- 5 个关于 API 中日期和时间设计规则
- 逐步改善,设计优秀API
- 如何设计一个优秀的API(转)