2010-10-05 76 views
63

我目前正在为现有的PHP应用程序设计API,为此我正在研究REST作为一种明智的架构方法。我应该如何处理RESTful API中的对象层次结构?

我相信我对关键概念有一个合理的把握,但我正在努力寻找解决了对象层次结构和REST的人。

这里的问题...

在[应用]业务对象的层次结构,我们有:

Users 
L which have one-to-many Channel objects 
L which have one-to-many Member objects 

在应用程序本身,我们使用延迟加载的方式来填充的阵列的用户对象这些对象根据需要。我相信OO术语这是对象聚合,但是我看到了各种命名不一致的情况,并且不关心开始一场关于精确命名约定的战争。

现在,请考虑我有一些松散耦合的对象,根据应用程序的需要,我可能会/可能不会填充这些对象。

从REST的角度来看,我试图确定该方法应该是什么。这是我目前的想法(只考虑GET暂时):

选项1 - 完全填充的对象:

GET api.example.com/user/{user_id} 

阅读用户对象(资源),并与所有返回的用户对象预先加载和编码的可能的Channel和Member对象(JSON或XML)。

优点:减少的对象的数目,没有对象层次的遍历需要
缺点:对象必须完全填充(昂贵的)

选项2 - 填充主对象和包括链接到其他对象资源:

GET api.example.com/user/{user_id} 

阅读用户对象(资源),并返回填充用户对象的用户数据和两个列表。

每个列表引用相应(子)资源即

api.example.com/channel/{channel_id} 
api.example.com/member/{member_id} 

我认为这是接近(或精确地)超媒体的影响 - 只要客户能得到其他资源,如果它想(我明智地标记他们)。

优点:客户可以选择加载下属或以其他方式,如REST资源的对象的更好的分离
缺点:获得二次资源

方案3需要进一步的行程 - 使递归检索

GET api.example.com/user/{user_id} 

阅读用户对象并包含指向子对象列表的链接即

api.example.com/user/{user_id}/channels 
api.example.com/user/{user_id}/members 

的/频道呼叫将在形式返回信道资源的列表(如上):

api.example.com/channel/{channel_id} 

优点:第一资源暴露到哪里得到subodinates但他们不是什么(更多RESTful?),不需要预先获得下属,下属列表生成器(/通道和/成员)提供接口(方法)使响应更像服务。
缺点:现在需要充分填充物三个电话

选项4 - (重新)考虑REST

我重新使用[现行]应用对象的层次结构,并试图对象设计将其应用于REST - 或者可能更直接地为其提供API接口。

也许REST对象层次结构应该是不同的,或者新的RESTful思想可能会暴露现有对象设计的局限性。

对上述任何想法都表示欢迎。

非常感谢

保罗

+0

在我搜索我也发现了这组文章,我发现非常有用的和可访问:http://www.infoq.com/minibooks/emag-03-2010-rest – paulkmoore 2010-10-06 10:18:38

+0

如果你正在寻找一个所有这些样式基于JSON的媒体类型,考虑商事:http://www.aminus.org/rbre/shoji/shoji-draft-02.txt – fumanchu 2010-10-06 17:45:46

回答

38

没有理由不将这些。

  • api.example.com/user/{user_id} - 返回用户表示
  • api.example.com/channel/{channel_id} - 返回信道表示
  • api.example.com/user/{user_id}/channels - 返回通道表示的
  • api.example.com/user/{user_id}/channel_list列表 - 返回通道ID列表(或链接到他们的充分陈述,使用上述链接)

如果有疑问,考虑如何将数据显示给用户没有“API”问题:用户需要索引页({user_id}/channel_list)和完整视图({user_id}/channels)。

一旦你有了这些,只需要支持JSON而不是HTML(作为表现形式),并且你有REST。

+1

伟大的方式把它。 – 2010-10-05 20:41:15

+0

皮埃特 - 非常感谢,这是非常有用的。我想澄清从人的角度来看穿过数据的观点。我的想法是,如果我提供的“下一个”资源列表,而不是一个“完全视图”我允许用户细读他们想要细读什么,因此提供的链接列表是“多”的RESTful(以HATEOS符合较好)。我可以理解,提供填充列表对于性能原因很有用。我知道这是有点用例相关的,但我不知道我会更好地保持接口简单(也许更慢)暂且? – paulkmoore 2010-10-06 10:14:06

+3

你如何创建这样的分层对象?例如假设我们有图书馆 - >书籍 - >章节 - >页面。现在有一种方法是创建一个庞大的库对象,但有什么选择?如果您先创建图书馆,先获取该图书,然后预订等。 – 2012-06-20 03:26:27

24

我可以给出的最好建议是尽量避免将REST API视为暴露对象。您创建的资源应该支持您需要的用例。如果必要的话,你可能会为所有三个选项创建资源:显然

api.example.com/completeuser/{id} 
api.example.com/linkeduser/{id} 
api.example.com/lightweightuser/{id} 

我的名字是有点愚蠢,但它其实并不重要,你叫他们什么。这个想法是,您可以使用REST API来以特定使用场景的最合理的方式呈现数据。如果有多个场景,请根据需要创建多个资源。我喜欢将我的资源更像UI模型而不是商业实体。

+0

达雷尔 - 感谢这 - 也非常有用。我怀疑我错过了对象映射周围的一些细微之处。我得出结论,虽然我可能会调用我现有的对象框架,但我需要仔细设计我的'资源视图'。谢谢。 – paulkmoore 2010-10-06 10:16:29

6

下面是几个小时我的结论搜索,并从这里开始应答输入:

在那里我有一个对象,它实际上是一个多部分对象,我需要把它看成一个单一的资源。因此,如果我获得对象,所有的子坐标都应该存在。这是必需的,以便资源可以缓存。如果我分开加载对象(并提供一个ETag图章),那么其他请求者可能会收到一个部分对象,当他们期望一个完整的对象时。 结束语 - 如果对象作为资源可用,则应完全填充对象。

相关对象关系应作为指向其他(主要)资源的链接。通过这种方式,可以通过遍历API来发现对象

另外,对于主应用程序站点而言有意义的对象层次结构可能不是您需要以RESTful方式执行的操作,而是更有可能揭示现有层次结构的问题。说了这些之后,API可能需要比以前设想更多的专用用例,并且可能需要专门的资源。

希望帮助别人

9

我会建议Restful Obects这是标准的暴露域模型的宁静

宁静的对象的想法是提供一个标准的,通用的RESTful接口的域对象模型,露出的表示其结构使用JSON并使用HTTP GET,POST,PUT和DELETE启用与域对象实例的交互。

根据标准,这些URI将是这样的:

  • api.example.com/object/user/31
  • api.example.com/object/user/31/properties/username
  • api.example.com/object/user/31/collections/channels
  • api.example.com/object/user/31/collections/members
  • api.example.com/object/user/31/actions/someFunction
  • api.example.com/object/user/31/actions/someFunction/invoke

还有其他资源

  • api.example.com/services
  • api.example。COM /域类型

该规范定义了几个主要表示:

  • 对象(其表示任何域对象或服务)
  • 列表(链接到其他对象)
  • 属性
  • 收集
  • 行动
  • 作用的结果(通常CONTA进不去为对象或列表,或者只是反馈消息)
  • ,也有少数次要的表示,如家,和用户

这是有趣的,因为你会看到,表示是完全的自我描述,如果需要,开放普通观众的可能性。

可替代地,所述表示可以直接由一个定制应用消耗。

相关问题