要想设计出可以正常运行的Web API,对基于web的应用的基本理解是一个良好的基础。但如果你的目标是创建出优秀的API,那么仅凭这一点还远远不够。设计优秀的API是一个艰难的过程,如果它恰巧是你当前的工作任务,那么你很可能会感到手足无措。 不过,优秀的设计绝对是可以实现的。本文所描述的流程将帮助你获得成功,我们将共同研究什么是优秀的设计,以及迭代式的流程如何帮助我们实现这一目标。我们还将叙述设计的三个重要阶段:草图设计、原型设计以及实现,同时还将介绍一些能够让你的工作变得更轻松的工具。 [TOC] ## 优秀的API设计来自于迭代过程 在开始设计API之前,我们必须理解它的目的。在你手动设计之前,你应当了解为什么要设计这个API,如果在这方面[需要](https://medium.com/@medjawii/5-ways-an-api-is-more-than-an-api-bddcdb0517ca)[帮助](http://101.apievangelist.com/),有[许多](http://www.slideshare.net/jmusser/j-musser-apibizmodels2013)[现成](http://www.infoq.com/articles/web-apis-business-perspective)[的资料](http://www.fabernovel.com/work/6-reasons-why-apis-are-reshaping-your-business/)可以参考。不过,定义你的动机仅仅是第一步,真正的诀窍在于直到实现为止,始终保持进行正确的设计决策。 成功的API设计意味着要设计出一种接口,让它的使用方式符合它的目的。作为API设计者来说,我们所做的每个决策都会影响到产品的成败。设计过程中需要做出一些重大的决策,例如API所使用的传输协议、或它所支持的消息格式。但除此之外,还有许多相关的次要决定,例如接口的控制、名称、关联以及次序。而当你将所有的决策集中在一起时,它们将带动API的使用模式。如果你能够做到每个决定都是正确的,那么这种模式将对API产生完美的支持与促进作用。 如果你要做出一个正确的设计决策,很可能会先做出一个错误的决策,并从中吸取经验教训。实际上,你很可能会在多次犯错之后才能够接近正确的决策。这也正是迭代的关键所在,因为没有人能够做到一次成功,但只要有足够的机会,你就能够做到接近完美。 通过迭代方式进行API设计,这一点说起来容易,但在实际应用中做到这一点并不简单。我们所面临的一个常见的挑战在于,在某个API发布之后再进行变更是非常困难的。事实上,对一个使用中的API进行变更的代价很大,并且伴随着很大的风险。或者借用Joshua Bloch的说法:“[公开的API就像钻石,它是永恒不变的。](http://www.infoq.com/articles/API-Design-Joshua-Bloch)” 处理这一问题的一种方式是在每次变更时不要破坏现有的接口,这是一种好习惯,也是优秀API设计的一个主要原则。但有些时候,破坏性的变更是不可避免的,而基本层面的设计变更尤其具有侵略性。 换种思路,我们应当在接口发布之前就做好这些变更。在理想的情况下,在变更的代价变得高昂之前,就应该消除易用性与设计方面的问题。当时,只有在首次发布之前做到尽早开始迭代,并保持频繁的迭代,才能够找到并修复这些问题。 ## 迭代式的设计过程 在每一次迭代中,我们都得到了一次对设计候选按其使用情况进行评估的机会。举例来说,开发者是否能够通过使用我们创建的产品实现他的工作目标?这个接口真的能够实现吗?如果我们要求他人使用这个API,他们又会有什么样的感受? 通过设计与实现多个接口而不发布它们,应该能够实现最佳的API设计。通过对每个接口进行审查与测试,我们将对于如何改进最终产品具有良好的洞察力。 但是在实践中,这种壮观的迭代式设计是不可能实现的。没有几个人能有足够的时间、金钱或耐心去不断地设计与实现一个个可以运行的API。对于任何具有一定复杂度的接口来说,这种方式的迭代式设计会占用你过多的时间。 一个更合理的方式是在设计过程的早期就进行迭代,这些早期的设计应当具有足够的细节,可展现改进的最佳时机,但又无需过度设计而导致实现的困难。随着时间的推移,我们可以逐步地增加细节度(或保真度),并最终得到一个完整的实现。 这种逐步推进的设计过程在设计界已经非常流行了,它通常被分解为三个重要的阶段: 1. 草图设计 2. 原型设计 3. 实现 ### 草图设计的强大作用 草图设计是设计方面的一种普遍行为。著名建筑师[Frank Gehry](http://en.wikipedia.org/wiki/Frank_Gehry)的草图可谓天下闻名,以至于诞生了一部专门描述这些草图的[电影](http://www.pbs.org/wnet/americanmasters/episodes/frank-gehry/sketches-of-frank-gehry/602/)。他的许多建筑项目都是从在一叠纸上所画的一系列草图开始的。Gehry总会画上几百张这样的草图,每一次都向良好的设计更靠近一步。 交互设计师[Bill Verplank](http://en.wikipedia.org/wiki/Bill_Verplank)将草图设计描述为[设计过程中必不可少的第一步](http://www.billverplank.com/IxDSketchBook.pdf)。[Bill Buxton](http://en.wikipedia.org/wiki/Bill_Buxton)还专门写了一整本书,用以介绍草图设计方法对用户体验设计的价值,并认为它的关键特征在于它的可弃性、而且在所有探索方式中是成本最低的一种。 将草图设计过程包含在API设计过程的早期阶段,让我们有机会体验接口的概念模型。这不仅是一次定义我们脑中已有的想法的好机会,也让我们有机会探索新的道路,并且提出“如果……会怎么样?”这样的问题,并逐步走向真正的创新。 优秀的草图应当是易于创建、并且可以任意丢弃的。如果创建这些草图花费了许多时间、或是难度太高,那么你就难以丢弃它们。这种可弃性非常重要,它让我们有机会承受住风险。 我们可以通过草图设计尝试不同类型的接口风格,并捉住那些在我们脑海中时而闪现的抽象概念。一旦这些思想具体化,我们就能够对它们进行审查及讨论。在过程中决定我们喜欢或是不喜欢某个特定的概念,然后在消化了这些知识后再次启动这一过程,并绘制新的草图。 对于设计团队之外的用户来说,他们很少会对草图进行评估。不仅是因为过早地对假设进行验证是没有价值的,并且在实际的项目中能够进行的用户测试次数是有限的。通过真实的用户对每种草图都进行测试的设想代价过高,而这种方式的收获是非常有限的。 ### 使用档案进行草图设计 在进行API的草图设计时,使用[档案](http://tools.ietf.org/html/draft-amundsen-richardson-foster-alps-01)(profile)或[元语言](http://dublincore.org/documents/profile-guidelines/#sect-6)(meta language)是一种非常实用的方式。档案提供了一系列的概念,可用于草图的设计。一个优秀的档案可以类比为框与线,通过它创建系统图的多种草图。这些元素是设计师与评估者都能够理解的内容,它让快速地开发草图变得更简单。 ![](https://box.kancloud.cn/2015-09-12_55f4340e12949.png) 实际上,着手进行API草图设计过程有一种好方法,就是定义接口中最明显的单词列表。有哪些单词是用户必须知道的?哪些单词能够最好地表达你的目标受众的目的与任务?通过回答这些问题,并创建一份接口的词汇表,将有助于你形成对该接口的一种早期草图。 档案的美妙之处在于,它为我们提供了一种正规化的方式以共享及重用这种类型的信息。举例来说,我们在开始设计时可能会从某个[XML结构](http://www.w3.org/XML/Schema)文档中提取出单词、从[schema.org](http://schema.org/)获取一份词汇表、或者从某个[ALPS](http://tools.ietf.org/html/draft-amundsen-richardson-foster-alps-01)或[RDF](http://www.w3.org/RDF/)文档获取信息,这取决于我们的需求。 设计阶段的目标并非创建一份全面的词汇表,恰恰相反,早期的词汇表只是一个起点,我们可以从这一点开始绘制出其它类型的细节。我们可能会发现一个由20个左右的单词组成的列表就能够捕获接口的本质,这个列表就可以作为我们的起点。 这份词汇表为我们提供了一个基础,我们可以从它出发为API中的资源与关联设计草图,内容可以包括URI、资源名称、资源间的关联、链接文本以及其它结构化以及导航元素。请再次注意,没有必要画出草图的所有细节,我们的目标是表达出API里最重要的部分。 最重要的一点在于,最初的草图无需过于深入。比方说,请尽量避免在这一阶段就深入到错误流的建模,或响应消息元素的设计。这些部分可以稍后再加入,或者可以为它们进行专门的草图设计。 一份单独的草图无需反映出整个接口,实际上,为某些细节部分专门设计草图的方式可能更实用。举例来说,我们可以设计一个基本错误流的草图,它与整个API都具有相关性,或是设计一种响应消息格式的草图,这种格式可以应用到所有响应中。之后,在原型设计阶段,我们可以将这些思想应用到某个工作模型中。 ### 原型设计 在原型设计阶段,我们将有机会为接口设计一个具有更高保真度的模型,并且对草图设计阶段产生的一些假设进行验证。一个优秀的API原型应当是可以调用的,它应当能够处理真实的请求消息,并在必要时提供响应。开发者甚至应该能够通过使用这个原型API,创建出一个简单的应用。 不过,创建原型的成本应当低于一个完整的实现。有一种方法可以保持较低的成本,即模拟响应的消息,而不是由后台系统输出真实的响应消息。这种方式有时也称为接口的虚构(mocking),它是一种建立快速原型的好方法。 无论使用哪种方法建立原型,要点在于为投入找到一个合适的范围,能够支持后续的迭代。我们应当能够基于草图创建出两至三个不同的原形,并在过程中持续地学习。根据我们在原型设计阶段所学的内容,我们甚至可能会返回草图设计阶段,并尝试全新的方向。 通过原型,你的团队将有机会获得对于设计的早期用户反馈,并且能够对真实的使用情况进行观察。如果该接口的保真度已经达到了一定程度,你就可以让潜在的用户创建应用,并且对他们在实现阶段所面临的挑战进行观察。 负责实现的成员也应当加入原形评估过程中。一个经过良好设计的API不仅应当易于使用,同时还是可持续的、可靠的、高性能的、并且是历时长久的。虽然接口本身不应暴露数据模型的内部细节与服务器的架构,但负责实现者为告诉设计团队所做的决定提供一些参考建议,例如运行环境的限制,以及实现的成本。 设计周期好比一个科学工艺流程,而你应当抓住原型阶段的这次机会,在提出变更还为时未晚时对所做的假设进行验证。 ### 实现 实现者的任务是将一个原型化的接口转变成一种可以放心地进行实际应用的产品。交付一个安全的、可靠的、以及可伸缩的实现是一个很大的挑战,这一过程本身也需要经历一种专门的设计流程。 最后的原型以及支持性的草图描述了接口应该表现出的样子,它们反映出了所有的设计决策,并形成了一份规格,说明了具体需要创建什么样的产品。实际上,可以使用一种正式的接口描述语言(或称[IDL](http://en.wikipedia.org/wiki/Interface_description_language)),从原型阶段自然地过渡到实现阶段。 举例来说,如果你对原型API感到满意,就可以选择以一种[API Blueprint](https://apiblueprint.org/)文档(或[Swagger](http://swagger.io/)、[RAML](http://raml.org/)、[WADL](http://www.w3.org/Submission/wadl/),又或者是其它任何一种最适合你工作环境的格式)对其进行描述。 虽然这一阶段的目标是实现,但也不应停下设计的脚步。这一阶段是一个良机,让你通过真实的使用数据对整个设计过程中所做的假设进行进一步的验证。就像原型化的API允许我们观察使用情况一样,实现后的API允许我们在一个宏观层面对使用情况进行分析。 打个比方,你或许想对你之前所做的设计假设进行验证。应用程序的开发者是否真的在使用你为他们所创建的便利的操作?你是否吸引到你所期望的用户类型?新的用户是否在使用接口中的某些部分时遇到了麻烦? 经过分析,你可能会重新开始一次草图设计过程,以准备经过进一步改进的接口。 ## 通过工具实现过程的自动化 工具与技术的使用会极大地改进整个设计过程。那些能够降低草图与原型创建成本的工具能够让设计团队在更短的时间内创建更多的细节,使设计的决策得到改进。 对于多数设计过程来说,工具与自动化的引入是一个重要的部分。在建筑设计的世界中,[SHoP](http://www.shoparc.com/)(一个位于纽约的建筑师事务所)就通过创新、合作与基于工具的设计获得了成功。他们的流程中就引入了原型工具,让设计师能够体现出所用材料的物理特性。这种方法让他们得以创建数以千计的设计迭代,在每次迭代中都能够体现出易于评估的实现细节。 在API设计的世界中,这种基于工具的优化有很好的表现机会。实际上,在服务描述领域中,已经出现了一些卓越的Web API设计工具。 接口描述语言也能够提供支持性的工具,以简化编写描述的任务,这一点现在已经很常见了。这些编辑器工具能够缩短基于IDL的设计的创建时间,因此在更短的时间内创建更多的描述也变得更容易了。Swagger、RAML与Blueprint都提供了优秀的编辑工具以支持各自的语言。即使像WADL这样仅作为规范发布的IDL,也能够从[SoapUI](http://www.soapui.org/rest-testing/working-with-rest-services.html)这样的工具中受益。 [Apiary](https://apiary.io/)为Blueprint语言所提供的编辑器有很强的竞争力,因为它提供了一套完整的工作流工具以支持设计过程。只要以Blueprint编写一个简单的API描述,设计师就能够对文档进行评估、调用原型,甚至对调用过程进行分析。 **(****单击图片以放大****)** [![](https://box.kancloud.cn/2015-09-12_55f43412e484b.png)](https://box.kancloud.cn/2015-09-12_55f43412e484b.png) 不过,这些现有的工具中的大部分都只限于其所支持的描述语言。设计者必须理解IDL的语法,并且用这种语言设计界面。虽然这种设计风格能够吸引熟悉编程语言的使用者,但也会限制在早期的草图设计阶段很有价值的抽象与实验性的思考方式。 由于IDL及其对应工具的这些特征,它们很适用于原型设计过程,但对于草图设计的早期实验性活动来说实用性不高。 ## 使用可视化工具进行草图设计 人们对于使用可视化工具帮助他们进行API设计的兴趣正在不断升温。这些工具并非直接支持编辑IDL的行为,而是让设计者能够随意摆弄接口的一个可视化展现。 可视的建模工具提供了一种接口描述语言,这种语言多数是关于绘画的,或是基于图形的。虽然这个视角限制了接口展现的准确度,但它也让设计者能够在一个较高层次看到这个接口的全貌。这一点带来了进行改进的机会,而这种机会在手写的形式中往往并不明显。 易于使用的可视化编辑器也是进行自动化草图设计的良好选择,它综合了低保真度、抽象的展现以及可弃性等特征,这正是我们所需的。 我参与开发了一个名为[Rápido!](http://rapidodesigner.com/)的可视化建模工具,用于辅助API的草图设计。Rápido将用户限制在一个低保真度的细节中,这一点并非它的副作用,而是本身就是如此设计的。用户可以使用它进行档案、导航元素以及响应数据的建模,但不能用于设计逻辑流程或动态的响应。 当设计者开始创建一个新的Rápido项目时,他们需要为API设计一个词汇表。在得到一个初始的单词列表(或者从外部导入一个ALPS词汇表)之后,设计师就可以在一个超媒体画布中开始为API设计概念模型、创建资源、尝试URI名称甚至是链接的状态。 ![](https://box.kancloud.cn/2015-09-12_55f4341943fa7.png) 最终,设计者可以为草图中的每个资源或状态实现静态的响应消息,以增加保真度。最后,当草图设计阶段结束后,可以将整个设计导出成IDL格式,准备在原型阶段导入高保真度的工具。 ![](https://box.kancloud.cn/2015-09-12_55f4341a4919f.png) Rápido的目标是在Web API设计的领域中提供一种快速绘制的“鸡尾酒餐巾”式的草图的体验。如果你选择了适当的保真度,并且没有施加过于强烈的限制,那么它就能够成为API设计工具链中的重要一环。 ## 在迭代过程中取得成功 如果你按照本文中所描述的方式进行迭代式风格的设计,那么你将为团队带来一个设计高效API的良机。在过程的一开始创建多个低保真度的设计并进行评估,以培育实验能力与构思能力。然后创建高保真度的原型以及虚拟的实现,以评估早期的设计思想。最后,为真实用户实现整个设计,并获取数据以分析实际应用中的使用情况。 迭代式设计过程的特定细节取决于你的环境与项目,需要多少细节、多少次迭代、以及需要哪些评估技术,这些问题将留给设计者进行回答。但作为一种通用的经验法则,随着你的设计过程的推移,迭代的数量应当逐步减少,而在评估方面需要投入更多的精力。 ![](https://box.kancloud.cn/2015-09-12_55f4341c5594e.png) 优秀的API设计过程为你提供了一个创建最佳的接口的机会。但创建优秀API的秘密并不在于专家的指导或什么神秘的知识,而是一种通过优秀的工具、语言以及档案所优化的迭代流程的应用而实现的。使用这个公式所交付的API定能帮助你的组织获得成功。 ## 关于作者 ![](https://box.kancloud.cn/2015-09-12_55f4341d43833.png) **Ronnie Mitra**是CA Technologies公司的API Academy部门的API设计总监。他多次帮助遍布全球的组织成功地完成了API的设计与实现。Ronnie具有超过30年的行业经验,在此期间内他不断地在失败中进行学习。 **查看英文原文:**[From Doodles to Delivery: An API Design Process](http://www.infoq.com/articles/doodles-to-delivery)