写点什么

RAML 的强大功能

  • 2015-08-27
  • 本文字数:5928 字

    阅读完需:约 19 分钟

本系列文章专注于 Web API__ 之 “元语言”的三个关键领域:即 API__ 描述、API__ 发现以及 API__ 档案。这些文章将涵盖所有这三个重要的趋势,并包括对这一快速发展的领域的一些关键人物的专访。

来自 InfoQ__ 的这篇文章是“描述、发现以及档案:进入Web API__ 的下一阶段”系列文章中的一篇,你可以在这里进行订阅,以便通过RSS__ 获取新文章的通知。

RAML 的全称是 RESTful API 建模语言,这是一种基于 YAML 格式的新规范,因此机器与人类都能够轻易地理解其中的内容。但 RAML 的目的不仅仅在于创建更易于理解的规范(你可以将这一工作指派给文档团队,他们会做得更好)而已。RAML 的设计者 Uri Sarid 希望使用者能够打破固有的思维,在开始编写代码之前以一种全新的方式对 API 进行建模。

Roy Fielding 博士在他的博客 Untangled 中指出,现在的人们总有一种倾向,他们只考虑短期的设计,目光只能看到我们所知的、我们目前所想的内容。

REST 风格的发明者 Roy Fielding 表示:“很不幸,人们很善于处理短期的设计,但对于长期的设计通常就束手无策了。”

设计 API 的一大挑战在于,API 通常都会存在较长的一段时间,有可能会存在数年之久。毕竟,API 的设计需要开发者投入大量的精力,但同样对于客户来说也是一种极大的投入,因为客户也依赖于这些 API,需要基于它们进行开发。从 2009 年起,Uri 开始思考如何解决 API 的长期设计的挑战,他希望能够找到一种工具,让设计者只需几行代码就能够对 API 进行建模(或设计),然后快速地生成一个原型,让全球的开发者都能够尝试你的原型并提供反馈。在 2013 年,随着 RAML 0.8 的发布,他的梦想终于变成了现实。

自那时起,人们对于 RAML 的兴趣就在不断地升温。无论是大型企业还是小公司,他们都开始意识到了 RAML 所带来的益处:包括以一种人类可读的格式设计 API、在设计时就看到这些 API 将怎样工作、并且能够为 API 创建一个活动的、全功能的示例,让开发者能够简单地通过点击按键,对这个 API 发起实际的调用。

(点击放大图像)

提示

所有的RAML 工具都是开源的,可以从 http://RAML.org/projects 免费下载。我的雇主 MuleSoft 还提供了这些工具的免费托管版本,你可以从 AnyPoint Platform for APIs 平台试用这些工具。

API 契约的设计周期

但是,仅仅简单地创建一个原型是不够的。MuleSoft 创建了一种 API 契约设计周期图,这一设计的前提在于 API 不仅仅是机器之间的一种契约,同样也是提供商与用户之间的一种契约。

这也意味着,在设计与创建原型之后,开发 API 的公司需要找到一种方式以共享他们的 API,并从使用者那里获取反馈。这些有价值的反馈能够让公司找到设计中的缺陷,例如数据或结构中的不一致性,以及 API 中的一些令人困惑之处。在这一阶段及时发现设计中的问题非常关键,因为一旦你的 API 发布之后需要修改,那么在大多数情况下都会破坏向后兼容性,而这将影响 API 的使用。

提示

这一周期同样也是规范驱动开发(Spec Driven Development)过程的基础。

API Console 与 API Notebook

为了实现这一设计周期,又出现了两种工具:即 API Console 与 API Notebook。API Console 与其它 API 控制台的作用很相似,例如 Mashery 的 IO Docs Swagger ,它提供了一个可进行文档工作的交互式环境,让开发者输入数据和发起调用请求。这意味着开发者在设计 API 原型的同时,也能够快速地看到可用的资源与方法,并且立即进行测试,以获得第一时间的验证结果。同时,一旦你的 API 发布之后,除了静态文档之外,你也能够发布交互式的文档,让开发者在一个相当简单的界面中试用这些 API,并对 API 调用进行调试。

另一方面, API Notebook 的交互性与探索性更进一步,它能够让开发者使用 JavaScript 去调用你的(以及其他人的)API。在 API Notebook 中还能够对数据进行各种操作,通过实际应用中的用例观察它的运作。也就是说,开发者能够通过用例测试他们的原型,所需的只是编写几行 JavaScript 而已。

举例来说,在下面这张截图中,用户能够连接到 Instagram 的 API ,通过 OAuth 进行验证,并尝试搜索带有“kitten”这个标签的图片,一步一步完成设计过程。

