API设计中的功能结构

MLi*_*ter 7 api rest web-services api-design

通过"功能结构化",我的意思是我们如何组织和协调不同的API端点,以便为客户提供所需的功能.这里的上下文是用于具有GPS跟踪的移动电话消费的web API,并且我假设大多数功能都需要蜂窝或WiFi连接.

我个人更喜欢更"模块化"的方法,其中每个端点主要完成一件事,并且它们的集合满足所有要求.当然,您可能需要组合这些端点的一些子集或序列以实现某些功能.总的来说,我尝试在计算和功能方面最小化端点之间的重叠.

另一方面,我知道其他一些人更喜欢客户端方便(或简单)而不是模块化,方法如下:

  1. 如果客户需要实现一个功能性,那么就应该存在一个单个 API端点这正是如此,使得客户端只需要一个单一的请求履行与请求之间具有最小的缓存/逻辑的功能.

  2. 对于GET端点,如果某些功能涉及多个级别/种类的数据,则他们更喜欢单个端点返回的尽可能多的数据(通常是所有必需的数据).具有讽刺意味的是,他们可能还需要一个专用端点,用于使用相应的"最高级别"ID检索"最低级别"数据.例如,If A对应于Bs 的集合,并且每个B对应于Cs 的集合,那么他们将更喜欢直接端点,该端点检索C给定的所有相关的s A.

  3. 在某些极端情况下,他们将要求具有模糊命名的单个端点(例如/ api/data),其基于查询字符串参数的不同组合返回来自不同底层DB表(换句话说,不同资源)的相关数据.

据我所知,人们更喜欢上述便利,目的是:1.减少履行功能所需的API请求数量; 2.最小化客户端的数据缓存和数据逻辑,以降低客户端的复杂性,这可以说是一个"简单"的客户端,简化了与服务器的交互.

但是,我也想知道从长远来看,这样做的成本是否在其他方面是不合理的,特别是在服务器端API的性能和维护方面.因此我的问题:

  1. 构建API功能的经过验证的指南是什么?

  2. 我们如何确定在移动应用中实现功能所需的最佳请求数量?当然,如果所有其他条件相同,单个请求是最好的,但实现这样的单一请求实现通常会在其他方面带来惩罚.

  3. 鉴于客户端请求的数量与服务器端API的性能和可维护性之间存在争议,为实现合理的设计,有哪些方法可以实现平衡?

bus*_*sse 13

您要问的是至少涉及API设计的三个主要方面:

  1. 本体设计(组织)
  2. 请求/响应设计(复杂性/性能)
  3. 维护注意事项

根据我的经验(主要来自与API生产和消费方面的大型组织合作以及与数百名开发人员讨论该主题),让我们看看每个领域,解决您提出的具体问题......

本体设计

在您的设计中需要考虑几件事情,当您说:

总的来说,我尝试在计算和功能方面最小化端点之间的重叠.

这种方法使API易于发现.如果您正在发布API供其他开发人员使用而您可能知道或可能不知道(并且可能有或没有足够的资源来真正支持),这种模块化 - 使他们易于查找和了解 - 创建一种不同的"便利",使您更容易采用和重用API.

我知道其他一些人更喜欢方便而不是模块化:1.如果客户需要一个功能,那么API中应该存在一个完全相同的端点......

对于这种方法,最令人想到的公共示例可能是Google Analytics核心报告API.它们实现了一系列查询字符串参数来构建一个返回所请求数据的调用,例如:

https://www.googleapis.com/analytics/v3/data/ga
?ids=ga:12134
&dimensions=ga:browser
&metrics=ga:pageviews
&filters=ga:browser%3D~%5EFirefox
&start-date=2007-01-01
&end-date=2007-12-31
Run Code Online (Sandbox Code Playgroud)

在该示例中,我们12134通过浏览器查询Google Analytics帐户的网页浏览量,其中broswer是指定日期范围内的Firefox.

鉴于其公开的指标,维度,过滤器和细分的数量,他们有一个名为Dimensions&Metrics Explorer的工具,可帮助开发人员了解如何使用API​​.

一种方法从一开始就使API可被发现并且更容易理解.另一个需要更多的支持工作来解释消费API的复杂性.使用上述Google API并不是显而易见的一件事是某些细分和指标不兼容,因此如果您通过一个键/值对进行调用,则可能无法再通过某些其他对.

请求/响应设计

这里的上下文是用于移动应用程序的API.

这仍然非常广泛,更好地定义(如果可能)您打算如何使用"移动应用程序"可以帮助您设计API.

  1. 你打算让他们完全离线使用吗?如果是这样,则可能需要繁重/完整的数据缓存.

  2. 您是否打算将它们用于低带宽和/或高延迟/错误率连接方案?如果是这样,可能需要繁重/完整的数据缓存,但小/离散数据请求也是如此.

对于GET端点,他们通常更喜欢单个端点返回的尽可能多的数据,尤其是涉及多个级别/层数据时

如果您知道自己只能处于良好的移动连接方案中,或者您可以在需要时大量缓存数据(从而脱机访问或者事情不稳定),这是安全的.

我理解人们更喜欢方便,目的是减少实现功能所需的API调用次数......

找到快乐中间立场的一种方法是在数据密集型调用中实现分页.例如,可以在GET中传递查询字符串,指定"pagesize".因此,可以在100次连续呼叫中一次返回100个记录100个,或者在10个呼叫中一次返回1,000个记录.

使用这种方法,您可以设计和发布API,而无需了解您的开发人员需要什么.尽管上面的分页示例使用前面引用的Google API,但它仍然可以在更加语义设计的API中使用.例如,假设您GET /customer/phonecalls仍然可以将其设计为接受pagesize值并进行连续调用以获取所有phonecalls关联的值customer.

保养

我还想知道这样做的成本[减少实现功能和最小化数据缓存所需的API调用的数量]从长远来看是不合理的,特别是对于API的性能和维护.

这里的关键指导原则是,如果您的API集合将发展到任何显着的复杂性和规模,那么关注点就会分离.

如果将所有内容捆绑在一起构成一个大型服务并且其中的一小部分发生变化,会发生什么?您现在不仅要创建一个维护问题,还要为您的API使用者创建.

这种"突破性变化"真的会影响他们使用的API部分吗?他们需要时间和精力来解决这个问题.将API功能设计为离散的语义服务将允许您创建路线图并以更易理解的方式对其进行版本化.

为了进一步阅读,我建议查看Martin Fowler关于微服务架构的着作:

简而言之,微服务架构风格是将单个应用程序开发为一套小型服务的方法,每个小型服务都在自己的流程中运行并与轻量级机制进行通信

虽然关于如何在实践中设计和构建"微服务"存在很多争论,但阅读这些内容应该有助于进一步塑造您对所面临的API设计决策的思考,并为您准备参与"当前"讨论做好准备话题.