REST媒体types爆炸

在尝试使用REST架构风格重新devise现有的应用程序时,我遇到了一个我想称为“Mediatype Explosion”的问题。 但是,我不确定这是否真的是REST的一个问题或固有的好处。 为了解释我的意思,以下面的例子

我们应用程序的一小部分如下所示:

收集-collections-的 – >集合-的-物品─>项

即顶层是一个集合的集合,这些集合中的每一个又是一个集合的项目。

另外,每个项目有8个属性可以单独读写。 试图公开上面的层次作为RESTful资源留给我以下媒体types:

application/vnd.mycompany.collection-of-collections+xml application/vnd.mycompany.collection-of-items+xml application/vnd.mycompany.item+xml 

而且,由于每个项目有8个属性可以单独读写,所以会导致另外8个媒体types。 例如,一个项目的“value”属性的这种媒体types将是:

 application/vnd.mycompany.item_value+xml 

正如我前面提到的,这只是我们应用程序的一小部分,我期望有几种不同的集合和项目需要以这种方式公开。

我的问题是:

  1. 我有这么多的媒体types做错了吗?
  2. 什么是避免媒体types爆炸的替代devise方法?

我也意识到,上面的devise是高度细化的,尤其是揭示项目的个别属性,并为他们分别有不同的媒体types。 然而,粗糙的意思是,当客户端实际上只需要读取或者写入一个项目的单个属性的时候,就会通过networking传输不必要的数据。 你将如何处理这样的devise问题?

减less所需媒体types数量的一种方法是使用定义为保存其他媒体types列表的媒体types。 这可以用于你的所有collections。 一般而言,列表往往具有一致的行为。 你可以推出你自己的vnd.mycompany.resourcelist,或者你可以重用Atom集合 。

关于像vnd.mycompany.item这样的具体资源表示,你可以做什么取决于你客户的特点。 它在浏览器中吗? 你可以做代码下载吗? 您的客户是一个丰富的用户界面,还是数据处理客户端?

如果客户端要做特定的数据处理,那么你几乎需要坚持精确的媒体types,最终你可能会得到大量的媒体。 但从好的一面来看,如果您使用的是SOAP,那么媒体types将比名称空间更less!

请记住,媒体types是你的合同,如果你的应用程序需要与客户定义大量的合同,那就这样吧。

但是,我不会去定义合同来交换单个属性值。 如果你觉得有必要这样做,那么你在devise中做了一些其他的错误。 分布式界面devise需要大块的对话,而不是健谈的对话。

我想我终于从伊恩·罗宾逊的陈述中得到了我所要求的澄清,并认为我应该在这里分享。

最近,我在Jim Webber的博客文章中看到了“ 帮助调整超媒体引擎的媒体types,架构模式 ”的说法。 然后我发现了Thoughttworks的Ian Robinson的这个演讲 。 这个演讲是我所见过的最好的演讲之一,它提供了对媒体types和模式语言的angular色和责任的一个非常清楚的理解(整个演讲是一种享受,我强烈build议所有人)。 特别注意标题为“您select了应用程序/ xml,您第二次”的幻灯片。 和“自定义媒体types”。 伊恩清楚地解释了模式和媒体types的不同angular色。 总之,这是我从伊恩的介绍中拿走的:

媒体types描述包括标识超媒体控件的处理模型,并定义适用于该types资源的方法。 识别超媒体控件意味着“我们如何识别链接?” 在XHTML中,链接是基于标签来标识的,RDF具有不同的语义。 媒体types帮助识别的下一件事是什么方法适用于给定媒体types的资源? ATOM(application / atom + xml)规范就是一个很好的例子,它提供了对超媒体控件的非常丰富的描述; 他们告诉我们如何定义链接元素? 以及当我们对URI进行解引用时我们可以期望能够做的事情,所以它实际上告诉了我们可以期望能够应用到资源的方法。 资源代表的结构信息不是媒体types描述的一部分或包含在媒体types描述中,而是作为实际表示的适当模式的一部分提供,即媒体types说明不一定指示关于该表示的结构的任何内容。

那么这对我们意味着什么呢? 简单地说,我们不需要一个单独的媒体types来描述每个资源,如上面在我原来的问题中所述。 我们只需要一个媒体types的整个应用程序。 这可能是一种全新的自定义媒体types,也可以是重用现有标准媒体types的自定义媒体types,也可以是更好的标准媒体types,可以在不改变应用的情况下重复使用。

希望这可以帮助。

在我看来,这是REST概念的薄弱环节。 作为一种build筑和界面风格,REST非常出色,Roy F.等人所做的工作大大提高了现有技术水平。 但是标准媒体types可以传递什么(不仅仅是表示)是有上限的。