(点击放大图像)

但作为一个RAML 工具,API Notebook 真正强大的地方在于你可以为API 的使用者创建用例,让他们自己进行走察。此外,你所创建的用例场景可以用于原型的设计以及发布于生产环境的API,并且你的调用者也能够通过markdown 语法创建自己的Notebook。这样一来,你的使用者就能够共享bug 与用例的信息,以获得更好的反馈与支持,并且无需共享任何私有的代码,也无需走查整个应用程序。

这个特性很简单,但它却让你的使用者不必将大量的精力用于寻找问题的根源,同时也让你的支持团队能够快速地重现这些错误,而无需猜测这些问题是否是由客户端代码所引起的。

等到你收集了这些反馈之后,就能够对你的设计进行调整,并决定该设计是否已经可以在生产环境中应用了。它的另一个益处在于,当你的API 已经准备好上线时,你就能够在生产环境中使用这两个优秀的工具了,正如上文所说的那样。

为了帮助你的API 顺利上线,可以在社区中找到许多其它实用的工具,包括用于生成API 的相应代码以及对API 进行测试的工具,例如 Abao 。除了 API Console 与 the API Notebook 之外,还有大量的工具能够帮助你进行文档化工作,包括 RAML to HTML ,它能够生成一个单一的 HTML 文件(与 API console 相类似)作为文档。以及使用PHP 的RAML2HTML 工具,这个脚本能够创建一个完整的、多页面的文档网站:

(点击放大图像)

这个脚本可以进行充分的自定义,可以修改全局的模板甚至是内容块,以满足你对于文档的需求。

此外,还有许多工具能够对RAML 进行解析,可以将你的API 规范整合到你的自定义应用中,而不关心你的应用是用Ruby、PHP、JavaScript、.NET、Python 还是Java 编写的。

人类可读

由于RAML 被设计为一种人类可读的格式,因此通过它开始设计一个全新的API 或定义一个现有的API 都非常简单。虽然你可以在任意一种编辑器中创建RAML,但最方便的方式还是使用在线的API 设计器,或是专门为 Sublime Visual Studio 等 IDE 所设计的插件(两者都可以在 RAML.org/projects 中找到),你可以在设计过程中充分利用它们的工具提示、自动完成以及实时校验功能,这使得整个过程更加简便。

开始设计时,首先创建一个包含以下内容的 RAML 文件:

复制代码
#%RAML 0.8
title: This is My API
baseUri: http://api.domain.com
version: 1

在以上代码中,我们首先声明这是一个 RAML 规范,它对应 RAML 0.8(版本 1 很快就会发布了),并声明 API 的标题、基本 URI、以及这个 API 的版本号(这个示例中的 API 是版本 1)。

在 RAML 中声明资源非常简单,只需使用 /resourceName 格式。而添加方法也同样便捷,只需引用相应的 HTTP 谓词即可:

复制代码
#%RAML 0.8
title: This is My API
baseUri: http://api.domain.com
version: 1
/resource1:
get:
description: This gets the collection of resource1
post:
description: This adds a new item to the collection

RAML 让你能够定义多种相应,返回不同的状态码、头信息以及响应体。例如:

复制代码
#%RAML 0.8
title: This is My API
baseUri: http://api.domain.com
version: 1
/resource1:
get:
responses:
200:
headers:
cache-control:
example: |
public, no-cache, no-store
{1}
body:
application/json:
example: |
{"name":"Michael Stowe"}
{1} application/xml:
example: |
<name>Michael Stowe</name>
{1} 400:
#...
401:
#...

RAML 本身还有大量的其它特性,让你通过 schema 与参数定义完整的 API。它还允许你使用资源嵌套(与 Saas 中进行 CSS 嵌套的方法相近)、文件引用(可以引用多个文件,以保持规范的易读性和易组织性),甚至是变量或属性的设置,从而在整个规范中保持一致性。

举例来说,你可以在规范中按以下方式利用这些特性:

复制代码
#%RAML 0.8
title: This is My API
baseUri: http://api.domain.com
version: 1
/resource1:
get:
responses:
200:
body:
application/json:
schema: |
{
"type": "object",
"$schema": "http://json-schema.org/draft-03/schema",
"id": "http://jsonschema.net",
"required": true,
"properties": {
"firstName": {
"type": "string",
"required": true
},
"lastName": {
"type": "string",
"required": true,
"minLength": 3,
"maxLength": 36
}
}
}
/sub-resource:
get:
queryParameters:
firstName:
description: "the user’s first name"
example: John
required: true
type: string

