在我尝试使用REST架构风格重新设计现有应用程序时,我遇到了一个问题,我想将其称为"Mediatype Explosion".但是,我不确定这是否真的是REST的问题或固有的好处.要解释我的意思,请参考以下示例
我们的应用程序的一小部分看起来像:
收集-collections-的 - >集合-的-物品─>项
即顶级是集合的集合,这些集合中的每一个都是项目的集合.
此外,每个项目都有8个属性,可以单独读取和写入.尝试将上述层次结构公开为RESTful资源会让我看到以下媒体类型:
application/vnd.mycompany.collection-of-collections+xml application/vnd.mycompany.collection-of-items+xml application/vnd.mycompany.item+xml
此外,由于每个项目具有8个可以单独读取和写入的属性,因此将产生另外8种媒体类型.例如,项目的"值"属性的一种这样的媒体类型将是:
application/vnd.mycompany.item_value+xml
正如我之前提到的,这只是我们应用程序的一小部分,我希望有几个不同的集合和项目需要以这种方式公开.
我的问题是:
我是否因为拥有大量媒体类型而做错了什么?
避免媒体类型爆炸的替代设计方法是什么?
我也知道上面的设计是高度精细的,特别是暴露项目的各个属性,并为每个属性分别设置媒体类型.然而,使其粗糙意味着我将最终通过线路传输不必要的数据,而实际上客户端只需要读取或写入项目的单个属性.你会如何处理这样的设计问题?
减少所需媒体类型数量的一种方法是使用定义的媒体类型来保存其他媒体类型的列表.这可以用于您的所有收藏.通常,列表往往具有一致的行为集.您可以滚动自己的vnd.mycompany.resourcelist,也可以重用Atom集合之类的东西.
关于vnd.mycompany.item等特定资源表示,您可以做的事情很大程度上取决于客户端的特征.它在浏览器中吗?你可以做代码下载吗?您的客户端是丰富的UI,还是数据处理客户端?
如果客户端要进行特定的数据处理,那么您几乎需要坚持使用精确的媒体类型,最终可能会有大量的媒体类型.但从好的方面来看,如果您使用SOAP,那么媒体类型将少于命名空间!
请记住,媒体类型是您的合同,如果您的应用程序需要与客户定义大量合同,那么就这样吧.
但是,我不会定义合同来交换单个属性值.如果您觉得有必要这样做,那么您在设计中做了其他错误.分布式界面设计需要进行粗略的对话,而不是繁琐的对话.
我想我终于从Ian Robinson的演讲中得到了我为上述问题所寻求的澄清,并认为我应该在这里分享.
最近,我在Jim Webber的博客文章中看到了" 帮助调整超媒体引擎,结构架构的媒体类型 "的声明.然后我发现了Thoughtworks 的Ian Robinson的演讲.这个演示文稿是我遇到的最好的演示文稿之一,它提供了对媒体类型和模式语言的角色和职责的非常清楚的理解(整个演示文稿是一种享受,我强烈建议所有人).特别要注意标题为"你已经选择了应用程序/ xml,你的第一个 "的幻灯片.和"自定义媒体类型".Ian清楚地解释了模式和媒体类型的不同角色.简而言之,这是我对Ian的介绍的看法:
媒体类型描述包括标识超媒体控件的处理模型,并定义适用于该类型资源的方法.识别超媒体控制意味着"我们如何识别链接?" 在XHTML中,链接是基于标记识别的,RDF具有不同的语义.媒体类型有助于识别的下一件事是什么方法适用于给定媒体类型的资源?一个很好的例子是ATOM(application/atom + xml)规范,它提供了对超媒体控件的非常丰富的描述; 他们告诉我们链接元素是如何定义的?以及当我们取消引用URI时我们可以期望能够做什么,因此它实际上讲述了我们可以期望能够应用于资源的方法.资源represenation的结构信息是NOT的一部分或NOT包含的媒体类型描述内,但被提供为即介质类型规范的实际表示的适当架构的一部分不一定会决定有关的表示的任何结构.
那么这对我们意味着什么呢?简单地说,我们不需要单独的媒体类型来描述每个资源,如上面我原来的问题所述.我们只需要一种媒体类型用于整个应用程序.这可能是一种全新的自定义媒体类型或自定义媒体类型,它可以重复使用现有的标准媒体类型,或者更好,只是一种标准媒体类型,可以在不改变我们的应用程序的情况下重复使用.
希望这可以帮助.
在我看来,这是REST概念的薄弱环节.作为一种架构和界面风格,REST非常出色,Roy F.和其他人所做的工作大大提升了现有技术水平.但是标准媒体类型可以传达(不仅仅是代表)的内容存在上限.
为了让人们理解和使用您的REST-ish API,他们需要了解数据的含义.有些媒体类型可以讲述大部分故事的API; 例如,如果你有一个文本到语音API,输入媒体类型是text/plain,输出媒体类型是audio/mp4,那么熟悉这个主题的人可能会做.文本输入,音频输出,可能足以在这种情况下继续.
但是,许多API无法仅通过媒体类型传达其意义.假设您有一个处理航空公司票务的API.输入和输出主要是数据.每个API的输入和输出上的媒体类型可以是application/json或application/xml,因此媒体类型不会传输大量信息.那么您将查看输入和输出中的各个字段.也许有一个叫"价格"的领域.这是美元还是便士?美元还是其他一些货币?我不知道如果没有(a)非常具有描述性的名称(如"price_pennies_in_usd")或(b)文档,用户将如何回答这些问题.更不用说格式约定了.是否提供带破折号的帐号,必须是全字母等字母.
当我们遇到客户端不需要对数据进行语义理解的情况时,这是一回事.这很好用.浏览器可以直观地呈现任何兼容文档,并与任何兼容资源进行交互这一事实非常棒.这基本上就是"媒体"用例.
但是当客户端(或实际上是客户端背后的开发人员/用户)需要理解数据的语义时,情况就完全不同了. 数据不是媒体.除了记录数据外,没有办法解释数据的所有真实含义和细微之处.这是"数据"用例.
REST的过度学术定义适用于媒体用例.它不起作用,需要补充非纯粹但有用的东西,如文档,用于其他用例.