为了让人们理解和使用REST-ish API,他们需要了解数据的含义 。 有媒体types讲述大部分故事的API; 例如,如果你有一个文本到语音API,input媒体types是文本/纯文本,输出媒体types是audio/ mp4,那么熟悉这个主题的人可能会做。 文本input,audio输出,可能足以继续在这种情况下。

但是,许多API只能通过媒体types传递很多意义。 假设您有一个处理航空公司票务的API。 input和输出将主要是数据。 每个API的input和输出的媒体types可以是application / json或application / xml,所以媒体types不会传输大量的信息。 那么你可以看看input和输出中的各个字段。 也许有一个叫“价格”的领域。 那是美元还是便士? 美元或其他一些货币? 我不知道用户如何回答这些问题,没有(a)非常具有描述性的名字,比如“price_pennies_in_usd”,或者(b)文档。 更不用说格式约定了。 是否提供有破折号的帐号,必须是全字母等等。 没有定义这些问题的标准媒体types。

当客户不需要对数据进行语义理解的情况下,这是一回事。 那效果很好。 浏览器可以直观地呈现任何兼容的文档,并与任何兼容的资源进行交互的事实是非常棒的。 这基本上是“媒体”用例。

但是,当客户端(或实际上,客户端后面的开发者/用户)需要理解数据的语义时,情况完全不同。 数据不是媒体 。 除了logging数据之外,没有任何方法可以解释数据的真实含义和微妙之处。 这是“数据”用例。

REST的过度学术定义在媒体用例中起作用。 它不起作用,需要补充非纯粹但有用的东西,如文档,用于其他用例。

您正在使用媒体types来传达应存储在表示本身中的数据的详细信息。 所以你可以只有一个媒体types,比如说“application / xml”,然后你的XMLperformanceforms如下:

 <collection-of-collections> <collection-of-items> <item> </item> <item> </item> </collection-of-items> <collection-of-items> <item> </item> <item> </item> </collection-of-items> </collection-of-collections> 

如果您担心发送太多数据,请将JSONreplace为XML。 另一种节省写入和读取字节的方法是使用gzip编码,这可以将事情减less约60-70%。 除非您有超高的性能需求,否则其中一种方法应该适合您。 (为了获得更好的性能,可以使用非常简洁的手工string,甚至可以使用自定义的二进制TCP / IP协议。

编辑您的一个担心是:

使[表示]粗糙的手段,我最终将传输不必要的数据通过networking,实际上客户端只需要读取或写入一个项目的单一属性

在任何Web服务中,发送消息都有相当多的开销(每个HTTP请求可能花费数百字节的起始行和请求标头,同样每个HTTP响应也是如此 )。 所以一般来说你想要更less的粒度表示。 所以你会写你的客户端来请求这些更大的表示,然后将它们caching在一些方便的内存数据结构中,在这里你的程序可以多次读取它们的数据(但是一定要遵守服务器设置的HTTP过期date)。 将数据写入服务器时,通常会将一更改结合到内存数据结构中,然后将更新作为单个HTTP PUT请求发送到服务器。

您应该获取Richardson和Ruby的RESTful Web服务的副本,这是一本关于如何deviseREST Web服务的非常出色的书,并且比我所能解释得更清楚。 如果您使用Java,我强烈build议使用RESTlet框架,它非常忠实地模拟REST概念。 Roy Fielding的USC论文定义了REST原则也可能有所帮助。

媒体types应该很less创造​​,应该投入时间来确保格式能够存活下来。

由于您依赖于xml,所以您无法创build一种媒体types,只要在一个源中描述了媒体types,就没有特别的理由。

select支持多个根元素的主机媒体types的ATOM不一定会带给你任何东西:在决定是否有足够的信息来处理请求之前,您仍然需要在特定操作的上下文中开始阅读消息。

所以我build议你可以愉快地有一个媒体types,由一个根元素表示,并使用模式语言来指定哪些元素可以被包含。

换句话说,像xsd这样的语言可以让你键入你的媒体types来支持多个根元素之一。 application / vnd.acme.humanresources + xml没有任何内在的错误,描述了一个xml文档,它既可以作为一个根元素,也可以作为一个根元素。

因此,为了回答你的问题,请尽可能less地创build媒体types,通过质疑媒体types的文档是否可以被开发人员理解和实现。

除非您打算注册这些媒体types,否则您应该select其中一种现有的MIMEtypes,而不是尝试构build自己的格式。 正如Jim所提到的, application / xml或text / xml或者application / json对于RESTdevise中的大部分内容都是有效的。

在回答达雷尔这里是罗伊的全职 。 你不是试图通过创build自己的MIMEtypes来定义types化的资源吗?

Suresh,为什么不是HTTP + POX Restful?