对开发者十分友好

RAML 的优点不仅在于简单的格式与丰富的工具,它还能够让开发者应用编码的最佳实践,例如模式与重用代码。这不仅能够极大地减少开发者的工作,还能够促使 API 在不同的资源与方法中保持统一性。虽然你总是能够抽象出一套 schema,以保持规范的良好组织,或是通过“!include”命令引入 schema、示例与其它 RAML 代码片段,但 RAML 还提供了两个额外的实用与独特的模板特性:即 traits 与 resourceTypes。

通过 traits 定义通用属性

RAML 的 traits 特性允许你为方法(GET、PUT、POST、PATCH、DELETE 等等)定义通用的属性(或 traits),例如它们是否可过滤、可搜索或是可分页。

在创建 trait 时,你实际上是创建了一份模板,它能够通过接受参数为方法提供属性,只需几行代码就能够完成。同时为你所需的 trait 提供了最大程度的灵活性与自定义能力:

复制代码
traits:
-searchable:
queryParameters:
query:
description: |
JSON array [{"field1","value1","operator1"},…] <<description>
example: |
<<example>>
/people:
get:
is: [searchable: {description: "search by location name", example: "[\"firstName\"\,\"Michael\",\"like\"]"}]

通过 ResourceTypes 为资源定义模板

此外,与 traits 相似,resourceTypes 也允许你为资源本身创建模板,以此调用通用的方法与响应。打个比方,对于 Collection 这种资源类型来说,你可能会大量用到 POST 与 GET 方法,并且通常会返回 200、201 或 400 等状态码。只要将它定义为一种 resourceType,你就能够通过两行代码就完成调用,而无需为你所创建的每种资源都加入相同的方法与状态码。

复制代码
resourceTypes:
- collection:
description: Collection of available <<resourcePathName>>
get:
description: Get a list of <<resourcePathName>>.
responses:
200:
body:
application/json:
example: |
<<responseVariable>>
400:
#...
401:
#...
/people:
type:
collection:
responseVariable: |
{
"name" : "Michael Stowe",
"company" : "MuleSoft",
}

你甚至可以在 resourceTypes 中定义可选的方法,只需为该方法加上一个问号(?)即可。这种可选方法只有在定义了该方法的资源中才会被引入,这就为你赋予了更大的灵活性。

提示

RAML 允许你创建任意数目的 resourceTypes 和 traits。不过,如果你发现你所定义的 resourceTypes 超过两种(collection 与 item),那么你可能要评估一下你的 API,以确保对这些 resourceTypes 的使用方式是一致的。你可以在 RAML 200 教程中了解到更多的知识。

自动生成 SDK

RAML 还可以通过其它工具为开发者节省宝贵的时间与资源,比方说可以通过 APImatic.io 等提供者为用户提供自动生成多种语言的 SDK 的能力。使用 APImatic.io 无需手动编写这些 SDK,也不必依赖于社区保持它们的更新,它可以让你简单的导入 RAML 规范,随后生成面向 Java、Python、PHP、Ruby、AngularJS、iOS 和 Windows 等平台和语言的 SDK。

超越代码

RAML 正逐渐成为 API 规范方面的领头人之一,与 Swagger 和 API Blueprint 并驾齐驱。现如今已有越来越多的 API 方案提供者支持这一格式了(包括管理与工具等方面)。

为了加快发展的脚步,同时确保规范的完整性,在 RAML 于 2013 年问世的同时,一个由 API 领域驱动的工作小组也一并成立了。该工作小组将负责指正 RAML 的发展方向,确保它将继续遵循最佳实践,并符合业界的需求。目前,该工作小组由来自 MuleSoft、AngularJS、Intuit、Airware、PayPal、API Science、Akana 和 Cisco 的代表所组成。

RAML 的出现不过一年多的时间,目前 1.0 版本的工作还在进行之中,新版本的目标是提供更多的功能,并且更好地满足业界的需求,同时推进 API 的最佳实践。当然,它也面临着一些挑战,包括如何定义与描述超媒体,这一点在所有的主要规范中都被提及。

如何为克服这些挑战作出贡献

开源社区的优点就体现在这里,新的点子总是能够找到立足之处。每个有志之士都可以通过访问 RAML.org 加入这一项目,并且在 GitHub 上贡献独创的工具,或是创建规范的分支。毕竟,RAML 的强大之处不仅仅在于目前它所实现的部分,即通过一个单一数据源,通过可视化的方式进行 API 的设计、创建原型、构建、共享以及进行文档化,而在于它将如何对未来产生持续性的影响。

关于作者

Michael Stowe是一位RAML**** 的忠实支持者,他在创建应用方面已有超过 10 年的经验,所涉及的领域包括法规实施、非盈利项目、工业,并且加入了多个开源项目。他目前在 MuleSoft 担任开发者管理经理,作为工作的一部分,他经常在各种技术型会议上进行 RAML 以及 API 设计方面的演讲,包括 API Con、API Strategy and Design 以及 API World 等等。由 Michael 所编著的一本关于 REST API 设计的书籍即将面世。你可以通过 @mikegstowe 关注他的 Twitter,了解他的最新帖子。你也可以通过 http://www.mikestowe.com 观看他所做的演讲,并了解他的技术思想。

本系列文章专注于 Web API__ 之 “元语言”的三个关键领域:即 API__ 描述、API__ 发现以及 API__ 档案。这些文章将涵盖所有这三个重要的趋势,并包括对这一快速发展的领域的一些关键人物的专访。

来自 InfoQ__ 的这篇文章是“描述、发现以及档案:进入Web API__ 的下一阶段”系列文章中的一篇,你可以在这里进行订阅,以便通过RSS__ 获取新文章的通知。

查看英文原文: The Power of RAML

2015-08-27 05:4617117
用户头像

发布了 428 篇内容, 共 175.3 次阅读, 收获喜欢 38 次。

关注

评论 1 条评论

发布
用户头像
能不能做个列表,把同系列文章的链接都放上来,方便系统性的阅读?
2021-12-02 18:36
回复
没有更多了
发现更多内容

设计模式之——JDK动态代理的源码分析

诸葛小猿

动态代理 cglib 代理模式 Proxy

ARTS Week11

时之虫

ARTS 打卡计划

关于 Bash 的 10 个常见误解

柴锋

bash Linux DevOps Shell

那些不可貌相的代码规范

废材姑娘

代码质量

十年一梦,小米的原罪得到救赎了吗?

脑极体

ARTS打卡 第11周

引花眠

ARTS 打卡计划

Requests模块基本操作

有梦想的tester

深化区块链技术的应用 体现其价值产业发展良机

CECBC

区块链技术 数字经济

微服务、DDD

chenzt

吃灰的旧显示器别扔!

小匚

学习 随笔杂谈

Java 常见的几种 OOM

hepingfly

Java OOM

面试这么撩准拿offer,HashMap深度学习,扰动函数、负载因子、扩容拆分,原理和实践验证,让懂了就是真的懂!

小傅哥

Java 面试 hashmap 负载因子 扰动函数

如何理解Java8 的函数式编程

Rayjun

Java 函数式编程

第十章作业

武鹏

BGP、OSPF、MPLS路由协议RFC分享

Phantasm

Suricata-流的处理

Phantasm

网络安全 suricata flow

应用开发基础之-并发编程

superman

ARTS 打卡(20.07.20-20.07.26)

小王同学

十多位全球技术专家,为你献上近十个小时的.Net微服务介绍

newbe36524

容器 微服务 .net core netcore

数据库的乐观锁和悲观锁并非真实的锁

架构师修行之路

数据库 架构 乐观锁 悲观锁 分布式锁

如何让区块链技术能够更好赋能数字社会建设

CECBC

区块链 数字经济

当实证资产定价遇上机器学习

分析101

人工智能 学习 金融科技 金融 资产定价

程序的机器级表示-控制

引花眠

计算机基础

视读——沟通的艺术,看入人里,看出人外(第二章)

废材姑娘

读书笔记 视觉笔记

图文讲解 AQS ,一起看看 AQS 的源码……(图文较长)

程序员小航

AQS jdk源码 源码阅读 java 并发

ARTS打卡Week 10

teoking

热潮-区块链的价值能够体现在哪些方面?

CECBC

区块链技术 标准化 应用价值

ARTS-WEEK10

一周思进

ARTS 打卡计划

LeetCode题解:21. 合并两个有序链表,利用数组排序,JavaScript,详细注释

Lee Chen

大前端 LeetCode

LeetCode题解:21. 合并两个有序链表,迭代,JavaScript,详细注释

Lee Chen

大前端 LeetCode

求刚好大于当前数组组合,Code Review最佳实践,JVM框架原理,JVM垃圾回收原理 John 易筋 ARTS 打卡 Week 12

John(易筋)

Code Review ARTS 打卡计划 JVM虚拟机原理 JVM垃圾回收原理 Array算法

RAML的强大功能_语言 & 开发_Michael Stowe_InfoQ精选文章